diff --git a/.astyleignore b/.astyleignore index 8583ce89ca..4d61963d44 100644 --- a/.astyleignore +++ b/.astyleignore @@ -3,16 +3,22 @@ cmsis features/cryptocell features/mbedtls features/lwipstack/lwip +features/lwipstack/lwip-sys rtos/TARGET_CORTEX/rtx4 -features/filesystem/littlefs/littlefs -features/filesystem/fat/ChaN +features/storage/filesystem/littlefs/littlefs/ +features/storage/filesystem/fat/ChaN +features/storage/FEATURE_STORAGE features/frameworks -features/FEATURE_BLE/targets +features/FEATURE_BLE features/unsupported/ -features/FEATURE_COMMON_PAL/ +features/netsocket/emac-drivers hal/storage_abstraction -FEATURE_NANOSTACK/coap-service -FEATURE_NANOSTACK/sal-stack-nanostack +TESTS/mbed_hal/trng/pithy +features/nanostack/coap-service +features/nanostack/sal-stack-nanostack rtos/TARGET_CORTEX/rtx5 +TESTS/mbed_hal/trng/pithy targets +components/802.15.4_RF +components/wifi tools diff --git a/.github/issue_template.md b/.github/issue_template.md index bb6b11d530..7d4f1e8407 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,5 +1,22 @@ + + ### Description - - -[ ] Question -[ ] Enhancement -[ ] Bug + [ ] Question + [ ] Enhancement + [ ] Bug diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f7e4d48c91..8a5faac289 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -20,5 +20,7 @@ [ ] Refactor [ ] Target update [ ] Functionality change + [ ] Docs update + [ ] Test update [ ] Breaking change diff --git a/.travis.yml b/.travis.yml index eae37104fc..66a04d825e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,15 +51,25 @@ matrix: # Print versions we use - doxygen --version before_script: + # Build doxygen + - > + (git clone --depth=1 --single-branch --branch Release_1_8_14 https://github.com/doxygen/doxygen; + cd doxygen; + mkdir build; + cd build; + cmake -G "Unix Makefiles" ..; + make; + sudo make install) # Create BUILD directory for tests - mkdir BUILD script: # Assert that the Doxygen build produced no warnings. # The strange command below asserts that the Doxygen command had an # output of zero length - - > - doxygen doxyfile_options 2>&1 | - tee BUILD/doxygen.out && [ ! -s BUILD/doxygen.out ] + - doxygen doxyfile_options 2>&1 + # Once Mbed OS has been fixed, enable the full test by replacing the top line with this: + # - ( ! doxygen doxyfile_options 2>&1 | grep . ) + # Assert that all binary libraries are named correctly # The strange command below asserts that there are exactly 0 libraries # that do not start with lib @@ -86,6 +96,7 @@ matrix: - arm-none-eabi-gcc --version - python --version + - pip list --verbose script: # Run local testing on tools - PYTHONPATH=. coverage run -a -m pytest tools/test @@ -132,10 +143,10 @@ matrix: # update status if we succeeded, compare with master if possible - | CURR=$(cat astyle-branch.out | grep Formatted | wc -l) - PREV=$(curl https://api.github.com/repos/$TRAVIS_REPO_SLUG/status/master \ + PREV=$(curl -u "$MBED_BOT" https://api.github.com/repos/$TRAVIS_REPO_SLUG/status/master \ | jq -re "select(.sha != \"$TRAVIS_COMMIT\") | .statuses[] | select(.context == \"travis-ci/$NAME\").description - | capture(\", (?[0-9]+) files\").warnings" \ + | capture(\", (?[0-9]+) files\").files" \ || echo 0) STATUSM="Passed, ${CURR} files" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 658983feee..701af04107 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,45 +1,5 @@ -# Description -This document is cheat sheet for everyone who wants to contribute to [ARMmbed/mbed-os](https://github.com/ARMmbed/mbed-os) GitHub repository at GitHub. -All changes in code base should originate from GitHub Issues and take advantage of existing GitHub flows. Goal is to attract contributors and allow them contribute to code and documentation at the same time. +# Contributing to Mbed OS -Guidelines from this document are created to help new and existing contributors understand process workflow and align to project rules before pull request is submitted. It explains how a participant should do things like format code, test fixes, and submit patches. +Mbed OS is an open-source, device software platform for the Internet of Things. Contributions are an important part of the platform, and our goal is to make it as simple as possible to become a contributor. -## Where to get more information? -You can read more on our [documentation page](https://docs.mbed.com/docs/mbed-os-handbook/en/latest/cont/contributing/). - -# How to contribute -We really appreciate your contributions! We are Open Source project and we need your help. We want to keep it as easy as possible to contribute changes that get things working in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. - -Before a pull request will be merged, the [mbed Contributor Agreement](http://developer.mbed.org/contributor_agreement/) must be signed. - -You can pick up existing [mbed-os GitHub Issue](https://github.com/ARMmbed/mbed-os/issues) and solve it or implement new feature you find important, attractive or just necessary. We will review your proposal via pull request mechanism, give you comments and merge your changes if we decide your contribution satisfy criteria such as quality. - -# Enhancements vs Bugs -Enhancements are: -* New features implementation. -* Code refactoring. -* Coding rules, coding styles improvements. -* Code comments improvement. -* Documentation work. - -Bugs are: -* Issues rose internally or externally by [ARMmbed/mbed-os](https://github.com/ARMmbed/mbed-os) users. -* Internally (within mbed team) created issues from Continuous Integration pipeline and build servers. -* Issues detected using automation tools such as compilers, sanitizers, static code analysis tools etc. - -# Gate Keeper role -Gate Keeper is a person responsible for GitHub process workflow execution and is responsible for repository / project code base. Gate Keeper is also responsible for code (pull request) quality stamp and approves or rejects code changes in project’s code base. - -Gate Keepers will review your pull request code, give you comments in pull request comment section and in the end if everything goes well merge your pull request to one of our branches (most probably default ```master``` branch). - -Please be patient, digest Gate Keeper's feedback and respond promptly :) - -# mbed SDK porting -* For more information regarding mbed SDK porting please refer to [mbed SDK porting](http://developer.mbed.org/handbook/mbed-SDK-porting) handbook. -* Before starting the mbed SDK porting, you might want to familiarize with the [mbed SDK library internals](http://developer.mbed.org/handbook/mbed-library-internals) first. - -# Glossary -* Gate Keeper – persons responsible for overall code-base quality of [ARMmbed/mbed-os](https://github.com/ARMmbed/mbed-os) project. -* Enhancement – New feature deployment, code refactoring actions or existing code improvements. -* Bugfix – Issues originated from GitHub Issues pool, raised internally within mbed classic team or issues from automated code validators like linters, static code analysis tools etc. -* Mbed classic – mbed SDK 2.0 located in GitHub at [ARMmbed/mbed-os](https://github.com/ARMmbed/mbed-os). +To encourage productive collaboration, as well as robust, consistent and maintainable code, we have a set of guidelines for [contributing to Mbed OS](https://os.mbed.com/docs/latest/reference/contributing.html). diff --git a/README.md b/README.md index 778ef47831..59d8fcc7e3 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,20 @@ Arm Mbed OS is an open source embedded operating system designed specifically for the "things" in the Internet of Things. It includes all the features you need to develop a connected product based on an Arm Cortex-M microcontroller, including security, connectivity, an RTOS and drivers for sensors and I/O devices. Mbed OS provides a platform that includes: -* Security foundations. -* Cloud management services. -* Drivers for sensors, I/O devices and connectivity. + +- Security foundations. +- Cloud management services. +- Drivers for sensors, I/O devices and connectivity. ## Release notes The [release notes](https://os.mbed.com/releases) detail the current release. You can also find information about previous versions. +## License and contributions + +The software is provided under [Apache-2.0 license](LICENSE). Contributions to this project are accepted under the same license. Please see [contributing.md](CONTRIBUTING.md) for more info. + +This project contains code from other projects. The original license text is included in those source files. They must comply with our [license guide](https://os.mbed.com/docs/latest/reference/license.html) + ## Getting started for developers We have a [developer website](https://os.mbed.com) for asking questions, engaging with others, finding information on boards and components, using an online IDE and compiler, reading the documentation and learning about what's new and what's coming next in Mbed OS. @@ -36,6 +43,7 @@ We also have a [contributing and publishing guide](https://os.mbed.com/contribut ## Documentation -For more information about Mbed OS, please see [our published documentation](https://os.mbed.com/docs/latest). It includes published Doxygen for our APIs, step-by-step tutorials, porting information and background reference materials about our architecture and tools. +For more information about Mbed OS, please see [our published documentation](https://os.mbed.com/docs/latest). It includes Doxygen for our APIs, step-by-step tutorials, porting information and background reference materials about our architecture and tools. + +To contribute to this documentation, please see the [mbed-os-5-docs repository](https://github.com/ARMmbed/mbed-os-5-docs). -To contribute to this documentation, please see the [mbed-os-5-docs repo](https://github.com/ARMmbed/mbed-os-5-docs). diff --git a/TESTS/host_tests/rtc_reset.py b/TESTS/host_tests/rtc_reset.py index abe1afd9c6..1ea8b373c3 100644 --- a/TESTS/host_tests/rtc_reset.py +++ b/TESTS/host_tests/rtc_reset.py @@ -29,7 +29,7 @@ class RtcResetTest(BaseHostTest): """ """Start of the RTC""" - START_TIME = 50000 + START_TIME = 1537789823 # GMT: Monday, 24 September 2018 11:50:23 START_TIME_TOLERANCE = 10 """Time to delay after sending reset""" DELAY_TIME = 5.0 diff --git a/TESTS/host_tests/system_reset.py b/TESTS/host_tests/system_reset.py index 7899e3783e..4093804213 100644 --- a/TESTS/host_tests/system_reset.py +++ b/TESTS/host_tests/system_reset.py @@ -36,9 +36,6 @@ class SystemResetTest(BaseHostTest): def __init__(self): super(SystemResetTest, self).__init__() self.reset = False - cycle_s = self.get_config_item('program_cycle_s') - self.program_cycle_s = cycle_s if cycle_s is not None else DEFAULT_CYCLE_PERIOD - self.test_steps_sequence = self.test_steps() # Advance the coroutine to it's first yield statement. self.test_steps_sequence.send(None) @@ -61,16 +58,18 @@ class SystemResetTest(BaseHostTest): """Reset the device and check the status """ system_reset = yield - self.reset = False + + wait_after_reset = self.get_config_item('forced_reset_timeout') + wait_after_reset = wait_after_reset if wait_after_reset is not None else DEFAULT_CYCLE_PERIOD + self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DUMMY) - time.sleep(self.program_cycle_s) + time.sleep(wait_after_reset) self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY) system_reset = yield - if self.reset == False: raise RuntimeError('Platform did not reset as expected.') # The sequence is correct -- test passed. - yield True \ No newline at end of file + yield True diff --git a/TESTS/lorawan/loraradio/main.cpp b/TESTS/lorawan/loraradio/main.cpp index 29ab638c79..325611ce92 100644 --- a/TESTS/lorawan/loraradio/main.cpp +++ b/TESTS/lorawan/loraradio/main.cpp @@ -38,6 +38,7 @@ using namespace utest::v1; +using namespace mbed; static LoRaRadio *radio = NULL; rtos::Semaphore event_sem(0); diff --git a/TESTS/mbed_drivers/crc/main.cpp b/TESTS/mbed_drivers/crc/main.cpp index 9fdaed1d07..bdb23c3d0b 100644 --- a/TESTS/mbed_drivers/crc/main.cpp +++ b/TESTS/mbed_drivers/crc/main.cpp @@ -130,7 +130,7 @@ void test_thread(void) char test[] = "123456789"; uint32_t crc; MbedCRC ct; - TEST_ASSERT_EQUAL(0, ct.compute((void *)test, strlen((const char*)test), &crc)); + TEST_ASSERT_EQUAL(0, ct.compute((void *)test, strlen((const char *)test), &crc)); TEST_ASSERT_EQUAL(0xCBF43926, crc); } diff --git a/TESTS/mbed_drivers/flashiap/main.cpp b/TESTS/mbed_drivers/flashiap/main.cpp index 6fecee4c79..be46362d55 100644 --- a/TESTS/mbed_drivers/flashiap/main.cpp +++ b/TESTS/mbed_drivers/flashiap/main.cpp @@ -55,9 +55,6 @@ void flashiap_program_test() TEST_ASSERT_TRUE(sector_size % page_size == 0); uint32_t prog_size = std::max(page_size, (uint32_t)8); uint8_t *data = new uint8_t[prog_size + 2]; - for (uint32_t i = 0; i < prog_size + 2; i++) { - data[i] = i; - } // the one before the last sector in the system uint32_t address = (flash_device.get_flash_start() + flash_device.get_flash_size()) - (sector_size); @@ -68,6 +65,20 @@ void flashiap_program_test() ret = flash_device.erase(address, sector_size); TEST_ASSERT_EQUAL_INT32(0, ret); + uint8_t erase_val = flash_device.get_erase_value(); + memset(data, erase_val, prog_size); + + uint8_t *data_flashed = new uint8_t[prog_size]; + for (uint32_t i = 0; i < sector_size / prog_size; i++) { + uint32_t page_addr = address + i * prog_size; + ret = flash_device.read(data_flashed, page_addr, prog_size); + TEST_ASSERT_EQUAL_INT32(0, ret); + TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, prog_size); + } + + for (uint32_t i = 0; i < prog_size + 2; i++) { + data[i] = i; + } for (uint32_t i = 0; i < sector_size / prog_size; i++) { uint32_t prog_addr = address + i * prog_size; @@ -75,7 +86,6 @@ void flashiap_program_test() TEST_ASSERT_EQUAL_INT32(0, ret); } - uint8_t *data_flashed = new uint8_t[prog_size]; for (uint32_t i = 0; i < sector_size / prog_size; i++) { uint32_t page_addr = address + i * prog_size; ret = flash_device.read(data_flashed, page_addr, prog_size); diff --git a/TESTS/mbed_drivers/lp_ticker/main.cpp b/TESTS/mbed_drivers/lp_ticker/main.cpp index ece4562f06..dd394c5c1a 100644 --- a/TESTS/mbed_drivers/lp_ticker/main.cpp +++ b/TESTS/mbed_drivers/lp_ticker/main.cpp @@ -79,7 +79,7 @@ void test_multi_ticker(void) ticker[i].attach_us(callback(increment_multi_counter), MULTI_TICKER_TIME_MS * 1000); } - Thread::wait(MULTI_TICKER_TIME_MS + extra_wait); + ThisThread::sleep_for(MULTI_TICKER_TIME_MS + extra_wait); TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter); for (int i = 0; i < TICKER_COUNT; i++) { @@ -95,7 +95,7 @@ void test_multi_ticker(void) ticker[i].attach_us(callback(increment_multi_counter), (MULTI_TICKER_TIME_MS + i) * 1000); } - Thread::wait(MULTI_TICKER_TIME_MS + TICKER_COUNT + extra_wait); + ThisThread::sleep_for(MULTI_TICKER_TIME_MS + TICKER_COUNT + extra_wait); TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter); for (int i = 0; i < TICKER_COUNT; i++) { diff --git a/TESTS/mbed_drivers/mem_trace/main.cpp b/TESTS/mbed_drivers/mem_trace/main.cpp index e2a53b6b49..9eac268444 100644 --- a/TESTS/mbed_drivers/mem_trace/main.cpp +++ b/TESTS/mbed_drivers/mem_trace/main.cpp @@ -24,8 +24,8 @@ #include #include -#if !MBED_MEM_TRACING_ENABLED - #error [NOT_SUPPORTED] test not supported +#ifndef MBED_MEM_TRACING_ENABLED +#error [NOT_SUPPORTED] test not supported #endif using utest::v1::Case; @@ -391,7 +391,7 @@ static void test_case_multithread_malloc_free() threads[i].start(callback(malloc_free, &threads_continue)); } - Thread::wait(wait_time_us); + ThisThread::sleep_for(wait_time_us); threads_continue = false; for (int i = 0; i < NUM_TEST_THREADS; i++) { diff --git a/TESTS/mbed_drivers/race_test/main.cpp b/TESTS/mbed_drivers/race_test/main.cpp index ca03daaaf4..059313e5ea 100644 --- a/TESTS/mbed_drivers/race_test/main.cpp +++ b/TESTS/mbed_drivers/race_test/main.cpp @@ -39,13 +39,13 @@ class TestClass { public: TestClass() { - Thread::wait(500); + ThisThread::sleep_for(500); instance_count++; } void do_something() { - Thread::wait(100); + ThisThread::sleep_for(100); } ~TestClass() @@ -83,7 +83,7 @@ void test_case_func_race() // Start start first thread t1.start(cb); // Start second thread while the first is inside the constructor - Thread::wait(250); + ThisThread::sleep_for(250); t2.start(cb); // Wait for the threads to finish @@ -105,7 +105,7 @@ void test_case_class_race() // Start start first thread t1.start(cb); // Start second thread while the first is inside the constructor - Thread::wait(250); + ThisThread::sleep_for(250); t2.start(cb); // Wait for the threads to finish diff --git a/TESTS/mbed_drivers/ticker/main.cpp b/TESTS/mbed_drivers/ticker/main.cpp index 04faac02ea..7a7fcb250b 100644 --- a/TESTS/mbed_drivers/ticker/main.cpp +++ b/TESTS/mbed_drivers/ticker/main.cpp @@ -195,7 +195,7 @@ void test_multi_ticker(void) ticker[i].attach_us(callback(increment_multi_counter), MULTI_TICKER_TIME_MS * 1000); } - Thread::wait(MULTI_TICKER_TIME_MS + extra_wait); + ThisThread::sleep_for(MULTI_TICKER_TIME_MS + extra_wait); TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter); for (int i = 0; i < TICKER_COUNT; i++) { @@ -211,7 +211,7 @@ void test_multi_ticker(void) ticker[i].attach_us(callback(increment_multi_counter), (MULTI_TICKER_TIME_MS + i) * 1000); } - Thread::wait(MULTI_TICKER_TIME_MS + TICKER_COUNT + extra_wait); + ThisThread::sleep_for(MULTI_TICKER_TIME_MS + TICKER_COUNT + extra_wait); TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter); for (int i = 0; i < TICKER_COUNT; i++) { diff --git a/TESTS/mbed_drivers/timeout/timeout_tests.h b/TESTS/mbed_drivers/timeout/timeout_tests.h index 4c1311d85d..1ff33375f5 100644 --- a/TESTS/mbed_drivers/timeout/timeout_tests.h +++ b/TESTS/mbed_drivers/timeout/timeout_tests.h @@ -177,7 +177,7 @@ void test_multiple(void) for (size_t i = 0; i < NUM_TIMEOUTS; i++) { timeouts[i].attach_callback(mbed::callback(cnt_callback, &callback_count), TEST_DELAY_US); } - Thread::wait(TEST_DELAY_MS + 2); + ThisThread::sleep_for(TEST_DELAY_MS + 2); TEST_ASSERT_EQUAL(NUM_TIMEOUTS, callback_count); } diff --git a/TESTS/mbed_hal/critical_section/critical_section_test.h b/TESTS/mbed_hal/critical_section/critical_section_test.h index 3a85684d98..4b0e5878ee 100644 --- a/TESTS/mbed_hal/critical_section/critical_section_test.h +++ b/TESTS/mbed_hal/critical_section/critical_section_test.h @@ -14,8 +14,11 @@ * limitations under the License. */ -/** \addtogroup hal_critical_tests +/** \addtogroup hal_critical * @{ + * \defgroup hal_critical_test Tests + * Tests definitions of the HAL Critical module. + * @{ */ #ifndef MBED_CRITICAL_SECTION_TEST_H @@ -45,7 +48,7 @@ template void test_critical_section(); - +/**@}*/ /**@}*/ #endif // MBED_CRITICAL_SECTION_TEST_H diff --git a/TESTS/mbed_hal/minimum_requirements/main.cpp b/TESTS/mbed_hal/minimum_requirements/main.cpp new file mode 100644 index 0000000000..ac8bdb0e6d --- /dev/null +++ b/TESTS/mbed_hal/minimum_requirements/main.cpp @@ -0,0 +1,72 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * 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. + */ + +#include "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" + +#include "mbed.h" + +using namespace utest::v1; + +/** + * This test is intended to gate devices that do not have enough RAM to run + * Mbed os. Devices passing this test should have enough RAM to run all + * other Mbed OS tests. + * + * If your device does not pass this test, then you should determine the + * cause of high memory usage and fix it. If you cannot free enough memory, + * then you should turn off Mbed OS support for this device. + */ + +#define MIN_HEAP_SIZE 2048 +#define MIN_DATA_SIZE 2048 + +volatile uint8_t test_buffer[MIN_DATA_SIZE]; + +static void minimum_heap_test() +{ + void *mem = malloc(MIN_HEAP_SIZE); + TEST_ASSERT_NOT_EQUAL(NULL, mem); + free(mem); +} + +static void minimum_data_test() +{ + // Use test buffer so it is not optimized away + for (int i = 0; i < MIN_DATA_SIZE; i++) { + test_buffer[i] = i & 0xFF; + } +} + + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(30, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Minimum heap test", minimum_heap_test), + Case("Minimum data test", minimum_data_test), +}; + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + Harness::run(specification); +} diff --git a/TESTS/mbed_hal/qspi/flash_configs/Freescale/K82F/flash_config.h b/TESTS/mbed_hal/qspi/flash_configs/Freescale/K82F/flash_config.h new file mode 100644 index 0000000000..d31af6b399 --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/Freescale/K82F/flash_config.h @@ -0,0 +1,118 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * 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. + */ +#ifndef MBED_QSPI_FLASH_CONFIG_H +#define MBED_QSPI_FLASH_CONFIG_H + +#include "../../MX25RXX35F_config.h" + +/* Fast mode not supported in MX25U3235F */ +#undef FAST_MODE_ENABLE +#undef FAST_MODE_DISABLE + +#ifdef QSPI_SECTOR_COUNT +#undef QSPI_SECTOR_COUNT +#define QSPI_SECTOR_COUNT 1024 // for MX25U3235F +#endif + +/* The values for MX25U3235F are different, specify this here */ +#undef QSPI_COMMON_MAX_FREQUENCY +#undef QSPI_WRSR_MAX_TIME +#undef QSPI_PAGE_PROG_MAX_TIME +#undef QSPI_ERASE_SECTOR_MAX_TIME +#undef QSPI_ERASE_BLOCK_32_MAX_TIME +#undef QSPI_ERASE_BLOCK_64_MAX_TIME + +/* Implementation of these macros are slightly different for MX25U3235F */ +#undef EXTENDED_SPI_ENABLE +#undef EXTENDED_SPI_DISABLE + +/* Max frequency for basic rw operation in MX25U3235F */ +#define QSPI_COMMON_MAX_FREQUENCY 54000000 + +/* WRSR operations max time [us] (datasheet max time + 15%) */ +#define QSPI_WRSR_MAX_TIME 46000 // 40ms + +/* Write operations max time [us] (datasheet max time + 15%) */ +#define QSPI_PAGE_PROG_MAX_TIME 3450 // 3ms + +/* erase operations max time [us] (datasheet max time + 15%) */ +#define QSPI_ERASE_SECTOR_MAX_TIME 230000 // 200 ms +#define QSPI_ERASE_BLOCK_32_MAX_TIME 1150000 // 1s +#define QSPI_ERASE_BLOCK_64_MAX_TIME 2300000 // 2s + +#define EXTENDED_SPI_ENABLE() \ + \ + const int32_t reg_size = QSPI_STATUS_REG_SIZE; \ + uint8_t reg_data[reg_size] = { 0 }; \ + \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + if (write_enable(qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + reg_data[0] = STATUS_BIT_QE; \ + if (write_register(QSPI_CMD_WRSR, reg_data, \ + reg_size, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + WAIT_FOR(WRSR_MAX_TIME, qspi); \ + \ + memset(reg_data, 0, QSPI_STATUS_REG_SIZE); \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + return ((reg_data[0] & STATUS_BIT_QE) != 0 ? \ + QSPI_STATUS_OK : QSPI_STATUS_ERROR) + + + +#define EXTENDED_SPI_DISABLE() \ + \ + const int32_t reg_size = QSPI_STATUS_REG_SIZE; \ + uint8_t reg_data[reg_size] = { 0 }; \ + \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + if (write_enable(qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + reg_data[0] &= ~(STATUS_BIT_QE); \ + \ + if (write_register(QSPI_CMD_WRSR, reg_data, \ + reg_size, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + WAIT_FOR(WRSR_MAX_TIME, qspi); \ + \ + reg_data[0] = 0; \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + return ((reg_data[0] & STATUS_BIT_QE) == 0 ? \ + QSPI_STATUS_OK : QSPI_STATUS_ERROR) + +#endif // MBED_QSPI_FLASH_CONFIG_H diff --git a/TESTS/mbed_hal/qspi/flash_configs/Freescale/KL82Z/flash_config.h b/TESTS/mbed_hal/qspi/flash_configs/Freescale/KL82Z/flash_config.h new file mode 100644 index 0000000000..9cbe04fabe --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/Freescale/KL82Z/flash_config.h @@ -0,0 +1,118 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * 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. + */ +#ifndef MBED_QSPI_FLASH_CONFIG_H +#define MBED_QSPI_FLASH_CONFIG_H + +#include "../../MX25RXX35F_config.h" + +/* Fast mode not supported in MX25L12845G */ +#undef FAST_MODE_ENABLE +#undef FAST_MODE_DISABLE + +#ifdef QSPI_SECTOR_COUNT +#undef QSPI_SECTOR_COUNT +#define QSPI_SECTOR_COUNT 4096 // for MX25L12845G +#endif + +/* The values for MX25U3235F are different, specify this here */ +#undef QSPI_COMMON_MAX_FREQUENCY +#undef QSPI_WRSR_MAX_TIME +#undef QSPI_PAGE_PROG_MAX_TIME +#undef QSPI_ERASE_SECTOR_MAX_TIME +#undef QSPI_ERASE_BLOCK_32_MAX_TIME +#undef QSPI_ERASE_BLOCK_64_MAX_TIME + +/* Implementation of these macros are slightly different for MX25L12845G */ +#undef EXTENDED_SPI_ENABLE +#undef EXTENDED_SPI_DISABLE + +/* Max frequency for basic rw operation based on max bus frequency of 24MHz */ +#define QSPI_COMMON_MAX_FREQUENCY 23000000 + +/* WRSR operations max time [us] (datasheet max time + 15%) */ +#define QSPI_WRSR_MAX_TIME 46000 // 40ms + +/* Write operations max time [us] (datasheet max time + 15%) */ +#define QSPI_PAGE_PROG_MAX_TIME 1000 // 0.75ms + +/* erase operations max time [us] (datasheet max time + 15%) */ +#define QSPI_ERASE_SECTOR_MAX_TIME 460000 // 400 ms +#define QSPI_ERASE_BLOCK_32_MAX_TIME 1150000 // 1s +#define QSPI_ERASE_BLOCK_64_MAX_TIME 2300000 // 2s + +#define EXTENDED_SPI_ENABLE() \ + \ + const int32_t reg_size = QSPI_STATUS_REG_SIZE; \ + uint8_t reg_data[reg_size] = { 0 }; \ + \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + if (write_enable(qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + reg_data[0] = STATUS_BIT_QE; \ + if (write_register(QSPI_CMD_WRSR, reg_data, \ + reg_size, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + WAIT_FOR(WRSR_MAX_TIME, qspi); \ + \ + memset(reg_data, 0, QSPI_STATUS_REG_SIZE); \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + return ((reg_data[0] & STATUS_BIT_QE) != 0 ? \ + QSPI_STATUS_OK : QSPI_STATUS_ERROR) + + + +#define EXTENDED_SPI_DISABLE() \ + \ + const int32_t reg_size = QSPI_STATUS_REG_SIZE; \ + uint8_t reg_data[reg_size] = { 0 }; \ + \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + if (write_enable(qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + reg_data[0] &= ~(STATUS_BIT_QE); \ + \ + if (write_register(QSPI_CMD_WRSR, reg_data, \ + reg_size, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + WAIT_FOR(WRSR_MAX_TIME, qspi); \ + \ + reg_data[0] = 0; \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + return ((reg_data[0] & STATUS_BIT_QE) == 0 ? \ + QSPI_STATUS_OK : QSPI_STATUS_ERROR) + +#endif // MBED_QSPI_FLASH_CONFIG_H diff --git a/TESTS/mbed_hal/qspi/flash_configs/flash_configs.h b/TESTS/mbed_hal/qspi/flash_configs/flash_configs.h index fc7cdfa303..fcf08b642e 100644 --- a/TESTS/mbed_hal/qspi/flash_configs/flash_configs.h +++ b/TESTS/mbed_hal/qspi/flash_configs/flash_configs.h @@ -25,6 +25,10 @@ #include "STM/DISCO_F413ZH/flash_config.h" #elif defined(TARGET_EFM32GG11_STK3701) #include "SiliconLabs/EFM32GG11_STK3701/flash_config.h" +#elif defined(TARGET_K82F) +#include "Freescale/K82F/flash_config.h" +#elif defined(TARGET_KL82Z) +#include "Freescale/KL82Z/flash_config.h" #endif #endif // MBED_FLASH_CONFIGS_H diff --git a/TESTS/mbed_hal/qspi/main.cpp b/TESTS/mbed_hal/qspi/main.cpp index 647f7cc467..b6f5d493cc 100644 --- a/TESTS/mbed_hal/qspi/main.cpp +++ b/TESTS/mbed_hal/qspi/main.cpp @@ -151,7 +151,7 @@ static void _qspi_write_read_test(Qspi &qspi, qspi_bus_width_t write_inst_width, TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); TEST_ASSERT_EQUAL(write_size, buf_len); - if(is_extended_mode(write_inst_width, write_addr_width, write_data_width)) { + if (is_extended_mode(write_inst_width, write_addr_width, write_data_width)) { // on some flash chips in extended-SPI mode, control commands works only in 1-1-1 mode // so switching back to 1-1-1 mode qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); @@ -195,7 +195,7 @@ static void _qspi_write_read_test(Qspi &qspi, qspi_bus_width_t write_inst_width, } qspi.cmd.set_dummy_cycles(0); - if(is_extended_mode(read_inst_width, read_addr_width, read_data_width)) { + if (is_extended_mode(read_inst_width, read_addr_width, read_data_width)) { // on some flash chips in extended-SPI mode, control commands works only in 1-1-1 mode // so switching back to 1-1-1 mode qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); diff --git a/TESTS/mbed_hal/qspi/qspi_test.h b/TESTS/mbed_hal/qspi/qspi_test.h index 9ab3076d74..ca9458ccc9 100644 --- a/TESTS/mbed_hal/qspi/qspi_test.h +++ b/TESTS/mbed_hal/qspi/qspi_test.h @@ -14,8 +14,11 @@ * limitations under the License. */ -/** \addtogroup hal_qspi_tests +/** \addtogroup hal_qspi * @{ + * \defgroup hal_qspi_tests Tests + * QSPI tests of the HAL. + * @{ */ #ifndef MBED_QSPI_TEST_H #define MBED_QSPI_TEST_H @@ -96,3 +99,4 @@ void qspi_write_read_test(void); #endif /** @}*/ +/** @}*/ diff --git a/TESTS/mbed_hal/qspi/qspi_test_utils.cpp b/TESTS/mbed_hal/qspi/qspi_test_utils.cpp index f1386534fb..306123ad3b 100644 --- a/TESTS/mbed_hal/qspi/qspi_test_utils.cpp +++ b/TESTS/mbed_hal/qspi/qspi_test_utils.cpp @@ -201,11 +201,11 @@ qspi_status_t erase(uint32_t erase_cmd, uint32_t flash_addr, Qspi &qspi) qspi_status_t mode_enable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width) { - if(is_extended_mode(inst_width, addr_width, data_width)) { + if (is_extended_mode(inst_width, addr_width, data_width)) { return extended_enable(qspi); - } else if(is_dual_mode(inst_width, addr_width, data_width)) { + } else if (is_dual_mode(inst_width, addr_width, data_width)) { return dual_enable(qspi); - } else if(is_quad_mode(inst_width, addr_width, data_width)) { + } else if (is_quad_mode(inst_width, addr_width, data_width)) { return quad_enable(qspi); } else { return QSPI_STATUS_OK; @@ -214,11 +214,11 @@ qspi_status_t mode_enable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_widt qspi_status_t mode_disable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width) { - if(is_extended_mode(inst_width, addr_width, data_width)) { + if (is_extended_mode(inst_width, addr_width, data_width)) { return extended_disable(qspi); - } else if(is_dual_mode(inst_width, addr_width, data_width)) { + } else if (is_dual_mode(inst_width, addr_width, data_width)) { return dual_disable(qspi); - } else if(is_quad_mode(inst_width, addr_width, data_width)) { + } else if (is_quad_mode(inst_width, addr_width, data_width)) { return quad_disable(qspi); } else { return QSPI_STATUS_OK; diff --git a/TESTS/mbed_hal/rtc_time/main.cpp b/TESTS/mbed_hal/rtc_time/main.cpp index fe06329677..c537b02fc6 100644 --- a/TESTS/mbed_hal/rtc_time/main.cpp +++ b/TESTS/mbed_hal/rtc_time/main.cpp @@ -25,8 +25,6 @@ using namespace utest::v1; -static rtc_leap_year_support_t rtc_leap_year_support; - /* Regular is_leap_year, see platform/mbed_mktime.c for the optimised version. */ bool is_leap_year(int year) { @@ -53,6 +51,7 @@ bool is_leap_year(int year) * When _rtc_is_leap_year() function is called. * Then _rtc_is_leap_year() returns true if given year is a leap year; false otherwise. */ +template void test_is_leap_year() { for (int i = 70; i <= LAST_VALID_YEAR; ++i) { @@ -79,31 +78,6 @@ typedef struct { bool result; } test_mk_time_struct; -/* Array which contains data to test boundary values for the RTC devices which handles correctly leap years in - * whole range (1970 - 2106). - * Expected range: the 1st of January 1970 at 00:00:00 (seconds: 0) to the 7th of February 2106 at 06:28:15 (seconds: UINT_MAX). - */ -test_mk_time_struct test_mk_time_arr_full[] = { - {{ 0, 0, 0, 1, 0, 70, 0, 0, 0 }, (time_t) 0, true}, // valid lower bound - the 1st of January 1970 at 00:00:00 - {{ 59, 59, 23, 31, 11, 59, 0, 0, 0 }, (time_t) 0, false }, // invalid lower bound - the 31st of December 1969 at 23:59:59 - - {{ 15, 28, 6, 7, 1, 206, 0, 0, 0 }, (time_t)(UINT_MAX), true }, // valid upper bound - the 7th of February 2106 at 06:28:15 - {{ 16, 28, 6, 7, 1, 206, 0, 0, 0 }, (time_t) 0, false }, // invalid upper bound - the 7th of February 2106 at 06:28:16 -}; - -/* Array which contains data to test boundary values for the RTC devices which does not handle correctly leap years in - * whole range (1970 - 2106). On this platforms we will be one day off after 28.02.2100 since 2100 year will be - * incorrectly treated as a leap year. - * Expected range: the 1st of January 1970 at 00:00:00 (seconds: 0) to the 6th of February 2106 at 06:28:15 (seconds: UINT_MAX). - */ -test_mk_time_struct test_mk_time_arr_partial[] = { - {{ 0, 0, 0, 1, 0, 70, 0, 0, 0 }, (time_t) 0, true}, // valid lower bound - the 1st of January 1970 at 00:00:00 - {{ 59, 59, 23, 31, 11, 59, 0, 0, 0 }, (time_t) 0, false }, // invalid lower bound - the 31st of December 1969 at 23:59:59 - - {{ 15, 28, 6, 6, 1, 206, 0, 0, 0 }, (time_t)(UINT_MAX), true }, // valid upper bound - the 6th of February 2106 at 06:28:15 - {{ 16, 28, 6, 6, 1, 206, 0, 0, 0 }, (time_t) 0, false }, // invalid upper bound - the 6th of February 2106 at 06:28:16 -}; - /* Test boundary values for _rtc_maketime(). * * Note: This test case is designed for both types of RTC devices: @@ -116,10 +90,36 @@ test_mk_time_struct test_mk_time_arr_partial[] = { * When _rtc_maketime() function is called to convert the calendar time into timestamp. * Then if given calendar time is valid function returns true and conversion result, otherwise returns false. */ +template void test_mk_time_boundary() { test_mk_time_struct *pTestCases; + /* Array which contains data to test boundary values for the RTC devices which handles correctly leap years in + * whole range (1970 - 2106). + * Expected range: the 1st of January 1970 at 00:00:00 (seconds: 0) to the 7th of February 2106 at 06:28:15 (seconds: UINT_MAX). + */ + test_mk_time_struct test_mk_time_arr_full[] = { + {{ 0, 0, 0, 1, 0, 70, 0, 0, 0 }, (time_t) 0, true}, // valid lower bound - the 1st of January 1970 at 00:00:00 + {{ 59, 59, 23, 31, 11, 59, 0, 0, 0 }, (time_t) 0, false }, // invalid lower bound - the 31st of December 1969 at 23:59:59 + + {{ 15, 28, 6, 7, 1, 206, 0, 0, 0 }, (time_t)(UINT_MAX), true }, // valid upper bound - the 7th of February 2106 at 06:28:15 + {{ 16, 28, 6, 7, 1, 206, 0, 0, 0 }, (time_t) 0, false }, // invalid upper bound - the 7th of February 2106 at 06:28:16 + }; + + /* Array which contains data to test boundary values for the RTC devices which does not handle correctly leap years in + * whole range (1970 - 2106). On this platforms we will be one day off after 28.02.2100 since 2100 year will be + * incorrectly treated as a leap year. + * Expected range: the 1st of January 1970 at 00:00:00 (seconds: 0) to the 6th of February 2106 at 06:28:15 (seconds: UINT_MAX). + */ + test_mk_time_struct test_mk_time_arr_partial[] = { + {{ 0, 0, 0, 1, 0, 70, 0, 0, 0 }, (time_t) 0, true}, // valid lower bound - the 1st of January 1970 at 00:00:00 + {{ 59, 59, 23, 31, 11, 59, 0, 0, 0 }, (time_t) 0, false }, // invalid lower bound - the 31st of December 1969 at 23:59:59 + + {{ 15, 28, 6, 6, 1, 206, 0, 0, 0 }, (time_t)(UINT_MAX), true }, // valid upper bound - the 6th of February 2106 at 06:28:15 + {{ 16, 28, 6, 6, 1, 206, 0, 0, 0 }, (time_t) 0, false }, // invalid upper bound - the 6th of February 2106 at 06:28:16 + }; + /* Select array with test cases. */ if (rtc_leap_year_support == RTC_FULL_LEAP_YEAR_SUPPORT) { pTestCases = test_mk_time_arr_full; @@ -169,33 +169,41 @@ void test_local_time_invalid_param() TEST_ASSERT_EQUAL(false, _rtc_localtime(1, NULL, RTC_4_YEAR_LEAP_YEAR_SUPPORT)); } -utest::v1::status_t teardown_handler_t(const Case *const source, const size_t passed, const size_t failed, - const failure_t reason) +/* Test set_time() function called a few seconds apart. + * + * Given is set_time() function. + * When set_time() is used to set the system time two times. + * Then if the value returned from time() is always correct return true, otherwise return false. + */ +#define NEW_TIME 15 +void test_set_time_twice() { - return greentea_case_teardown_handler(source, passed, failed, reason); -} + time_t current_time; -utest::v1::status_t full_leap_year_case_setup_handler_t(const Case *const source, const size_t index_of_case) -{ - rtc_leap_year_support = RTC_FULL_LEAP_YEAR_SUPPORT; + /* Set the time to NEW_TIME and check it */ + set_time(NEW_TIME); + current_time = time(NULL); + TEST_ASSERT_EQUAL (true, (current_time == NEW_TIME)); - return greentea_case_setup_handler(source, index_of_case); -} + /* Wait 2 seconds */ + wait_ms(2000); -utest::v1::status_t partial_leap_year_case_setup_handler_t(const Case *const source, const size_t index_of_case) -{ - rtc_leap_year_support = RTC_4_YEAR_LEAP_YEAR_SUPPORT; - - return greentea_case_setup_handler(source, index_of_case); + /* set the time to NEW_TIME again and check it */ + set_time(NEW_TIME); + current_time = time(NULL); + TEST_ASSERT_EQUAL (true, (current_time == NEW_TIME)); } Case cases[] = { - Case("test is leap year - RTC leap years full support", full_leap_year_case_setup_handler_t, test_is_leap_year, teardown_handler_t), - Case("test is leap year - RTC leap years partial support", partial_leap_year_case_setup_handler_t, test_is_leap_year, teardown_handler_t), - Case("test make time boundary values - RTC leap years full support", full_leap_year_case_setup_handler_t, test_mk_time_boundary, teardown_handler_t), - Case("test make time boundary values - RTC leap years partial support", partial_leap_year_case_setup_handler_t, test_mk_time_boundary, teardown_handler_t), - Case("test make time - invalid param", test_mk_time_invalid_param, teardown_handler_t), - Case("test local time - invalid param", test_local_time_invalid_param, teardown_handler_t), + Case("test is leap year - RTC leap years full support", test_is_leap_year), + Case("test is leap year - RTC leap years partial support", test_is_leap_year), + Case("test make time boundary values - RTC leap years full support", test_mk_time_boundary), + Case("test make time boundary values - RTC leap years partial support", test_mk_time_boundary), + Case("test make time - invalid param", test_mk_time_invalid_param), + Case("test local time - invalid param", test_local_time_invalid_param), +#if DEVICE_RTC || DEVICE_LPTICKER + Case("test set_time twice", test_set_time_twice), +#endif }; utest::v1::status_t greentea_test_setup(const size_t number_of_cases) diff --git a/TESTS/mbed_hal/sleep/main.cpp b/TESTS/mbed_hal/sleep/main.cpp index 46beb039b2..bfcee25c5d 100644 --- a/TESTS/mbed_hal/sleep/main.cpp +++ b/TESTS/mbed_hal/sleep/main.cpp @@ -25,28 +25,13 @@ #include "greentea-client/test_env.h" #include "mbed_lp_ticker_wrapper.h" +#include "sleep_test_utils.h" #include "sleep_api_tests.h" -#define US_PER_S 1000000 - -/* Flush serial buffer before deep sleep - * - * Since deepsleep() may shut down the UART peripheral, we wait for some time - * to allow for hardware serial buffers to completely flush. - * - * Take NUMAKER_PFM_NUC472 as an example: - * Its UART peripheral has 16-byte Tx FIFO. With baud rate set to 9600, flush - * Tx FIFO would take: 16 * 8 * 1000 / 9600 = 13.3 (ms). So set wait time to - * 20ms here for safe. - * - * This should be replaced with a better function that checks if the - * hardware buffers are empty. However, such an API does not exist now, - * so we'll use the busy_wait_ms() function for now. - */ -#define SERIAL_FLUSH_TIME_MS 20 - using namespace utest::v1; +static char info[512] = {0}; + /* The following ticker frequencies are possible: * high frequency ticker: 250 KHz (1 tick per 4 us) - 8 Mhz (1 tick per 1/8 us) * low power ticker: 8 KHz (1 tick per 125 us) - 64 KHz (1 tick per ~15.6 us) @@ -65,71 +50,6 @@ static const uint32_t sleep_mode_delta_us = (10 + 4 + 5); * delta = default 10 ms + worst ticker resolution + extra time for code execution */ static const uint32_t deepsleep_mode_delta_us = (10000 + 125 + 5); -unsigned int ticks_to_us(unsigned int ticks, unsigned int freq) -{ - return (unsigned int)((unsigned long long) ticks * US_PER_S / freq); -} - -unsigned int us_to_ticks(unsigned int us, unsigned int freq) -{ - return (unsigned int)((unsigned long long) us * freq / US_PER_S); -} - -unsigned int overflow_protect(unsigned int timestamp, unsigned int ticker_width) -{ - unsigned int counter_mask = ((1 << ticker_width) - 1); - - return (timestamp & counter_mask); -} - -bool compare_timestamps(unsigned int delta_ticks, unsigned int ticker_width, unsigned int expected, unsigned int actual) -{ - const unsigned int counter_mask = ((1 << ticker_width) - 1); - - const unsigned int lower_bound = ((expected - delta_ticks) & counter_mask); - const unsigned int upper_bound = ((expected + delta_ticks) & counter_mask); - - if (lower_bound < upper_bound) { - if (actual >= lower_bound && actual <= upper_bound) { - return true; - } else { - return false; - } - } else { - if ((actual >= lower_bound && actual <= counter_mask) || (actual >= 0 && actual <= upper_bound)) { - return true; - } else { - return false; - } - } -} - -void busy_wait_ms(int ms) -{ - const ticker_info_t *info = us_ticker_get_info(); - uint32_t mask = (1 << info->bits) - 1; - int delay = (int)((uint64_t)ms * info->frequency / 1000); - - uint32_t prev = us_ticker_read(); - while (delay > 0) { - uint32_t next = us_ticker_read(); - delay -= (next - prev) & mask; - prev = next; - } -} - -void us_ticker_isr(const ticker_data_t *const ticker_data) -{ - us_ticker_clear_interrupt(); -} - -#ifdef DEVICE_LPTICKER -void lp_ticker_isr(const ticker_data_t *const ticker_data) -{ - lp_ticker_clear_interrupt(); -} -#endif - /* Test that wake-up time from sleep should be less than 10 us and * high frequency ticker interrupt can wake-up target from sleep. */ void sleep_usticker_test() @@ -140,6 +60,11 @@ void sleep_usticker_test() const ticker_irq_handler_type us_ticker_irq_handler_org = set_us_ticker_irq_handler(us_ticker_isr); + /* Give some time Green Tea to finish UART transmission before entering + * sleep mode. + */ + busy_wait_ms(SERIAL_FLUSH_TIME_MS); + /* Test only sleep functionality. */ sleep_manager_lock_deep_sleep(); TEST_ASSERT_FALSE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should be locked"); @@ -147,7 +72,8 @@ void sleep_usticker_test() /* Testing wake-up time 10 us. */ for (timestamp_t i = 100; i < 1000; i += 100) { /* note: us_ticker_read() operates on ticks. */ - const timestamp_t next_match_timestamp = overflow_protect(us_ticker_read() + us_to_ticks(i, ticker_freq), + const timestamp_t start_timestamp = us_ticker_read(); + const timestamp_t next_match_timestamp = overflow_protect(start_timestamp + us_to_ticks(i, ticker_freq), ticker_width); us_ticker_set_interrupt(next_match_timestamp); @@ -156,9 +82,11 @@ void sleep_usticker_test() const unsigned int wakeup_timestamp = us_ticker_read(); - TEST_ASSERT( - compare_timestamps(us_to_ticks(sleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp, - wakeup_timestamp)); + sprintf(info, "Delta ticks: %u, Ticker width: %u, Expected wake up tick: %d, Actual wake up tick: %d, delay ticks: %d, wake up after ticks: %d", + us_to_ticks(sleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp, wakeup_timestamp, us_to_ticks(i, ticker_freq), wakeup_timestamp - start_timestamp); + + TEST_ASSERT_MESSAGE(compare_timestamps(us_to_ticks(sleep_mode_delta_us, ticker_freq), + ticker_width, next_match_timestamp, wakeup_timestamp), info); } set_us_ticker_irq_handler(us_ticker_irq_handler_org); @@ -189,7 +117,8 @@ void deepsleep_lpticker_test() /* Testing wake-up time 10 ms. */ for (timestamp_t i = 20000; i < 200000; i += 20000) { /* note: lp_ticker_read() operates on ticks. */ - const timestamp_t next_match_timestamp = overflow_protect(lp_ticker_read() + us_to_ticks(i, ticker_freq), ticker_width); + const timestamp_t start_timestamp = lp_ticker_read(); + const timestamp_t next_match_timestamp = overflow_protect(start_timestamp + us_to_ticks(i, ticker_freq), ticker_width); lp_ticker_set_interrupt(next_match_timestamp); @@ -197,7 +126,11 @@ void deepsleep_lpticker_test() const timestamp_t wakeup_timestamp = lp_ticker_read(); - TEST_ASSERT(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp, wakeup_timestamp)); + sprintf(info, "Delta ticks: %u, Ticker width: %u, Expected wake up tick: %d, Actual wake up tick: %d, delay ticks: %d, wake up after ticks: %d", + us_to_ticks(deepsleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp, wakeup_timestamp, us_to_ticks(i, ticker_freq), wakeup_timestamp - start_timestamp); + + TEST_ASSERT_MESSAGE(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, ticker_freq), ticker_width, + next_match_timestamp, wakeup_timestamp), info); } set_lp_ticker_irq_handler(lp_ticker_irq_handler_org); @@ -240,8 +173,12 @@ void deepsleep_high_speed_clocks_turned_off_test() TEST_ASSERT_UINT32_WITHIN(1000, 0, ticks_to_us(us_ticks_diff, us_ticker_freq)); + sprintf(info, "Delta ticks: %u, Ticker width: %u, Expected wake up tick: %d, Actual wake up tick: %d", + us_to_ticks(deepsleep_mode_delta_us, lp_ticker_freq), lp_ticker_width, wakeup_time, lp_ticks_after_sleep); + /* Check if we have woken-up after expected time. */ - TEST_ASSERT(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, lp_ticker_freq), lp_ticker_width, wakeup_time, lp_ticks_after_sleep)); + TEST_ASSERT_MESSAGE(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, lp_ticker_freq), lp_ticker_width, + wakeup_time, lp_ticks_after_sleep), info); } #endif diff --git a/TESTS/mbed_hal/sleep/sleep_test_utils.h b/TESTS/mbed_hal/sleep/sleep_test_utils.h new file mode 100644 index 0000000000..b619a09bc3 --- /dev/null +++ b/TESTS/mbed_hal/sleep/sleep_test_utils.h @@ -0,0 +1,118 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * 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. + */ + +/** + * @addtogroup hal_sleep + * @{ + * @defgroup hal_sleep_test_util Tests + * Tests of the sleep HAL. + * @{ + */ + +#ifndef MBED_SLEEP_TEST_UTILS_H +#define MBED_SLEEP_TEST_UTILS_H + +#include "hal/ticker_api.h" +#include "hal/us_ticker_api.h" +#include "hal/lp_ticker_api.h" + +/* Flush serial buffer before deep sleep + * + * Since deepsleep() may shut down the UART peripheral, we wait for some time + * to allow for hardware serial buffers to completely flush. + * + * Take NUMAKER_PFM_NUC472 as an example: + * Its UART peripheral has 16-byte Tx FIFO. With baud rate set to 9600, flush + * Tx FIFO would take: 16 * 8 * 1000 / 9600 = 13.3 (ms). So set wait time to + * 20ms here for safe. + * + * This should be replaced with a better function that checks if the + * hardware buffers are empty. However, such an API does not exist now, + * so we'll use the busy_wait_ms() function for now. + */ +#define SERIAL_FLUSH_TIME_MS 20 + +#define US_PER_S 1000000 + +unsigned int ticks_to_us(unsigned int ticks, unsigned int freq) +{ + return (unsigned int)((unsigned long long) ticks * US_PER_S / freq); +} + +unsigned int us_to_ticks(unsigned int us, unsigned int freq) +{ + return (unsigned int)((unsigned long long) us * freq / US_PER_S); +} + +unsigned int overflow_protect(unsigned int timestamp, unsigned int ticker_width) +{ + unsigned int counter_mask = ((1 << ticker_width) - 1); + + return (timestamp & counter_mask); +} + +bool compare_timestamps(unsigned int delta_ticks, unsigned int ticker_width, unsigned int expected, unsigned int actual) +{ + const unsigned int counter_mask = ((1 << ticker_width) - 1); + + const unsigned int lower_bound = ((expected - delta_ticks) & counter_mask); + const unsigned int upper_bound = ((expected + delta_ticks) & counter_mask); + + if (lower_bound < upper_bound) { + if (actual >= lower_bound && actual <= upper_bound) { + return true; + } else { + return false; + } + } else { + if ((actual >= lower_bound && actual <= counter_mask) || (actual >= 0 && actual <= upper_bound)) { + return true; + } else { + return false; + } + } +} + +void busy_wait_ms(int ms) +{ + const ticker_info_t *info = us_ticker_get_info(); + uint32_t mask = (1 << info->bits) - 1; + int delay = (int)((uint64_t) ms * info->frequency / 1000); + + uint32_t prev = us_ticker_read(); + while (delay > 0) { + uint32_t next = us_ticker_read(); + delay -= (next - prev) & mask; + prev = next; + } +} + +void us_ticker_isr(const ticker_data_t *const ticker_data) +{ + us_ticker_clear_interrupt(); +} + +#ifdef DEVICE_LPTICKER +void lp_ticker_isr(const ticker_data_t *const ticker_data) +{ + lp_ticker_clear_interrupt(); +} +#endif + +#endif + +/** @}*/ +/** @}*/ diff --git a/TESTS/mbed_hal/sleep_manager/main.cpp b/TESTS/mbed_hal/sleep_manager/main.cpp index 3d3e392b50..324139b4fd 100644 --- a/TESTS/mbed_hal/sleep_manager/main.cpp +++ b/TESTS/mbed_hal/sleep_manager/main.cpp @@ -16,46 +16,238 @@ #include "utest/utest.h" #include "unity/unity.h" #include "greentea-client/test_env.h" +#include +#include "mbed.h" +#include "mbed_lp_ticker_wrapper.h" +#include "../sleep/sleep_test_utils.h" +#include "sleep_manager_api_tests.h" #if !DEVICE_SLEEP #error [NOT_SUPPORTED] test not supported #endif -using namespace utest::v1; +#define SLEEP_DURATION_US 20000ULL +#define DEEP_SLEEP_TEST_CHECK_WAIT_US 2000 +#define DEEP_SLEEP_TEST_CHECK_WAIT_DELTA_US 500 -void sleep_manager_deepsleep_counter_test() +using utest::v1::Case; +using utest::v1::Specification; +using utest::v1::Harness; + +void test_lock_unlock() { - bool deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check(); - TEST_ASSERT_TRUE(deep_sleep_allowed); + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep()); sleep_manager_lock_deep_sleep(); - deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check(); - TEST_ASSERT_FALSE(deep_sleep_allowed); + TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep()); sleep_manager_unlock_deep_sleep(); - deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check(); - TEST_ASSERT_TRUE(deep_sleep_allowed); + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep()); } -utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) +void test_lock_eq_ushrt_max() { - greentea_case_failure_abort_handler(source, reason); - return STATUS_CONTINUE; + uint32_t lock_count = 0; + while (lock_count < USHRT_MAX) { + sleep_manager_lock_deep_sleep(); + lock_count++; + TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep()); + } + while (lock_count > 1) { + sleep_manager_unlock_deep_sleep(); + lock_count--; + TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep()); + } + sleep_manager_unlock_deep_sleep(); + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep()); } -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +#if DEVICE_LPTICKER +#if DEVICE_USTICKER +utest::v1::status_t testcase_setup(const Case *const source, const size_t index_of_case) { - GREENTEA_SETUP(20, "default_auto"); - return greentea_test_setup_handler(number_of_cases); + // Suspend the RTOS kernel scheduler to prevent interference with duration of sleep. + osKernelSuspend(); +#if DEVICE_LPTICKER + ticker_suspend(get_lp_ticker_data()); +#if (LPTICKER_DELAY_TICKS > 0) + // Suspend the low power ticker wrapper to prevent interference with deep sleep lock. + lp_ticker_wrapper_suspend(); +#endif +#endif + ticker_suspend(get_us_ticker_data()); + // Make sure HAL tickers are initialized. + us_ticker_init(); +#if DEVICE_LPTICKER + lp_ticker_init(); +#endif + return utest::v1::greentea_case_setup_handler(source, index_of_case); +} + +utest::v1::status_t testcase_teardown(const Case *const source, const size_t passed, const size_t failed, + const utest::v1::failure_t failure) +{ + ticker_resume(get_us_ticker_data()); +#if DEVICE_LPTICKER +#if (LPTICKER_DELAY_TICKS > 0) + lp_ticker_wrapper_resume(); +#endif + ticker_resume(get_lp_ticker_data()); +#endif + osKernelResume(0); + return utest::v1::greentea_case_teardown_handler(source, passed, failed, failure); +} + +/* This test is based on the fact that the high-speed clocks are turned off + * in deep sleep mode but remain on in the ordinary sleep mode. Low-speed + * clocks stay on for both sleep and deep sleep modes. + * + * The type of sleep that was actually used by sleep_manager_sleep_auto() + * can be detected by comparing times measured by us and lp tickers. + */ +void test_sleep_auto() +{ + const ticker_info_t *us_ticker_info = get_us_ticker_data()->interface->get_info(); + const unsigned us_ticker_mask = ((1 << us_ticker_info->bits) - 1); + const ticker_irq_handler_type us_ticker_irq_handler_org = set_us_ticker_irq_handler(us_ticker_isr); + const ticker_info_t *lp_ticker_info = get_lp_ticker_data()->interface->get_info(); + const unsigned lp_ticker_mask = ((1 << lp_ticker_info->bits) - 1); + const ticker_irq_handler_type lp_ticker_irq_handler_org = set_lp_ticker_irq_handler(lp_ticker_isr); + us_timestamp_t us_ts1, us_ts2, lp_ts1, lp_ts2, us_diff1, us_diff2, lp_diff1, lp_diff2; + + sleep_manager_lock_deep_sleep(); + uint32_t lp_wakeup_ts_raw = lp_ticker_read() + us_to_ticks(SLEEP_DURATION_US, lp_ticker_info->frequency); + timestamp_t lp_wakeup_ts = overflow_protect(lp_wakeup_ts_raw, lp_ticker_info->bits); + lp_ticker_set_interrupt(lp_wakeup_ts); + us_ts1 = ticks_to_us(us_ticker_read(), us_ticker_info->frequency); + lp_ts1 = ticks_to_us(lp_ticker_read(), lp_ticker_info->frequency); + + sleep_manager_sleep_auto(); + us_ts2 = ticks_to_us(us_ticker_read(), us_ticker_info->frequency); + us_diff1 = (us_ts1 <= us_ts2) ? (us_ts2 - us_ts1) : (us_ticker_mask - us_ts1 + us_ts2 + 1); + lp_ts2 = ticks_to_us(lp_ticker_read(), lp_ticker_info->frequency); + lp_diff1 = (lp_ts1 <= lp_ts2) ? (lp_ts2 - lp_ts1) : (lp_ticker_mask - lp_ts1 + lp_ts2 + 1); + + // Deep sleep locked -- ordinary sleep mode used: + // * us_ticker powered ON, + // * lp_ticker powered ON, + // so both should increment equally. + + // Verify us and lp tickers incremented equally, with 10% tolerance. + TEST_ASSERT_UINT64_WITHIN_MESSAGE( + SLEEP_DURATION_US / 10ULL, lp_diff1, us_diff1, + "Deep sleep mode locked, but still used"); + + sleep_manager_unlock_deep_sleep(); + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep()); + + // Wait for hardware serial buffers to flush. + busy_wait_ms(SERIAL_FLUSH_TIME_MS); + + lp_wakeup_ts_raw = lp_ticker_read() + us_to_ticks(SLEEP_DURATION_US, lp_ticker_info->frequency); + lp_wakeup_ts = overflow_protect(lp_wakeup_ts_raw, lp_ticker_info->bits); + lp_ticker_set_interrupt(lp_wakeup_ts); + us_ts1 = ticks_to_us(us_ticker_read(), us_ticker_info->frequency); + lp_ts1 = ticks_to_us(lp_ticker_read(), lp_ticker_info->frequency); + + sleep_manager_sleep_auto(); + us_ts2 = ticks_to_us(us_ticker_read(), us_ticker_info->frequency); + us_diff2 = (us_ts1 <= us_ts2) ? (us_ts2 - us_ts1) : (us_ticker_mask - us_ts1 + us_ts2 + 1); + lp_ts2 = ticks_to_us(lp_ticker_read(), lp_ticker_info->frequency); + lp_diff2 = (lp_ts1 <= lp_ts2) ? (lp_ts2 - lp_ts1) : (lp_ticker_mask - lp_ts1 + lp_ts2 + 1); + + // Deep sleep unlocked -- deep sleep mode used: + // * us_ticker powered OFF, + // * lp_ticker powered ON. + // The us_ticker increment represents only the code execution time + // and should be much shorter than both: + // 1. current lp_ticker increment, + // 2. previous us_ticker increment (locked sleep test above) + + // Verify that the current us_ticker increment: + // 1. is at most 10% of lp_ticker increment + // 2. is at most 10% of previous us_ticker increment. + TEST_ASSERT_MESSAGE(us_diff2 < lp_diff2 / 10ULL, "Deep sleep mode unlocked, but not used"); + TEST_ASSERT_MESSAGE(us_diff2 < us_diff1 / 10ULL, "Deep sleep mode unlocked, but not used"); + + set_us_ticker_irq_handler(us_ticker_irq_handler_org); + set_lp_ticker_irq_handler(lp_ticker_irq_handler_org); +} +#endif + +void test_lock_unlock_test_check() +{ + // Make sure HAL tickers are initialized. + ticker_read(get_us_ticker_data()); + ticker_read(get_lp_ticker_data()); + + // Use LowPowerTimer instead of Timer to prevent deep sleep lock. + LowPowerTimer lp_timer; + us_timestamp_t exec_time_unlocked, exec_time_locked; + LowPowerTimeout lp_timeout; + + // Deep sleep unlocked: + // * sleep_manager_can_deep_sleep() returns true, + // * sleep_manager_can_deep_sleep_test_check() returns true instantly. + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep()); + lp_timer.start(); + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep_test_check()); + lp_timer.stop(); + exec_time_unlocked = lp_timer.read_high_resolution_us(); + + // Deep sleep locked: + // * sleep_manager_can_deep_sleep() returns false, + // * sleep_manager_can_deep_sleep_test_check() returns false with 2 ms delay. + sleep_manager_lock_deep_sleep(); + TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep()); + lp_timer.reset(); + lp_timer.start(); + TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep_test_check()); + lp_timer.stop(); + exec_time_locked = lp_timer.read_high_resolution_us(); + TEST_ASSERT_UINT64_WITHIN(DEEP_SLEEP_TEST_CHECK_WAIT_DELTA_US, DEEP_SLEEP_TEST_CHECK_WAIT_US, + exec_time_locked - exec_time_unlocked); + + // Deep sleep unlocked with a 1 ms delay: + // * sleep_manager_can_deep_sleep() returns false, + // * sleep_manager_can_deep_sleep_test_check() returns true with a 1 ms delay, + // * sleep_manager_can_deep_sleep() returns true when checked again. + lp_timer.reset(); + lp_timeout.attach_us(mbed::callback(sleep_manager_unlock_deep_sleep_internal), + DEEP_SLEEP_TEST_CHECK_WAIT_US / 2); + lp_timer.start(); + TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep()); + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep_test_check()); + lp_timer.stop(); + TEST_ASSERT_UINT64_WITHIN(DEEP_SLEEP_TEST_CHECK_WAIT_DELTA_US, DEEP_SLEEP_TEST_CHECK_WAIT_US / 2, + lp_timer.read_high_resolution_us()); + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep()); +} +#endif + +utest::v1::status_t testsuite_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(10, "default_auto"); + return utest::v1::greentea_test_setup_handler(number_of_cases); } Case cases[] = { - Case("sleep manager - deep sleep counter", sleep_manager_deepsleep_counter_test, greentea_failure_handler), + Case("deep sleep lock/unlock", test_lock_unlock), + Case("deep sleep locked USHRT_MAX times", test_lock_eq_ushrt_max), +#if DEVICE_LPTICKER +#if DEVICE_USTICKER + Case("sleep_auto calls sleep/deep sleep based on lock", + (utest::v1::case_setup_handler_t) testcase_setup, + test_sleep_auto, + (utest::v1::case_teardown_handler_t) testcase_teardown), +#endif + Case("deep sleep lock/unlock test_check", test_lock_unlock_test_check), +#endif }; -Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); +Specification specification(testsuite_setup, cases); int main() { - Harness::run(specification); + return !Harness::run(specification); } diff --git a/TESTS/mbed_hal/sleep_manager/sleep_manager_api_tests.h b/TESTS/mbed_hal/sleep_manager/sleep_manager_api_tests.h new file mode 100644 index 0000000000..6dce0efadd --- /dev/null +++ b/TESTS/mbed_hal/sleep_manager/sleep_manager_api_tests.h @@ -0,0 +1,86 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * 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. + */ + +/** + * @addtogroup hal_sleep_manager_tests + * @{ + */ + +#ifndef MBED_HAL_SLEEP_MANAGER_API_TESTS_H +#define MBED_HAL_SLEEP_MANAGER_API_TESTS_H + +#if DEVICE_SLEEP + +/** Test lock/unlock + * + * Given no prior calls to lock/unlock + * When the deep sleep status is checked + * Then the deep sleep is allowed + * + * When the lock function is called + * Then the deep sleep is not allowed + * + * When the unlock function is called + * Then the deep sleep is allowed again + */ +void test_lock_unlock(); + +/** Test lock USHRT_MAX times + * + * Given a device with sleep mode support + * When deep sleep mode is locked USHRT_MAX times + * Then the deep sleep mode is locked + * + * When unlock is called repeatedly + * Then deep sleep mode stays locked until the number + * of unlock calls is equal to number of lock calls + */ +void test_lock_eq_ushrt_max(); + +/** Test sleep_auto calls sleep and deep sleep based on lock + * + * Given a device with sleep mode support + * When the deep sleep mode is locked + * Then sleep_auto uses sleep mode + * + * When the deep sleep mode is unlocked + * Then sleep_auto uses deep sleep mode + */ +void test_sleep_auto(); + +/** Test lock/unlock test_check fun + * + * Given the deep sleep has not been locked + * When the deep sleep status is checked + * Then sleep_manager_can_deep_sleep() returns true + * and sleep_manager_can_deep_sleep_test_check() returns true instantly. + * + * When the deep sleep mode is locked + * Then sleep_manager_can_deep_sleep() returns false + * and sleep_manager_can_deep_sleep_test_check() returns false with 2 ms delay. + * + * When the deep sleep mode is unlocked with a 1 ms delay + * Then sleep_manager_can_deep_sleep() returns false + * and sleep_manager_can_deep_sleep_test_check() returns true with 1 ms delay + * and sleep_manager_can_deep_sleep() returns true when checked again. + */ +void test_lock_unlock_test_check(); + +#endif + +#endif + +/** @}*/ diff --git a/TESTS/mbed_hal/sleep_manager_racecondition/main.cpp b/TESTS/mbed_hal/sleep_manager_racecondition/main.cpp index d43492c052..86f2aaeeea 100644 --- a/TESTS/mbed_hal/sleep_manager_racecondition/main.cpp +++ b/TESTS/mbed_hal/sleep_manager_racecondition/main.cpp @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include "utest/utest.h" #include "unity/unity.h" #include "greentea-client/test_env.h" +#include "mbed.h" +#include "sleep_manager_api_racecondition_tests.h" #if !DEVICE_SLEEP #error [NOT_SUPPORTED] test not supported @@ -34,7 +35,7 @@ void sleep_manager_locking_thread_test() { for (uint32_t i = 0; i < 100; i++) { sleep_manager_lock_deep_sleep(); - Thread::wait(25); + ThisThread::sleep_for(25); sleep_manager_unlock_deep_sleep(); } } @@ -47,7 +48,7 @@ void sleep_manager_multithread_test() Thread t2(osPriorityNormal, TEST_STACK_SIZE); t1.start(callback(cb)); - Thread::wait(25); + ThisThread::sleep_for(25); t2.start(callback(cb)); // Wait for the threads to finish @@ -94,8 +95,8 @@ utest::v1::status_t greentea_test_setup(const size_t number_of_cases) } Case cases[] = { - Case("sleep manager HAL - locking multithreaded", sleep_manager_multithread_test), - Case("sleep manager HAL - locking IRQ", sleep_manager_irq_test), + Case("deep sleep lock/unlock is thread safe", sleep_manager_multithread_test), + Case("deep sleep lock/unlock is IRQ safe", sleep_manager_irq_test), }; Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); diff --git a/TESTS/mbed_hal/sleep_manager_racecondition/sleep_manager_api_racecondition_tests.h b/TESTS/mbed_hal/sleep_manager_racecondition/sleep_manager_api_racecondition_tests.h new file mode 100644 index 0000000000..343b374e99 --- /dev/null +++ b/TESTS/mbed_hal/sleep_manager_racecondition/sleep_manager_api_racecondition_tests.h @@ -0,0 +1,43 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * 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. + */ + +/** + * @addtogroup hal_sleep_manager_tests + * @{ + */ + +#ifndef MBED_HAL_SLEEP_MANAGER_API_RACECONDITION_TESTS_H +#define MBED_HAL_SLEEP_MANAGER_API_RACECONDITION_TESTS_H + +/** Test lock/unlock is thread safe + * + * Given a device with sleep mode support + * When multiple threads are using the sleep manager API + * Then lock/unlock calls are thread safe + */ +void sleep_manager_multithread_test(); + +/** Test lock/unlock is IRQ safe + * + * Given a device with sleep mode support + * When the sleep manager API is used from IRQ and the main thread concurrently + * Then lock/unlock calls are IRQ safe + */ +void sleep_manager_irq_test(); + +#endif + +/** @}*/ diff --git a/TESTS/mbed_hal/trng/base64b/base64b.cpp b/TESTS/mbed_hal/trng/base64b/base64b.cpp index 2623bfee6f..9b8525c567 100644 --- a/TESTS/mbed_hal/trng/base64b/base64b.cpp +++ b/TESTS/mbed_hal/trng/base64b/base64b.cpp @@ -72,10 +72,10 @@ base64_result_e trng_DecodeNBase64(const char *string, } *writePtr = 0; - while (( currPos < stringMaxSize ) && - ( string[currPos] != 0 ) && - ( writePtr < bufferEnd ) && - ( !isEndOfString )) { + while ((currPos < stringMaxSize) && + (string[currPos] != 0) && + (writePtr < bufferEnd) && + (!isEndOfString)) { uint8_t val; if (string[currPos] == 0) { @@ -125,11 +125,11 @@ base64_result_e trng_DecodeNBase64(const char *string, } // Check if additional bytes should have been processed but buffer isn't sufficient. - if (( result == BASE64_SUCCESS ) && - ( !isEndOfString ) && - ( currPos < stringMaxSize ) && - ( string[currPos] != 0 ) && - ( string[currPos] != '=' ) ) { + if ((result == BASE64_SUCCESS) && + (!isEndOfString) && + (currPos < stringMaxSize) && + (string[currPos] != 0) && + (string[currPos] != '=')) { return BASE64_BUFFER_TOO_SMALL; } diff --git a/TESTS/mbed_hal/trng/main.cpp b/TESTS/mbed_hal/trng/main.cpp index cfa0260d13..b4fd22e0f8 100644 --- a/TESTS/mbed_hal/trng/main.cpp +++ b/TESTS/mbed_hal/trng/main.cpp @@ -92,7 +92,7 @@ static int fill_buffer_trng(uint8_t *buffer, trng_t *trng_obj, size_t trng_len) void print_array(uint8_t *buffer, size_t size) { - for (size_t i=0; i < size; i++) { + for (size_t i = 0; i < size; i++) { utest_printf("%02x", buffer[i]); } utest_printf("\n"); @@ -120,7 +120,7 @@ static void compress_and_compare(char *key, char *value) uint32_t lengthWritten = 0; uint32_t charsProcessed = 0; result = trng_DecodeNBase64((const char *)value, - MSG_VALUE_LEN, + MSG_VALUE_LEN, buffer, BUFFER_LEN, &lengthWritten, @@ -143,11 +143,11 @@ static void compress_and_compare(char *key, char *value) (char *)out_comp_buf, OUT_COMP_BUF_SIZE, 9); - if (comp_sz <= BUFFER_LEN){ - print_array(buffer, BUFFER_LEN); + if (comp_sz <= BUFFER_LEN) { + print_array(buffer, BUFFER_LEN); } TEST_ASSERT_MESSAGE(comp_sz > BUFFER_LEN, - "TRNG_TEST_STEP1: trng_get_bytes was able to compress thus not random"); + "TRNG_TEST_STEP1: trng_get_bytes was able to compress thus not random"); /*pithy_Compress will try to compress the random data with a different buffer size*/ result = fill_buffer_trng(temp_buf, &trng_obj, TEMP_BUF_SIZE); @@ -158,11 +158,11 @@ static void compress_and_compare(char *key, char *value) (char *)out_comp_buf, OUT_COMP_BUF_SIZE, 9); - if (comp_sz <= TEMP_BUF_SIZE){ - print_array(temp_buf, TEMP_BUF_SIZE); + if (comp_sz <= TEMP_BUF_SIZE) { + print_array(temp_buf, TEMP_BUF_SIZE); } TEST_ASSERT_MESSAGE(comp_sz > TEMP_BUF_SIZE, - "TRNG_TEST_STEP2: trng_get_bytes was able to compress thus not random"); + "TRNG_TEST_STEP2: trng_get_bytes was able to compress thus not random"); memcpy(input_buf + BUFFER_LEN, temp_buf, TEMP_BUF_SIZE); /*pithy_Compress will try to compress the random data from before reset concatenated with new random data*/ @@ -171,11 +171,11 @@ static void compress_and_compare(char *key, char *value) (char *)out_comp_buf, OUT_COMP_BUF_SIZE, 9); - if (comp_sz <= TEMP_BUF_SIZE + BUFFER_LEN){ - print_array(input_buf, TEMP_BUF_SIZE + BUFFER_LEN); + if (comp_sz <= TEMP_BUF_SIZE + BUFFER_LEN) { + print_array(input_buf, TEMP_BUF_SIZE + BUFFER_LEN); } TEST_ASSERT_MESSAGE(comp_sz > TEMP_BUF_SIZE + BUFFER_LEN, - "TRNG_TEST_STEP3: concatenated buffer after reset was able to compress thus not random"); + "TRNG_TEST_STEP3: concatenated buffer after reset was able to compress thus not random"); greentea_send_kv(MSG_TRNG_TEST_SUITE_ENDED, MSG_VALUE_DUMMY); } @@ -184,9 +184,9 @@ static void compress_and_compare(char *key, char *value) if (strcmp(key, MSG_TRNG_TEST_STEP1) == 0) { int result = 0; /*Using base64 to encode data sending from host*/ - result = trng_EncodeBase64(buffer, - BUFFER_LEN, - (char *)out_comp_buf, + result = trng_EncodeBase64(buffer, + BUFFER_LEN, + (char *)out_comp_buf, OUT_COMP_BUF_SIZE); TEST_ASSERT_EQUAL(RESULT_SUCCESS, result); diff --git a/TESTS/mbed_platform/FileHandle/TestFile.h b/TESTS/mbed_platform/FileHandle/TestFile.h index 38e001ad00..1c8ce7273e 100644 --- a/TESTS/mbed_platform/FileHandle/TestFile.h +++ b/TESTS/mbed_platform/FileHandle/TestFile.h @@ -18,14 +18,13 @@ #include "platform/FileHandle.h" - #define POS_IS_VALID(pos) (pos >= 0 && pos < _end) #define NEW_POS_IS_VALID(pos) (pos >= 0 && pos < (int32_t)FILE_SIZE) #define SEEK_POS_IS_VALID(pos) (pos >= 0 && pos <= _end) #define INVALID_POS (-1) template -class TestFile : public FileHandle { +class TestFile : public mbed::FileHandle { public: TestFile(): _pos(0), _end(0) {} ~TestFile() {} diff --git a/TESTS/mbed_platform/Stream/main.cpp b/TESTS/mbed_platform/Stream/main.cpp new file mode 100644 index 0000000000..e615e8adfc --- /dev/null +++ b/TESTS/mbed_platform/Stream/main.cpp @@ -0,0 +1,75 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * 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. + */ + +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" +#include "mbed.h" + +using utest::v1::Case; + +class Loopback : public Stream { +public: + Loopback(const char *name = NULL) : Stream(name) {} + +protected: + virtual int _getc() + { + return _c; + } + virtual int _putc(int c) + { + _c = c; + return c; + } +private: + char _c; +}; + +Loopback loop("loopback"); + +void test_putc_getc() +{ + int ret; + char char_buf[2] = {'a', 'b'}; + + ret = loop.putc(char_buf[0]); + TEST_ASSERT_EQUAL_INT(char_buf[0], ret); + ret = loop.getc(); + TEST_ASSERT_EQUAL_INT(char_buf[0], ret); + ret = loop.putc(char_buf[1]); + TEST_ASSERT_EQUAL_INT(char_buf[1], ret); + ret = loop.getc(); + TEST_ASSERT_EQUAL_INT(char_buf[1], ret); + return; +} + +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(10, "default_auto"); + return utest::v1::verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Test putc/getc", test_putc_getc) +}; + +utest::v1::Specification specification(test_setup, cases); + +int main() +{ + return !utest::v1::Harness::run(specification); +} diff --git a/TESTS/mbed_platform/stats_cpu/main.cpp b/TESTS/mbed_platform/stats_cpu/main.cpp index 9ae162b245..51915d92d6 100644 --- a/TESTS/mbed_platform/stats_cpu/main.cpp +++ b/TESTS/mbed_platform/stats_cpu/main.cpp @@ -56,7 +56,7 @@ void get_cpu_usage() uint8_t usage = 100 - ((diff * 100) / (SAMPLE_TIME * 1000)); prev_idle_time = stats.idle_time; TEST_ASSERT_NOT_EQUAL(0, usage); - Thread::wait(SAMPLE_TIME); + ThisThread::sleep_for(SAMPLE_TIME); } } @@ -65,7 +65,7 @@ void test_cpu_info(void) mbed_stats_cpu_t stats; // Additional read to make sure timer is initialized mbed_stats_cpu_get(&stats); - Thread::wait(3); + ThisThread::sleep_for(3); mbed_stats_cpu_get(&stats); TEST_ASSERT_NOT_EQUAL(0, stats.uptime); TEST_ASSERT_NOT_EQUAL(0, stats.idle_time); @@ -83,7 +83,7 @@ void test_cpu_load(void) // Steadily increase the system load for (int count = 1; ; count++) { - Thread::wait(LOOP_TIME); + ThisThread::sleep_for(LOOP_TIME); if (wait_time <= 0) { break; } diff --git a/TESTS/mbed_platform/stats_heap/main.cpp b/TESTS/mbed_platform/stats_heap/main.cpp index 2d7d6b27e9..163ff20d6c 100644 --- a/TESTS/mbed_platform/stats_heap/main.cpp +++ b/TESTS/mbed_platform/stats_heap/main.cpp @@ -66,11 +66,13 @@ void test_case_malloc_free_size() TEST_ASSERT_EQUAL_UINT32(stats_start.total_size + ALLOCATION_SIZE_DEFAULT * (i + 1), stats_current.total_size); TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_cnt + 1, stats_current.alloc_cnt); TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_fail_cnt, stats_current.alloc_fail_cnt); - + // Library header 0x4-0x8, stats header 0x8 and alignment addition 0x4 + TEST_ASSERT_INT_WITHIN(0x8, stats_start.overhead_size + 0xC, stats_current.overhead_size); // Free memory and assert back to starting size free(data); mbed_stats_heap_get(&stats_current); TEST_ASSERT_EQUAL_UINT32(stats_start.current_size, stats_current.current_size); + TEST_ASSERT_EQUAL_UINT32(stats_start.overhead_size, stats_current.overhead_size); TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_cnt, stats_current.alloc_cnt); TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_fail_cnt, stats_current.alloc_fail_cnt); } @@ -93,10 +95,14 @@ void test_case_allocate_zero() TEST_ASSERT_EQUAL_UINT32(stats_start.current_size, stats_current.current_size); TEST_ASSERT_EQUAL_UINT32(stats_start.total_size, stats_current.total_size); TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_fail_cnt, stats_current.alloc_fail_cnt); - + // Library header 0x4-0x8, stats header 0x8 and alignment addition 0x4 + if (NULL != data) { + TEST_ASSERT_INT_WITHIN(0x8, stats_start.overhead_size + 0xC, stats_current.overhead_size); + } // Free memory and assert back to starting size free(data); mbed_stats_heap_get(&stats_current); + TEST_ASSERT_EQUAL_UINT32(stats_start.overhead_size, stats_current.overhead_size); TEST_ASSERT_EQUAL_UINT32(stats_start.current_size, stats_current.current_size); TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_cnt, stats_current.alloc_cnt); TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_fail_cnt, stats_current.alloc_fail_cnt); @@ -121,6 +127,7 @@ void test_case_allocate_fail() TEST_ASSERT_EQUAL_UINT32(stats_start.total_size, stats_current.total_size); TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_cnt, stats_current.alloc_cnt); TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_fail_cnt + i + 1, stats_current.alloc_fail_cnt); + TEST_ASSERT_EQUAL_UINT32(stats_start.overhead_size, stats_current.overhead_size); } } diff --git a/TESTS/mbed_platform/stats_thread/main.cpp b/TESTS/mbed_platform/stats_thread/main.cpp index f79375db93..2a9f62d8f9 100644 --- a/TESTS/mbed_platform/stats_thread/main.cpp +++ b/TESTS/mbed_platform/stats_thread/main.cpp @@ -46,7 +46,7 @@ void increment_with_delay() { while (1) { counter++; - Thread::wait(500); + ThisThread::sleep_for(500); } } @@ -111,7 +111,7 @@ void test_case_multi_threads_blocked() uint32_t ret = ef.set(FLAG_SIGNAL_DEC); TEST_ASSERT_FALSE(ret & osFlagsError); - Thread::wait(100); + ThisThread::sleep_for(100); count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); TEST_ASSERT_EQUAL(1, (count - old_count)); diff --git a/TESTS/mbed_platform/system_reset/main.cpp b/TESTS/mbed_platform/system_reset/main.cpp index 637735e472..e611ebf0eb 100644 --- a/TESTS/mbed_platform/system_reset/main.cpp +++ b/TESTS/mbed_platform/system_reset/main.cpp @@ -43,9 +43,9 @@ void test_system_reset() int main(void) { - GREENTEA_SETUP(2, "system_reset"); + GREENTEA_SETUP(30, "system_reset"); test_system_reset(); GREENTEA_TESTSUITE_RESULT(0); // Fail on any error. return 0; -} \ No newline at end of file +} diff --git a/TESTS/mbedmicro-rtos-mbed/basic/main.cpp b/TESTS/mbedmicro-rtos-mbed/basic/main.cpp index 62e6aa29e9..15aa793ede 100644 --- a/TESTS/mbedmicro-rtos-mbed/basic/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/basic/main.cpp @@ -48,7 +48,7 @@ static const int test_timeout = 40; void update_tick_thread(Mutex *mutex) { while (true) { - Thread::wait(1); + ThisThread::sleep_for(1); mutex->lock(); ++elapsed_time_ms; mutex->unlock(); @@ -56,7 +56,7 @@ void update_tick_thread(Mutex *mutex) } -/** Tests is to measure the accuracy of Thread::wait() over a period of time +/** Tests is to measure the accuracy of ThisThread::sleep_for() over a period of time Given a thread updating elapsed_time_ms every milli sec @@ -109,7 +109,7 @@ void test(void) } Case cases[] = { - Case("Test Thread::wait accuracy", test) + Case("Test ThisThread::sleep_for accuracy", test) }; utest::v1::status_t greentea_test_setup(const size_t number_of_cases) diff --git a/TESTS/mbedmicro-rtos-mbed/event_flags/main.cpp b/TESTS/mbedmicro-rtos-mbed/event_flags/main.cpp index a519cb165b..0cba8c5dde 100644 --- a/TESTS/mbedmicro-rtos-mbed/event_flags/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/event_flags/main.cpp @@ -48,26 +48,6 @@ using utest::v1::Case; Semaphore sync_sem(0, 1); -/* In order to successfully run this test suite when compiled with --profile=debug - * error() has to be redefined as noop. - * - * EventFlags calls RTX API which uses Event Recorder functionality. When compiled - * with MBED_TRAP_ERRORS_ENABLED=1 (set in debug profile) EvrRtxEventFlagsError() calls error() - * which aborts test program. - */ -#if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED -void error(const char *format, ...) -{ - (void) format; -} - -//Override the set_error function to trap the errors -mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) -{ - return MBED_SUCCESS; -} -#endif - template void send_thread(EventFlags *ef) { @@ -75,7 +55,7 @@ void send_thread(EventFlags *ef) const uint32_t flag = flags & (1 << i); if (flag) { ef->set(flag); - Thread::wait(wait_ms); + ThisThread::sleep_for(wait_ms); } } } @@ -88,7 +68,7 @@ void send_thread_sync(EventFlags *ef) if (flag) { sync_sem.wait(); ef->set(flag); - Thread::wait(wait_ms); + ThisThread::sleep_for(wait_ms); } } } @@ -167,14 +147,18 @@ void test_prohibited(void) ev.set(FLAG01 | FLAG02 | FLAG03); +#if !MBED_TRAP_ERRORS_ENABLED flags = ev.clear(PROHIBITED_FLAG); TEST_ASSERT_EQUAL(osFlagsErrorParameter, flags); +#endif flags = ev.get(); TEST_ASSERT_EQUAL(FLAG01 | FLAG02 | FLAG03, flags); +#if !MBED_TRAP_ERRORS_ENABLED flags = ev.set(PROHIBITED_FLAG); TEST_ASSERT_EQUAL(osFlagsErrorParameter, flags); +#endif flags = ev.get(); TEST_ASSERT_EQUAL(FLAG01 | FLAG02 | FLAG03, flags); diff --git a/TESTS/mbedmicro-rtos-mbed/heap_and_stack/main.cpp b/TESTS/mbedmicro-rtos-mbed/heap_and_stack/main.cpp index d4334ad6f6..dd9f52789f 100644 --- a/TESTS/mbedmicro-rtos-mbed/heap_and_stack/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/heap_and_stack/main.cpp @@ -226,7 +226,7 @@ void test_heap_allocation_free(void) check_and_free_heap(head, max_allocation_size); // Force a task switch so a stack check is performed - Thread::wait(10); + ThisThread::sleep_for(10); printf("Total size dynamically allocated: %luB\n", max_allocation_size); } diff --git a/TESTS/mbedmicro-rtos-mbed/mail/main.cpp b/TESTS/mbedmicro-rtos-mbed/mail/main.cpp index 36af0fb831..08a65fbb32 100644 --- a/TESTS/mbedmicro-rtos-mbed/mail/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/mail/main.cpp @@ -62,7 +62,7 @@ void send_thread(Mail *m) mail->thread_id = thread_id; mail->data = data++; m->put(mail); - Thread::wait(wait_ms); + ThisThread::sleep_for(wait_ms); } } @@ -72,7 +72,7 @@ void receive_thread(Mail *m) int result_counter = 0; uint32_t data = thread_id * DATA_BASE; - Thread::wait(wait_ms); + ThisThread::sleep_for(wait_ms); for (uint32_t i = 0; i < queue_size; i++) { osEvent evt = m->get(); if (evt.status == osEventMail) { @@ -108,7 +108,7 @@ void test_single_thread_order(void) thread.start(callback(send_thread, &mail_box)); // wait for some mail to be collected - Thread::wait(10); + ThisThread::sleep_for(10); for (uint32_t i = 0; i < QUEUE_SIZE; i++) { // mail receive (main thread) @@ -150,7 +150,7 @@ void test_multi_thread_order(void) thread3.start(callback(send_thread, &mail_box)); // wait for some mail to be collected - Thread::wait(10); + ThisThread::sleep_for(10); for (uint32_t i = 0; i < QUEUE_SIZE; i++) { // mail receive (main thread) @@ -211,7 +211,7 @@ void test_multi_thread_multi_mail_order(void) mail->data = data[id]++; mail_box[id].put(mail); - Thread::wait(i * 10); + ThisThread::sleep_for(i * 10); } thread1.join(); diff --git a/TESTS/mbedmicro-rtos-mbed/malloc/main.cpp b/TESTS/mbedmicro-rtos-mbed/malloc/main.cpp index 10a9ea883e..c4ffd70c1d 100644 --- a/TESTS/mbedmicro-rtos-mbed/malloc/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/malloc/main.cpp @@ -90,7 +90,7 @@ void test_multithread_allocation(void) // Give the test time to run while (test_time--) { - Thread::wait(1000); + ThisThread::sleep_for(1000); } // Join and delete all threads diff --git a/TESTS/mbedmicro-rtos-mbed/mutex/main.cpp b/TESTS/mbedmicro-rtos-mbed/mutex/main.cpp index 126673f982..c3cfd3d651 100644 --- a/TESTS/mbedmicro-rtos-mbed/mutex/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/mutex/main.cpp @@ -62,7 +62,7 @@ bool manipulate_protected_zone(const int thread_delay) change_counter++; core_util_critical_section_exit(); - Thread::wait(thread_delay); + ThisThread::sleep_for(thread_delay); core_util_critical_section_enter(); changing_counter = false; @@ -100,7 +100,7 @@ void test_multiple_threads(void) while (true) { // Thread 1 action - Thread::wait(t1_delay); + ThisThread::sleep_for(t1_delay); manipulate_protected_zone(t1_delay); core_util_critical_section_enter(); @@ -199,7 +199,7 @@ void test_dual_thread_lock_lock_thread(Mutex *mutex) bool stat = mutex->trylock_for(TEST_DELAY); TEST_ASSERT_EQUAL(false, stat); - TEST_ASSERT_UINT32_WITHIN(5000, TEST_DELAY*1000, timer.read_us()); + TEST_ASSERT_UINT32_WITHIN(5000, TEST_DELAY * 1000, timer.read_us()); } /** Test dual thread lock diff --git a/TESTS/mbedmicro-rtos-mbed/queue/main.cpp b/TESTS/mbedmicro-rtos-mbed/queue/main.cpp index b2a1c0257e..286630bb77 100644 --- a/TESTS/mbedmicro-rtos-mbed/queue/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/queue/main.cpp @@ -37,7 +37,7 @@ using namespace utest::v1; template void thread_put_uint_msg(Queue *q) { - Thread::wait(ms); + ThisThread::sleep_for(ms); osStatus stat = q->put((uint32_t *) TEST_UINT_MSG); TEST_ASSERT_EQUAL(osOK, stat); } @@ -45,7 +45,7 @@ void thread_put_uint_msg(Queue *q) template void thread_get_uint_msg(Queue *q) { - Thread::wait(ms); + ThisThread::sleep_for(ms); osEvent evt = q->get(); TEST_ASSERT_EQUAL(osEventMessage, evt.status); TEST_ASSERT_EQUAL(val, evt.value.v); diff --git a/TESTS/mbedmicro-rtos-mbed/rtostimer/main.cpp b/TESTS/mbedmicro-rtos-mbed/rtostimer/main.cpp index 74cfb51f54..a06561afc8 100644 --- a/TESTS/mbedmicro-rtos-mbed/rtostimer/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/rtostimer/main.cpp @@ -77,25 +77,6 @@ void sem_callback(Semaphore *sem) sem->release(); } -/* In order to successfully run this test suite when compiled with --profile=debug - * error() has to be redefined as noop. - * - * RtosTimer calls RTX API which uses Event Recorder functionality. When compiled - * with MBED_TRAP_ERRORS_ENABLED=1 (set in debug profile) EvrRtxTimerError() calls error() - * which aborts test program. - */ -#if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED -void error(const char *format, ...) -{ - (void) format; -} - -mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) -{ - return MBED_SUCCESS; -} -#endif - /** Test one-shot not restarted when elapsed * * Given a one-shot RtosTimer @@ -121,8 +102,11 @@ void test_oneshot_not_restarted() slots = stopwatch.wait_until_stopped(DELAY_MS + DELTA_MS); TEST_ASSERT_EQUAL(0, slots); + +#if !MBED_TRAP_ERRORS_ENABLED status = rtostimer.stop(); TEST_ASSERT_EQUAL(osErrorResource, status); +#endif } /** Test periodic repeats continuously @@ -160,8 +144,11 @@ void test_periodic_repeats() slots = stopwatch.wait_until_stopped(DELAY_MS + DELTA_MS); TEST_ASSERT_EQUAL(0, slots); + +#if !MBED_TRAP_ERRORS_ENABLED status = rtostimer.stop(); TEST_ASSERT_EQUAL(osErrorResource, status); +#endif } /** Test timer can be started again @@ -185,8 +172,10 @@ void test_start_again() int32_t slots = sem.wait(DELAY_MS + DELTA_MS); TEST_ASSERT_EQUAL(1, slots); +#if !MBED_TRAP_ERRORS_ENABLED status = rtostimer.stop(); TEST_ASSERT_EQUAL(osErrorResource, status); +#endif status = rtostimer.start(DELAY_MS); TEST_ASSERT_EQUAL(osOK, status); @@ -194,8 +183,10 @@ void test_start_again() slots = sem.wait(DELAY_MS + DELTA_MS); TEST_ASSERT_EQUAL(1, slots); +#if !MBED_TRAP_ERRORS_ENABLED status = rtostimer.stop(); TEST_ASSERT_EQUAL(osErrorResource, status); +#endif } /** Test timer restart updates delay @@ -228,8 +219,10 @@ void test_restart_updates_delay() TEST_ASSERT_EQUAL(1, slots); TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY2_MS, stopwatch.read_ms()); +#if !MBED_TRAP_ERRORS_ENABLED status = rtostimer.stop(); TEST_ASSERT_EQUAL(osErrorResource, status); +#endif } /** Test timer is created in stopped state @@ -241,8 +234,10 @@ void test_restart_updates_delay() void test_created_stopped() { RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce); +#if !MBED_TRAP_ERRORS_ENABLED osStatus status = rtostimer.stop(); TEST_ASSERT_EQUAL(osErrorResource, status); +#endif } /** Test one-shot can be stopped @@ -269,8 +264,10 @@ void test_stop() slots = sem.wait(DELAY_MS + DELTA_MS); TEST_ASSERT_EQUAL(0, slots); +#if !MBED_TRAP_ERRORS_ENABLED status = rtostimer.stop(); TEST_ASSERT_EQUAL(osErrorResource, status); +#endif } /** Test timer started with infinite delay @@ -290,6 +287,7 @@ void test_wait_forever() TEST_ASSERT_EQUAL(osOK, status); } +#if !MBED_TRAP_ERRORS_ENABLED /** Test timer started with zero delay * * Given a one-shot RtosTimer @@ -331,6 +329,7 @@ void test_isr_calls_fail() wait_ms(DELAY_MS + DELTA_MS); } +#endif // !MBED_TRAP_ERRORS_ENABLED utest::v1::status_t test_setup(const size_t number_of_cases) { @@ -346,8 +345,10 @@ Case cases[] = { Case("Timer can be stopped", test_stop), Case("Timer is created in stopped state", test_created_stopped), Case("Timer started with infinite delay", test_wait_forever), +#if !MBED_TRAP_ERRORS_ENABLED Case("Timer started with zero delay", test_no_wait), Case("Calls from ISR fail", test_isr_calls_fail) +#endif }; Specification specification(test_setup, cases); diff --git a/TESTS/mbedmicro-rtos-mbed/semaphore/main.cpp b/TESTS/mbedmicro-rtos-mbed/semaphore/main.cpp index 69c92fdbcf..182b447294 100644 --- a/TESTS/mbedmicro-rtos-mbed/semaphore/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/semaphore/main.cpp @@ -52,7 +52,7 @@ void test_thread(int const *delay) if (sem_lock_failed) { sem_defect = true; } - Thread::wait(thread_delay); + ThisThread::sleep_for(thread_delay); sem_counter--; change_counter++; two_slots.release(); @@ -123,7 +123,7 @@ void test_single_thread() res = t.start(callback(single_thread, &data)); TEST_ASSERT_EQUAL(osOK, res); - Thread::wait(SHORT_WAIT); + ThisThread::sleep_for(SHORT_WAIT); TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state()); TEST_ASSERT_EQUAL(0, data.data); @@ -131,7 +131,7 @@ void test_single_thread() res = sem.release(); TEST_ASSERT_EQUAL(osOK, res); - Thread::wait(SHORT_WAIT); + ThisThread::sleep_for(SHORT_WAIT); TEST_ASSERT_EQUAL(1, data.data); @@ -160,7 +160,7 @@ void test_timeout() timer.start(); res = t.start(callback(timeout_thread, &sem)); TEST_ASSERT_EQUAL(osOK, res); - Thread::wait(SHORT_WAIT); + ThisThread::sleep_for(SHORT_WAIT); TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state()); diff --git a/TESTS/mbedmicro-rtos-mbed/signals/main.cpp b/TESTS/mbedmicro-rtos-mbed/signals/main.cpp index cd852b2ef0..4f340a646e 100644 --- a/TESTS/mbedmicro-rtos-mbed/signals/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/signals/main.cpp @@ -46,27 +46,6 @@ struct Sync { Semaphore &sem_child; }; - -/* In order to successfully run this test suite when compiled with --profile=debug - * error() has to be redefined as noop. - * - * ThreadFlags calls RTX API which uses Event Recorder functionality. When compiled - * with MBED_TRAP_ERRORS_ENABLED=1 (set in debug profile) EvrRtxEventFlagsError() calls error() - * which aborts test program. - */ -#if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED -void error(const char *format, ...) -{ - (void) format; -} - -mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) -{ - return MBED_SUCCESS; -} -#endif - - template void run_signal_wait(void) { @@ -103,7 +82,7 @@ void run_wait_clear(Sync *sync) { sync->sem_parent.release(); sync->sem_child.wait(); - int32_t ret = Thread::signal_clr(signals); + int32_t ret = ThisThread::flags_clear(signals); TEST_ASSERT_EQUAL(test_val, ret); } @@ -114,10 +93,10 @@ void run_double_wait_clear(Sync *sync) sync->sem_parent.release(); sync->sem_child.wait(); - ret = Thread::signal_clr(signals1); + ret = ThisThread::flags_clear(signals1); TEST_ASSERT_EQUAL(test_val1, ret); - ret = Thread::signal_clr(signals2); + ret = ThisThread::flags_clear(signals2); TEST_ASSERT_EQUAL(test_val2, ret); } @@ -128,7 +107,7 @@ void run_loop_wait_clear(Sync *sync) int32_t signal = 1 << i; signals |= signal; sync->sem_child.wait(); - int32_t ret = Thread::signal_clr(NO_SIGNALS); + int32_t ret = ThisThread::flags_clear(NO_SIGNALS); TEST_ASSERT_EQUAL(signals, ret); sync->sem_parent.release(); } @@ -214,8 +193,10 @@ void test_set_prohibited(void) sem_parent.wait(); t.signal_set(ALL_SIGNALS); +#if !MBED_TRAP_ERRORS_ENABLED ret = t.signal_set(PROHIBITED_SIGNAL); TEST_ASSERT_EQUAL(osErrorParameter, ret); +#endif sem_child.release(); t.join(); diff --git a/TESTS/mbedmicro-rtos-mbed/threads/main.cpp b/TESTS/mbedmicro-rtos-mbed/threads/main.cpp index 20bbad5a46..3111aa3d73 100644 --- a/TESTS/mbedmicro-rtos-mbed/threads/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/threads/main.cpp @@ -474,7 +474,7 @@ void test_thread_wait() Timer timer; timer.start(); - Thread::wait(150); + ThisThread::sleep_for(150); TEST_ASSERT_UINT32_WITHIN(50000, 150000, timer.read_us()); } @@ -528,7 +528,7 @@ void test_deleted() void test_delay_thread() { - Thread::wait(50); + ThisThread::sleep_for(50); } /** Testing thread states: wait delay diff --git a/TESTS/mbedtls/multi/main.cpp b/TESTS/mbedtls/multi/main.cpp index 76d5ff1b8f..e6a03f450b 100644 --- a/TESTS/mbedtls/multi/main.cpp +++ b/TESTS/mbedtls/multi/main.cpp @@ -145,7 +145,7 @@ void test_case_sha256_multi() for (i = 0; i < 32; i++) { printf("%02X", outsum1[i]); } - printf("\nawaited result : 248D6A61D20638B8E5C026930C3E6039A33CE45964FF216F6ECEDD19DB06C1\n"); // for abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq + printf("\nawaited result : 248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1\n"); // for abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq printf("\nreceived result ctx2 : "); for (i = 0; i < 32; i++) { printf("%02X", outsum2[i]); diff --git a/TESTS/netsocket/README.md b/TESTS/netsocket/README.md index 689c711495..971c9d61f6 100644 --- a/TESTS/netsocket/README.md +++ b/TESTS/netsocket/README.md @@ -715,10 +715,9 @@ Call `UDPSocket::sendto()` with invalid parameters. 3. Call `UDPSocket:sendto( "", 0, NULL, 0);` 4. Call `UDPSocket:sendto(NULL, 9, "hello", 5);` 5. Call `UDPSocket:sendto(NULL, 0, "hello", 5);` -6. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 0, "hello", 5);` -7. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 9,NULL, 0);` -8. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 9, "hello", 5);` -9. destroy the socket +6. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 9,NULL, 0);` +7. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 9, "hello", 5);` +8. destroy the socket **Expected result:** @@ -990,9 +989,8 @@ Call `TCPSocket::connect()` with invalid parameters. 1. Call `TCPSocket:connect( NULL, 9);` 2. Call `TCPSocket:connect( "", 9);` 3. Call `TCPSocket:connect( "", 0);` -4. Call `TCPSocket:connect( "echo.mbedcloudtesting.com", 0);` -5. Call `TCPSocket:connect( "echo.mbedcloudtesting.com", 9);` -6. destroy the socket +4. Call `TCPSocket:connect( "echo.mbedcloudtesting.com", 9);` +5. destroy the socket **Expected result:** diff --git a/TESTS/netsocket/dns/main.cpp b/TESTS/netsocket/dns/main.cpp index e8ae973532..ecc63ce40c 100644 --- a/TESTS/netsocket/dns/main.cpp +++ b/TESTS/netsocket/dns/main.cpp @@ -181,7 +181,7 @@ Case cases[] = { Case("SYNCHRONOUS_DNS_INVALID", SYNCHRONOUS_DNS_INVALID), }; -Specification specification(test_setup, cases); +Specification specification(test_setup, cases, greentea_continue_handlers); int main() { diff --git a/TESTS/netsocket/tcp/main.cpp b/TESTS/netsocket/tcp/main.cpp index 4051251f40..bbccb85f0d 100644 --- a/TESTS/netsocket/tcp/main.cpp +++ b/TESTS/netsocket/tcp/main.cpp @@ -151,7 +151,7 @@ Case cases[] = { #endif }; -Specification specification(greentea_setup, cases, greentea_teardown); +Specification specification(greentea_setup, cases, greentea_teardown, greentea_continue_handlers); int main() { diff --git a/TESTS/netsocket/tcp/tcpsocket_connect_invalid.cpp b/TESTS/netsocket/tcp/tcpsocket_connect_invalid.cpp index 5f66b2974d..aa77cbc4a8 100644 --- a/TESTS/netsocket/tcp/tcpsocket_connect_invalid.cpp +++ b/TESTS/netsocket/tcp/tcpsocket_connect_invalid.cpp @@ -32,7 +32,6 @@ void TCPSOCKET_CONNECT_INVALID() TEST_ASSERT(sock.connect(NULL, 9) < 0); TEST_ASSERT(sock.connect("", 9) < 0); TEST_ASSERT(sock.connect("", 0) < 0); - TEST_ASSERT(sock.connect(MBED_CONF_APP_ECHO_SERVER_ADDR, 0) < 0); TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.connect(MBED_CONF_APP_ECHO_SERVER_ADDR, 9)); TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close()); diff --git a/TESTS/netsocket/tcp/tcpsocket_echotest.cpp b/TESTS/netsocket/tcp/tcpsocket_echotest.cpp index 86a14e7065..30c773567f 100644 --- a/TESTS/netsocket/tcp/tcpsocket_echotest.cpp +++ b/TESTS/netsocket/tcp/tcpsocket_echotest.cpp @@ -119,7 +119,7 @@ void TCPSOCKET_ECHOTEST_NONBLOCK() tcpsocket_connect_to_echo_srv(sock); sock.set_blocking(false); - sock.sigio(callback(_sigio_handler, Thread::gettid())); + sock.sigio(callback(_sigio_handler, ThisThread::get_id())); int bytes2send; int sent; diff --git a/TESTS/netsocket/tcp/tcpsocket_echotest_burst.cpp b/TESTS/netsocket/tcp/tcpsocket_echotest_burst.cpp index f88a06d178..06f749c26b 100644 --- a/TESTS/netsocket/tcp/tcpsocket_echotest_burst.cpp +++ b/TESTS/netsocket/tcp/tcpsocket_echotest_burst.cpp @@ -41,7 +41,7 @@ void TCPSOCKET_ECHOTEST_BURST() { TCPSocket sock; tcpsocket_connect_to_echo_srv(sock); - sock.sigio(callback(_sigio_handler, Thread::gettid())); + sock.sigio(callback(_sigio_handler, ThisThread::get_id())); // TX buffer to be preserved for comparison fill_tx_buffer_ascii(tcp_global::tx_buffer, BURST_SIZE); @@ -94,7 +94,7 @@ void TCPSOCKET_ECHOTEST_BURST_NONBLOCK() TCPSocket sock; tcpsocket_connect_to_echo_srv(sock); sock.set_blocking(false); - sock.sigio(callback(_sigio_handler, Thread::gettid())); + sock.sigio(callback(_sigio_handler, ThisThread::get_id())); // TX buffer to be preserved for comparison fill_tx_buffer_ascii(tcp_global::tx_buffer, BURST_SIZE); diff --git a/TESTS/netsocket/tcp/tcpsocket_endpoint_close.cpp b/TESTS/netsocket/tcp/tcpsocket_endpoint_close.cpp index ae138ba478..8dfc295328 100644 --- a/TESTS/netsocket/tcp/tcpsocket_endpoint_close.cpp +++ b/TESTS/netsocket/tcp/tcpsocket_endpoint_close.cpp @@ -63,7 +63,7 @@ void TCPSOCKET_ENDPOINT_CLOSE() TEST_FAIL(); return; } - sock.sigio(callback(_sigio_handler, Thread::gettid())); + sock.sigio(callback(_sigio_handler, ThisThread::get_id())); int recvd = 0; int recvd_total = 0; diff --git a/TESTS/netsocket/tcp/tcpsocket_recv_100k.cpp b/TESTS/netsocket/tcp/tcpsocket_recv_100k.cpp index 16dd6f2c76..a7b723cb36 100644 --- a/TESTS/netsocket/tcp/tcpsocket_recv_100k.cpp +++ b/TESTS/netsocket/tcp/tcpsocket_recv_100k.cpp @@ -58,15 +58,19 @@ static nsapi_error_t _tcpsocket_connect_to_chargen_srv(TCPSocket &sock) * \param offset Start pattern from offset * \param len Length of pattern to generate. */ -static void generate_RFC_864_pattern(size_t offset, uint8_t *buf, size_t len) +static void generate_RFC_864_pattern(size_t offset, uint8_t *buf, size_t len, bool is_xinetd) { + const int row_size = 74; // Number of chars in single row + const int row_count = 95; // Number of rows in pattern after which pattern start from beginning + const int chars_scope = is_xinetd ? 93 : 95; // Number of chars from ASCII table used in pattern + const char first_char = is_xinetd ? '!' : ' '; // First char from ASCII table used in pattern while (len--) { - if (offset % 74 == 72) { + if (offset % row_size == (row_size - 2)) { *buf++ = '\r'; - } else if (offset % 74 == 73) { + } else if (offset % row_size == (row_size - 1)) { *buf++ = '\n'; } else { - *buf++ = ' ' + (offset % 74 + offset / 74) % 95 ; + *buf++ = first_char + (offset % row_size + ((offset / row_size) % row_count)) % chars_scope; } offset++; } @@ -74,10 +78,14 @@ static void generate_RFC_864_pattern(size_t offset, uint8_t *buf, size_t len) static void check_RFC_864_pattern(void *rx_buff, const size_t len, const size_t offset) { + static bool is_xinetd = false; void *ref_buff = malloc(len); TEST_ASSERT_NOT_NULL(ref_buff); - generate_RFC_864_pattern(offset, (uint8_t *)ref_buff, len); + if (offset == 0) { + is_xinetd = ((uint8_t *)rx_buff)[0] == '!'; + } + generate_RFC_864_pattern(offset, (uint8_t *)ref_buff, len, is_xinetd); bool match = memcmp(ref_buff, rx_buff, len) == 0; free(ref_buff); @@ -170,7 +178,7 @@ void TCPSOCKET_RECV_100K_NONBLOCK() } sock.set_blocking(false); - sock.sigio(callback(_sigio_handler, Thread::gettid())); + sock.sigio(callback(_sigio_handler, ThisThread::get_id())); rcv_n_chk_against_rfc864_pattern_nonblock(sock); diff --git a/TESTS/netsocket/tcp/tcpsocket_recv_timeout.cpp b/TESTS/netsocket/tcp/tcpsocket_recv_timeout.cpp index b2df0bfa70..4fd0008c03 100644 --- a/TESTS/netsocket/tcp/tcpsocket_recv_timeout.cpp +++ b/TESTS/netsocket/tcp/tcpsocket_recv_timeout.cpp @@ -45,7 +45,7 @@ void TCPSOCKET_RECV_TIMEOUT() TCPSocket sock; tcpsocket_connect_to_echo_srv(sock); sock.set_timeout(100); - sock.sigio(callback(_sigio_handler, Thread::gettid())); + sock.sigio(callback(_sigio_handler, ThisThread::get_id())); int recvd = 0; int pkt_unrecvd; diff --git a/TESTS/netsocket/tcp/tcpsocket_thread_per_socket_safety.cpp b/TESTS/netsocket/tcp/tcpsocket_thread_per_socket_safety.cpp index b508949179..969e267a10 100644 --- a/TESTS/netsocket/tcp/tcpsocket_thread_per_socket_safety.cpp +++ b/TESTS/netsocket/tcp/tcpsocket_thread_per_socket_safety.cpp @@ -47,7 +47,7 @@ static void check_const_len_rand_sequence() { TCPSocket sock; tcpsocket_connect_to_echo_srv(sock); - sock.sigio(callback(_sigio_handler1, Thread::gettid())); + sock.sigio(callback(_sigio_handler1, ThisThread::get_id())); static const int BUFF_SIZE = 10; static char rx_buff[BUFF_SIZE] = {0}; @@ -104,7 +104,7 @@ static void check_var_len_rand_sequence() { TCPSocket sock; tcpsocket_connect_to_echo_srv(sock); - sock.sigio(callback(_sigio_handler2, Thread::gettid())); + sock.sigio(callback(_sigio_handler2, ThisThread::get_id())); static const int BUFF_SIZE = 1001; static char rx_buff[BUFF_SIZE]; diff --git a/TESTS/netsocket/udp/main.cpp b/TESTS/netsocket/udp/main.cpp index a1df7eadee..68222597cf 100644 --- a/TESTS/netsocket/udp/main.cpp +++ b/TESTS/netsocket/udp/main.cpp @@ -104,7 +104,7 @@ Case cases[] = { #endif }; -Specification specification(greentea_setup, cases, greentea_teardown); +Specification specification(greentea_setup, cases, greentea_teardown, greentea_continue_handlers); int main() { diff --git a/TESTS/netsocket/udp/udpsocket_echotest.cpp b/TESTS/netsocket/udp/udpsocket_echotest.cpp index fafed4a870..b3ed7e7397 100644 --- a/TESTS/netsocket/udp/udpsocket_echotest.cpp +++ b/TESTS/netsocket/udp/udpsocket_echotest.cpp @@ -127,7 +127,7 @@ void UDPSOCKET_ECHOTEST_NONBLOCK() TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface())); sock.set_blocking(false); - sock.sigio(callback(_sigio_handler, Thread::gettid())); + sock.sigio(callback(_sigio_handler, ThisThread::get_id())); int sent; int s_idx = 0; diff --git a/TESTS/netsocket/udp/udpsocket_echotest_burst.cpp b/TESTS/netsocket/udp/udpsocket_echotest_burst.cpp index eb833a4868..d2e6a1ce23 100644 --- a/TESTS/netsocket/udp/udpsocket_echotest_burst.cpp +++ b/TESTS/netsocket/udp/udpsocket_echotest_burst.cpp @@ -78,7 +78,7 @@ void UDPSOCKET_ECHOTEST_BURST() const int TIMEOUT = 5000; // [ms] TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface())); sock.set_timeout(TIMEOUT); - sock.sigio(callback(_sigio_handler, Thread::gettid())); + sock.sigio(callback(_sigio_handler, ThisThread::get_id())); // TX buffers to be preserved for comparison prepare_tx_buffers(); @@ -156,7 +156,7 @@ void UDPSOCKET_ECHOTEST_BURST_NONBLOCK() UDPSocket sock; TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface())); sock.set_blocking(false); - sock.sigio(callback(_sigio_handler, Thread::gettid())); + sock.sigio(callback(_sigio_handler, ThisThread::get_id())); // TX buffers to be preserved for comparison prepare_tx_buffers(); diff --git a/TESTS/netsocket/udp/udpsocket_recv_timeout.cpp b/TESTS/netsocket/udp/udpsocket_recv_timeout.cpp index 946e4e3e60..2d0d558742 100644 --- a/TESTS/netsocket/udp/udpsocket_recv_timeout.cpp +++ b/TESTS/netsocket/udp/udpsocket_recv_timeout.cpp @@ -46,7 +46,7 @@ void UDPSOCKET_RECV_TIMEOUT() UDPSocket sock; TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface())); sock.set_timeout(100); - sock.sigio(callback(_sigio_handler, Thread::gettid())); + sock.sigio(callback(_sigio_handler, ThisThread::get_id())); int recvd; Timer timer; diff --git a/TESTS/netsocket/udp/udpsocket_sendto_invalid.cpp b/TESTS/netsocket/udp/udpsocket_sendto_invalid.cpp index c451ad9891..26ae88bda8 100644 --- a/TESTS/netsocket/udp/udpsocket_sendto_invalid.cpp +++ b/TESTS/netsocket/udp/udpsocket_sendto_invalid.cpp @@ -32,7 +32,6 @@ void UDPSOCKET_SENDTO_INVALID() TEST_ASSERT(sock.sendto(NULL, 9, NULL, 0) < 0); TEST_ASSERT(sock.sendto("", 9, NULL, 0) < 0); TEST_ASSERT(sock.sendto("", 0, NULL, 0) < 0); - TEST_ASSERT_EQUAL(5, sock.sendto(MBED_CONF_APP_ECHO_SERVER_ADDR, 0, "hello", 5)); TEST_ASSERT_EQUAL(0, sock.sendto(MBED_CONF_APP_ECHO_SERVER_ADDR, 9, NULL, 0)); TEST_ASSERT_EQUAL(5, sock.sendto(MBED_CONF_APP_ECHO_SERVER_ADDR, 9, "hello", 5)); diff --git a/TESTS/network/emac/main.cpp b/TESTS/network/emac/main.cpp index ac2bdb1403..49ee3cf909 100644 --- a/TESTS/network/emac/main.cpp +++ b/TESTS/network/emac/main.cpp @@ -53,7 +53,7 @@ using namespace utest::v1; utest::v1::status_t test_setup(const size_t number_of_cases) { #if !MBED_CONF_APP_ECHO_SERVER - GREENTEA_SETUP(1200, "default_auto"); + GREENTEA_SETUP(1400, "default_auto"); #endif return verbose_test_setup_handler(number_of_cases); } diff --git a/TESTS/network/interface/main.cpp b/TESTS/network/interface/main.cpp index 995bec86ff..05e07914f4 100644 --- a/TESTS/network/interface/main.cpp +++ b/TESTS/network/interface/main.cpp @@ -38,10 +38,10 @@ utest::v1::status_t test_setup(const size_t number_of_cases) } Case cases[] = { - Case("NETWORKINTERFACE_STATUS", NETWORKINTERFACE_STATUS), - Case("NETWORKINTERFACE_STATUS_NONBLOCK", NETWORKINTERFACE_STATUS_NONBLOCK), - Case("NETWORKINTERFACE_STATUS_GET", NETWORKINTERFACE_STATUS_GET), - Case("NETWORKINTERFACE_CONN_DISC_REPEAT", NETWORKINTERFACE_CONN_DISC_REPEAT), + Case("NETWORKINTERFACE_STATUS", NETWORKINTERFACE_STATUS), + Case("NETWORKINTERFACE_STATUS_NONBLOCK", NETWORKINTERFACE_STATUS_NONBLOCK), + Case("NETWORKINTERFACE_STATUS_GET", NETWORKINTERFACE_STATUS_GET), + Case("NETWORKINTERFACE_CONN_DISC_REPEAT", NETWORKINTERFACE_CONN_DISC_REPEAT), }; Specification specification(test_setup, cases); diff --git a/TESTS/network/interface/networkinterface_conn_disc_repeat.cpp b/TESTS/network/interface/networkinterface_conn_disc_repeat.cpp index 9582c7c82b..a717346c10 100644 --- a/TESTS/network/interface/networkinterface_conn_disc_repeat.cpp +++ b/TESTS/network/interface/networkinterface_conn_disc_repeat.cpp @@ -23,10 +23,9 @@ using namespace utest::v1; -namespace -{ - NetworkInterface* net; - const int repeats = 5; +namespace { +NetworkInterface *net; +const int repeats = 5; } void NETWORKINTERFACE_CONN_DISC_REPEAT() diff --git a/TESTS/network/interface/networkinterface_status.cpp b/TESTS/network/interface/networkinterface_status.cpp index 8da8b139bc..c0d509d516 100644 --- a/TESTS/network/interface/networkinterface_status.cpp +++ b/TESTS/network/interface/networkinterface_status.cpp @@ -23,16 +23,15 @@ using namespace utest::v1; -namespace -{ - NetworkInterface* net; - rtos::Semaphore status_semaphore; - int status_write_counter = 0; - int status_read_counter = 0; - const int repeats = 5; - const int status_buffer_size = 100; - nsapi_connection_status_t current_status = NSAPI_STATUS_ERROR_UNSUPPORTED; - nsapi_connection_status_t statuses[status_buffer_size]; +namespace { +NetworkInterface *net; +rtos::Semaphore status_semaphore; +int status_write_counter = 0; +int status_read_counter = 0; +const int repeats = 5; +const int status_buffer_size = 100; +nsapi_connection_status_t current_status = NSAPI_STATUS_ERROR_UNSUPPORTED; +nsapi_connection_status_t statuses[status_buffer_size]; } void status_cb(nsapi_event_t event, intptr_t value) diff --git a/TESTS/network/wifi/main.cpp b/TESTS/network/wifi/main.cpp index 1fdf0f8f83..7043e00b42 100644 --- a/TESTS/network/wifi/main.cpp +++ b/TESTS/network/wifi/main.cpp @@ -90,7 +90,7 @@ Case cases[] = { #endif }; -Specification specification(test_setup, cases); +Specification specification(test_setup, cases, greentea_continue_handlers); // Entry point into the tests int main() diff --git a/TESTS/network/wifi/wifi_connect.cpp b/TESTS/network/wifi/wifi_connect.cpp index 6d27988838..aec259f130 100644 --- a/TESTS/network/wifi/wifi_connect.cpp +++ b/TESTS/network/wifi/wifi_connect.cpp @@ -25,13 +25,27 @@ using namespace utest::v1; #if defined(MBED_CONF_APP_WIFI_UNSECURE_SSID) +#define SSID_MAX_LEN 32 + void wifi_connect(void) { WiFiInterface *wifi = get_interface(); - TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->set_credentials(MBED_CONF_APP_WIFI_UNSECURE_SSID, NULL)); + char ssid[SSID_MAX_LEN + 1] = MBED_CONF_APP_WIFI_UNSECURE_SSID; + + TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->set_credentials(ssid, NULL)); + TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->connect()); + TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->disconnect()); + + TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->set_credentials(ssid, "")); + TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->connect()); + TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->disconnect()); + + // Driver is expected to cache the credentials + memset(ssid, 0, SSID_MAX_LEN + 1); TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->connect()); + TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->disconnect()); } #endif // defined(MBED_CONF_APP_WIFI_UNSECURE_SSID) diff --git a/TESTS/network/wifi/wifi_connect_params_channel_fail.cpp b/TESTS/network/wifi/wifi_connect_params_channel_fail.cpp index 9584b93721..40b2bc9a0d 100644 --- a/TESTS/network/wifi/wifi_connect_params_channel_fail.cpp +++ b/TESTS/network/wifi/wifi_connect_params_channel_fail.cpp @@ -34,7 +34,8 @@ void wifi_connect_params_channel_fail(void) return; } - nsapi_error_t error = wifi->connect(MBED_CONF_APP_WIFI_SECURE_SSID, MBED_CONF_APP_WIFI_PASSWORD, get_security(), MBED_CONF_APP_WIFI_CH_UNSECURE); + uint8_t wrong_channel = 1 + (MBED_CONF_APP_WIFI_CH_SECURE % 10); + nsapi_error_t error = wifi->connect(MBED_CONF_APP_WIFI_SECURE_SSID, MBED_CONF_APP_WIFI_PASSWORD, get_security(), wrong_channel); TEST_ASSERT(error == NSAPI_ERROR_CONNECTION_TIMEOUT || error == NSAPI_ERROR_NO_CONNECTION); wifi->set_channel(0); diff --git a/TESTS/network/wifi/wifi_scan.cpp b/TESTS/network/wifi/wifi_scan.cpp index ab74e5deb9..92130ad3fd 100644 --- a/TESTS/network/wifi/wifi_scan.cpp +++ b/TESTS/network/wifi/wifi_scan.cpp @@ -48,25 +48,18 @@ void wifi_scan(void) const char *ssid = ap[i].get_ssid(); nsapi_security_t security = ap[i].get_security(); int8_t rssi = ap[i].get_rssi(); - uint8_t ch = ap[i].get_channel(); TEST_ASSERT_INT8_WITHIN(-10, -100, rssi); if (strcmp(MBED_CONF_APP_WIFI_SECURE_SSID, ssid) == 0) { secure_found = true; TEST_ASSERT_EQUAL_INT(get_security(), security); - if (MBED_CONF_APP_WIFI_CH_SECURE) { - TEST_ASSERT_EQUAL_INT(MBED_CONF_APP_WIFI_CH_SECURE, ch); - } } if (strcmp(MBED_CONF_APP_WIFI_UNSECURE_SSID, ssid) == 0) { unsecure_found = true; TEST_ASSERT_EQUAL_INT(NSAPI_SECURITY_NONE, security); - if (MBED_CONF_APP_WIFI_CH_UNSECURE) { - TEST_ASSERT_EQUAL_INT(MBED_CONF_APP_WIFI_CH_UNSECURE, ch); - } } } - TEST_ASSERT_TRUE(secure_found); - TEST_ASSERT_TRUE(unsecure_found); + // Finding one SSID is enough + TEST_ASSERT_TRUE(secure_found || unsecure_found); } #endif // defined(MBED_CONF_APP_WIFI_SECURE_SSID) && defined(MBED_CONF_APP_WIFI_UNSECURE_SSID) diff --git a/TESTS/network/wifi/wifi_set_channel.cpp b/TESTS/network/wifi/wifi_set_channel.cpp index 53ce93e18c..5f609e0848 100644 --- a/TESTS/network/wifi/wifi_set_channel.cpp +++ b/TESTS/network/wifi/wifi_set_channel.cpp @@ -69,5 +69,6 @@ void wifi_set_channel(void) TEST_ASSERT(error == NSAPI_ERROR_PARAMETER); } + wifi->set_channel(0); } diff --git a/TEST_APPS/device/nanostack_mac_tester/README.md b/TEST_APPS/device/nanostack_mac_tester/README.md new file mode 100644 index 0000000000..0a42a2d2f8 --- /dev/null +++ b/TEST_APPS/device/nanostack_mac_tester/README.md @@ -0,0 +1,88 @@ +# Nanostack MAC test application + +You can use this application to test the Nanostack RF driver implementations that follow the [Nanostack RF driver porting instructions](https://os.mbed.com/docs/v5.6/reference/contributing-connectivity.html#porting-new-rf-driver-for-6lowpan-stack). The application has a command-line interface that is used to send commands to Nanostack's MAC layer, for example starting PANs, scanning or sending data. The provided tests do not test performance or stability and only indirectly test RF functionalities. + +## Table of contents + +* [Prerequisites](#prerequisites) +* [Setting up the application](#setting-up-the-application) +* [Application usage](#application-usage) + * [Interactive mode](#interactive-mode) + * [Automated mode](#automated-mode) + * [Testcases](#testcases) + * [Considerations](#considerations) + +## Prerequisites + +* [Mbed CLI](https://github.com/ARMmbed/mbed-cli). +* Mbed OS target board with build in radio, OR RF shield with Mbed OS driver + +## Setting up the application + +### Add your RF driver + +When using RF shield, you need to configure it to be a default RF driver and instruct Mbed OS that RF driver is present. For example, configuring Atmel RF driver to provide default driver: + +``` + "target_overrides": { + "*": { + "target.device_has_add": ["802_15_4_RF_PHY"], + "atmel-rf.provide-default": true +``` + +### Checking platform support + +Check that your choice of platform is supported by your choice of toolchain: + +``` +mbed compile --supported +``` + +**Note:** Targets are often abbreviated from the full model names. In the case of `FRDM-K64F` the target is `K64F`. + +## Run tests + +You can use this application in interactive or automated mode. + +### Interactive mode + +To set the application to interactive mode: + +1. Build the application. +``` +mbed test --compile --icetea -t TOOLCHAIN -m TARGET_PLATFORM -DICETEA_MAC_TESTER_ENABLED --test-config NANOSTACK_MAC_TESTER -n address_read_and_write,send_data,send_data_indirect,send_large_payloads,create_and_join_PAN,ED_scan +``` +2. Connect your board and copy the compiled application binary from the `BUILD/tests/TARGET_PLATFORM/TOOLCHAIN/TEST_APPS/device/nanostack_mac_tester/` folder to the board. +3. Wait for the device to flash the binary. +4. Open a serial connection with a program such as PuTTY, screen or minicom. The default baudrate is 115200. +5. Press the reset button on the board. The Arm Mbed logo and trace appears in the terminal window. + +If the driver registration and SW MAC creation was successful, the application is ready to receive commands. + +To start off, type `help` to list all commands available and furthermore `help ` to print detailed information about a specific command. + +### Automated mode + +``` +mbed test --clean --compile --run --icetea -t TOOLCHAIN -m TARGET_PLATFORM -DICETEA_MAC_TESTER_ENABLED --test-config NANOSTACK_MAC_TESTER -n address_read_and_write,send_data,send_data_indirect,send_large_payloads,create_and_join_PAN,ED_scan +``` + +Many of the provided testcases have a `self.channel` variable in the `setUp()` function for setting the RF channel. The default channel is 11. If you wish to run a test on another channel, you will need to change it manually in TEST_APPS/testcases/nanostack_mac_tester/. + +Some testcases also use a secondary channel for transmitting and will use the next higher channel for that purpose. If the given channel is 26, the secondary channel will default to 25. + +### Test cases + +The automated test set runs the following testcases included in the repository under `TEST_APPS/testcases/nanostack_mac_tester/`. +* Create and join PAN +* Direct data transmission(Transmission between two devices) +* Indirect data transmission(Transmission between two devices with one device acting as intermediary) +* ED scan(Energy Density scanning) +* Address read and write +* Large data transmission + +### Considerations + +* Devices need to be power cycled if they are unresponsive to test framework commands even after resetting. +* Devices can be enclosed in an RF isolation box to improve the consistency of test results. +* Some boards and radio modules come with a PCB trace antenna, instead of an SMD antenna, and need to be spaced further apart to decrease interference. \ No newline at end of file diff --git a/TEST_APPS/device/nanostack_mac_tester/main.cpp b/TEST_APPS/device/nanostack_mac_tester/main.cpp new file mode 100644 index 0000000000..b1e99bcca4 --- /dev/null +++ b/TEST_APPS/device/nanostack_mac_tester/main.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2017, 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. + */ +#include "mbed.h" +#include "rtos.h" +#include "sw_mac.h" +#include "ns_hal_init.h" +#define MBED_CMDLINE_MAX_LINE_LENGTH 250 +#include "ns_cmdline.h" + +#include "mac_commands.h" + +#define HEAP_FOR_MAC_TESTER_SIZE 10000 +#define RX_BUFFER_SIZE 512 + +#define ATMEL 1 +#define MCR20 2 +#define OTHER 3 + +#define TRACE_GROUP "Main" +#include "mbed-trace/mbed_trace.h" + +#include "NanostackRfPhy.h" + +#if !DEVICE_802_15_4_PHY +#error [NOT_SUPPORTED] No 802.15.4 RF driver found for this target +#endif + +#ifndef ICETEA_MAC_TESTER_ENABLED +#error [NOT_SUPPORTED] Skipping Nanostack MAC tester application. +#endif + +extern mac_api_s *mac_interface; +RawSerial pc(USBTX, USBRX); +osThreadId_t main_thread; +static CircularBuffer rx_buffer; +static uint8_t ns_heap[HEAP_FOR_MAC_TESTER_SIZE]; + +static void app_heap_error_handler(heap_fail_t event) +{ + tr_error("Heap error (%d), app_heap_error_handler()", event); + switch (event) { + case NS_DYN_MEM_NULL_FREE: + case NS_DYN_MEM_DOUBLE_FREE: + case NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID: + case NS_DYN_MEM_POINTER_NOT_VALID: + case NS_DYN_MEM_HEAP_SECTOR_CORRUPTED: + case NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED: + break; + default: + break; + } + while (1); +} + +static void rx_interrupt(void) +{ + uint8_t c = pc.getc(); + rx_buffer.push(c); + if (main_thread != NULL) { + osThreadFlagsSet(main_thread, 1); + } +} + +static void handle_rx_data(void) +{ + bool exit = false; + uint8_t data; + + while (1) { + exit = !rx_buffer.pop(data); + if (exit) { + break; + } + cmd_char_input(data); + } +} + + +static int mac_prepare(void) +{ + NanostackRfPhy &rf_phy = NanostackRfPhy::get_default_instance(); + int8_t rf_driver_id = rf_phy.rf_register(); + uint8_t rf_eui64[8]; + + if (rf_driver_id < 0) { + tr_error("Failed to register RF driver."); + return -1; + } + rf_phy.get_mac_address(rf_eui64); + mac_description_storage_size_t mac_description; + mac_description.device_decription_table_size = DEVICE_DESCRIPTOR_TABLE_SIZE; /** MAC Device description list size */ + mac_description.key_description_table_size = KEY_DESCRIPTOR_TABLE_SIZE; /** MAC Key description list size */ + mac_description.key_lookup_size = LOOKUP_DESCRIPTOR_TABLE_SIZE; /** Key description key lookup list size */ + mac_description.key_usage_size = USAGE_DESCRIPTOR_TABLE_SIZE; /** Key description key usage list size */ + tr_info("Registered RF driver with id: %hhu, EUI64: %s", rf_driver_id, mbed_trace_array(rf_eui64, 8)); + mac_interface = ns_sw_mac_create(rf_driver_id, &mac_description); + if (!mac_interface) { + tr_error("Failed to create SW MAC."); + return -2; + } + + return mac_interface->mac_initialize(mac_interface, mac_data_confirm_handler, + mac_data_indication_handler, mac_purge_confirm_handler, mac_mlme_confirm_handler, + mac_mlme_indication_handler, rf_driver_id); +} + +static void cmd_ready_cb(int retcode) +{ + cmd_next(retcode); +} + +static void trace_printer(const char *str) +{ + printf("%s\n", str); + cmd_output(); + fflush(stdout); +} + +int main(void) +{ + main_thread = ThisThread::get_id(); + pc.baud(MBED_CONF_PLATFORM_STDIO_BAUD_RATE); + pc.attach(rx_interrupt); + ns_hal_init(ns_heap, HEAP_FOR_MAC_TESTER_SIZE, app_heap_error_handler, NULL); + mbed_trace_init(); + mbed_trace_print_function_set(trace_printer); + cmd_init(&default_cmd_response_out); + cmd_set_ready_cb(cmd_ready_cb); + mac_commands_init(); + + if (mac_prepare() != 0) { + return -1; + } + tr_info("Created driver & SW MAC"); + + while (true) { + ThisThread::flags_wait_any(1); + handle_rx_data(); + } + return 0; +} diff --git a/TEST_APPS/device/nanostack_mac_tester/mbed_app.json b/TEST_APPS/device/nanostack_mac_tester/mbed_app.json new file mode 100644 index 0000000000..d86bfd2dc7 --- /dev/null +++ b/TEST_APPS/device/nanostack_mac_tester/mbed_app.json @@ -0,0 +1,16 @@ +{ + "macros": ["MBED_TRACE_LINE_LENGTH=200", "OS_TASKCNT=4", "OS_IDLESTKSIZE=32"], + "target_overrides": { + "*": { + "nanostack.configuration": "lowpan_host", + "platform.stdio-convert-newlines": true, + "platform.stdio-baud-rate": 115200, + "mbed-mesh-api.heap-size": 6000, + "nanostack-hal.event_loop_thread_stack_size": 2000, + "mbed-trace.enable": true, + "nsapi.default-stack": "LWIP", + "target.device_has_add": ["802_15_4_PHY"], + "atmel-rf.provide-default": true + } + } +} diff --git a/TEST_APPS/device/nanostack_mac_tester/source/mac_commands.cpp b/TEST_APPS/device/nanostack_mac_tester/source/mac_commands.cpp new file mode 100644 index 0000000000..ceef2f6a39 --- /dev/null +++ b/TEST_APPS/device/nanostack_mac_tester/source/mac_commands.cpp @@ -0,0 +1,1644 @@ +/* + * Copyright (c) 2017, 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. + */ +#include "mac_commands.h" + +//Need to disable filtering until mac_filter_api.h in mbed-os is updated +#define DISABLE_FILTERING + +#define TRACE_GROUP "MAC" + +#define MAN_MAC_START "start --- Starts a PAN\n"\ + " --pan_id PAN id in hex, default: 0x1234\n"\ + " --logical_channel Operated logical channel, default: 11 (0-26)\n"\ + " --channel_page Operated channel page, default: 0 (0-2)\n"\ + " --start_time Time at which to start sending beacons\n"\ + " default: 0\n"\ + " --beacon_order How often are beacons transmitted\n"\ + " default: 15 (0-15, 15 = never)\n"\ + " --super_frame_order Length of the superframe's active portion\n"\ + " if beacon_order is 15, this option is ignored\n"\ + " default: 15 (0-15)\n"\ + " --pan_coordinator Is this device the PAN coordinator?\n"\ + " default: true\n"\ + " --battery_life_extension Disable beaconing device periodically\n"\ + " to save power? default: false\n"\ + " --coord_realignment If true, coordinator realignment command\n"\ + " is sent prior to changing\n"\ + " the superframe configuration default: false\n" + +#define MAN_MAC_SCAN "scan --- Perform a scan\n"\ + " --scan_type What type of scan to perform, 0=ED, 1=active\n"\ + " 2=passive, 3=orphan, default: 1\n"\ + " --channel_page_enum default: 0 (0-10)\n"\ + " --channel_mask Bitmap of the channels on which to perform\n"\ + " the scan, lower 27-bits are used\n"\ + " bit 0 corresponds to channel 0 and so forth\n"\ + " default: 0x07FFF800 (channels 11-26)\n"\ + " --scan_duration How long to spend in each channel,\n"\ + " aBaseSuperFrameDuration * (2^n + 1) symbols\n"\ + " default: 5 (0-14)\n"\ + " --channel_page The channel page on which to perform the scan\n"\ + " default: 0 (0-31)\n"\ + MAN_MAC_SECURITY + +#define MAN_MAC_DATA "data --- Send arbitrary data\n"\ + " --src_addr_mode Source addressing mode, 0=no address, 1=reserved\n"\ + " 2=16-bit address, 3=64-bit address\n"\ + " default: 3 (0-3)\n"\ + " --dst_addr_mode Destination addressing mode, same as above\n"\ + " default: 3 (0-3)\n"\ + " --dst_pan_id Destination PAN id in hex\n"\ + " default: 0x1234 (0x0-0xFFFF)\n"\ + " --dst_addr Destination address, default: 00:00:00:...\n"\ + " --msdu_length Length of the data to send, default: 0 (0-255)\n"\ + " --msdu Data to transmit, default: \n"\ + " --msdu_handle Handle of this MSDU, default: 0 (0-255)\n"\ + " --tx_ack_req Is ack required for this transmission?\n"\ + " default: true\n"\ + " --indirect_tx Transmit indirectly? default: false\n"\ + " --pending_bit Specifies whether more fragments (higher layer)\n"\ + " are to be sent, default: false\n"\ + " --wait_for_confirm Should we block further commands until we have\n"\ + " received a data confirmation, default: true\n"\ + MAN_MAC_SECURITY + +#define MAN_MAC_POLL "poll --- Poll the coordinator for data\n"\ + " --coord_addr_mode Coordinator addressing mode, 2=16-bit address\n"\ + " 3=64-bit address, default: 3 (2-3)\n"\ + " --coord_pan_id Coordinator PAN id in hex\n"\ + " default: 0x1234 (0x0-0xFFFF)\n"\ + " --coord_address Coordinator address, default 00:00:00:...\n"\ + MAN_MAC_SECURITY + +#define MAN_MAC_PURGE "purge --- Remove a transmission from the queue\n"\ + " --msdu_handle Handle of the MSDU to be removed\n"\ + " default: 0 (0-255)\n"\ + +#define MAN_MAC_SET "mlme-set --- Set a specified PIB attribute\n"\ + " --attr ID of the attribute to set in hex (0x0-0xFF)\n"\ + " --attr_index <0-255> Index of the attribute, default: 0 (0-255)\n"\ + " --value_ascii Specify the set value as an ASCII string\n"\ + " --value_bytes Value as a string of bytes\n"\ + " --value_uint8/16/32 Value as a uint8, uint16, or uint32\n"\ + " Max value for uint32 is the max value for int32\n"\ + " --value_size Size of the value in bytes (0-255)\n" + +#define MAN_MAC_GET "mlme-get --- Get a specified PIB attribute\n"\ + " --attr ID of the attribute we want to get in hex (0x0-0xFF)\n"\ + " --attr_index Index of the attribute, default: 0 (0-255)\n" + +#define MAN_MAC_RESET "mlme-reset --- Reset the MAC sublayer\n"\ + " --set_default_pib When set to true, PIB attributes are set to\n"\ + " their default values\n"\ + " If set to false, PIB attributes retain\n"\ + " their values, default: true\n" + +#define MAN_MAC_ADDR "addr --- Configure 16/64-bit MAC addresses\n"\ + " having no options will display the addresses\n"\ + " --16-bit 16-bit MAC address in hex (0x0-0xFFFF)\n"\ + " --64-bit 64-bit MAC address\n" + +#define MAN_MAC_SECURITY " --security_level 0=no security, 1=MIC32, 2=MIC64, 3=MIC128,\n"\ + " 4=ENC, 5=ENC+MIC32, 6=ENC+MIC64, 7=ENC+MIC128\n"\ + " default: 0\n"\ + " --key_id_mode 0=implicit, 1=default key source\n"\ + " 2=2-byte key source\n"\ + " 3=8-byte key source, default: 0 (0-3)\n"\ + " --key_index Which key to use, default: 0 (0-255)\n"\ + " --key_source The originator of the key to be used\n" + +#define MAN_MAC_KEY "key --- Configure or add key descriptors\n"\ + "config --- Configure parameters for key descriptor\n"\ + " --key Actual security key, 16 bytes\n"\ + " default: C0:C1:C2:...:CF\n"\ + " --key_id_lookup_list_entries Amount of entries in the key's lookup\n"\ + " --key_device_list_entries ...device...\n"\ + " --key_usage_list_entries and usage list, default: 2 (0-255)\n"\ + " --lookup_index Which entry of the lookup list\n"\ + " are we accessing? default: 0 (0-255)\n"\ + " --lookup_data The lookup data for this key\n"\ + " length is 9 bytes regardless of\n"\ + " the next option\n"\ + " --lookup_data_size How large is the lookup data? (0-1)\n"\ + " 0=5 bytes, 1=9 bytes\n"\ + " --device_list_index Which entry of the device list\n"\ + " are we accessing, default: 0 (0-255)\n"\ + " --device_descriptor_handle Which entry in our neighbour table\n"\ + " do we want to use this key with\n"\ + " default: 0 (0-255)\n"\ + " --unique_device Is the device unique to the key?\n"\ + " --blacklisted Is the device blacklisted?\n"\ + " --usage_list_index Which entry of the usage list\n"\ + " are we accessing, default: 0 (0-255)\n"\ + " --frame_type What type of frame do we want to\n"\ + " use this key with? (0-3)\n"\ + " 0=beacon, 1=data, 2=ACK, 3=command\n"\ + " --command_frame_identifier Type of the command frame (1-9)\n"\ + " 1=association request\n"\ + " 2=association response\n"\ + " 3=disassociation notification\n"\ + " 4=data request\n"\ + " 5=PAN id conflict notification\n"\ + " 6=orphan notification\n"\ + " 7=beacon request\n"\ + " 8=coordinator realigment\n"\ + " 9=GTS request\n"\ + "add --- Add the key into the key descriptor table\n"\ + " --index Index in the key table (0-255)\n" + +#define MAN_MAC_ADD_NEIGHBOUR "add-neigh --- Add an entry to the neighbour table\n"\ + " --frame_ctr Frame counter for this neighbour\n"\ + " --mac16 16-bit MAC address in hex (0x0-0xFFFF)\n"\ + " --mac64 64-bit MAC address\n"\ + " --pan_id PAN id (0x0-0xFFFF)\n"\ + " --index Index in the neighbour table (0-255)\n" + +#define MAN_MAC_FILTER "filter --- Configure MAC layer filtering\n"\ + "start --- Start a generic filter in blacklist, whitelist or fixed mode\n"\ + " --mode Set the filtering mode, values: allow|block|fixed\n"\ + " --lqi_m LQI multiplier (fixed mode only)\n"\ + " --dbm_m dBm multiplier (fixed mode only)\n"\ + "add --- Add a filter by manually supplying values, or using a preset mode\n"\ + " --lqi_m LQI multiplier\n"\ + " --lqi_add Value added to the LQI\n"\ + " --dbm_m dBm multiplier\n"\ + " --dbm_add Value added to the dBm\n"\ + " --mode Filtering mode, values: allow|block|fixed\n"\ + " --short 16-bit address in hex to filter (0x0-0xFFFF)\n"\ + " --long 64-bit address as bytes to filter\n"\ + "remove --- Remove a filter\n"\ + " --short 16-bit address to remove from filter (0x0-0xFFFF)\n"\ + " --long 64-bit address to remove from filter\n"\ + "clear --- Clear all filters excluding the default one\n"\ + "stop --- Stop filtering completely\n"\ + +#define MAN_MAC_CONFIG_STATUS "config-status --- Configure expected status codes\n"\ + " having no options will display configured statuses\n"\ + " default: 0 (MLME_SUCCESS) for all\n"\ + " --data_conf MCPS-DATA.confirm (0-255)\n"\ + " --data_ind MCPS-DATA.indication (0-255)\n"\ + " --get MLME-GET.confirm (0-255)\n"\ + " --scan MLME-SCAN.confirm (0-255)\n"\ + " --poll MLME-POLL.confirm (0-255)\n"\ + " --purge MCPS-PURGE.confirm (0-255)\n"\ + " --comm_status MLME-COMM-STATUS.indication (0-255)\n"\ + " --list List all statuses\n"\ + " --reset Reset all statuses to default values\n" + +#define MAN_MAC_FIND_BEACON "find-beacon --- Search for a PAN in the\n"\ + " results of the last scan\n"\ + " --data Beacon data transmitted in the beacon\n" + +#define MAN_MAC_WAIT "wait --- Wait for data sent directly for a\n"\ + " specified amount of milliseconds\n"\ + " --timeout Milliseconds to wait, default: 1000\n" + +#define MAN_MAC_ED_ANALYZE "analyze-ed Channel to analyze (11-26)\n"\ + " --above Check if the ED value is above a given value\n"\ + " --below Check if the ED value is below a given value\n" + +#define MAN_RESET "reset --- Reset MCPS and MLME structures to default values\n" + +#define MAN_SILENT "silent-mode --- When enabled, doesn't print extended information\n"\ + " of MCPS/MLME primitives\n" + +mac_api_s *mac_interface = NULL; +static bool wait_for_confirm = true; +static bool silent_mode = false; +static volatile unsigned int data_count = 0; + +static mlme_start_t start_req = { + 0x1234, /*PANId*/ + 11, /*LogicalChannel*/ + 0, /*ChannelPage*/ + 0, /*StartTime*/ + 15, /*BeaconOrder*/ + 15, /*SuperframeOrder*/ + true, /*PANCoordinator*/ + false, /*BatteryLifeExtension*/ + false, /*CoordRealignment*/ +}; + +static mlme_scan_t scan_req = { + MAC_ACTIVE_SCAN, /*ScanType*/ + { + CHANNEL_PAGE_0, /*channel_page (enum)*/ + 0x07FFF800 /*channel_mask*/ + }, + 5, /*ScanDuration*/ + 0, /*ChannelPage*/ + { + 0, /*SecurityLevel*/ + 0, /*KeyIdMode*/ + 0, /*KeyIndex*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /*Keysource*/ + } +}; + +static mcps_data_req_t data_req = { + 3, /*SrcAddrMode*/ + 3, /*DstAddrMode*/ + 0x1234, /*DstPANId*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*DstAddr*/ + 0, /*msduLength*/ + NULL, /*msdu*/ + 0, /*msduHandle*/ + true, /*TxAckReq*/ + false, /*IndirectTx*/ + false, /*PendingBit*/ + false, /*SeqNumSuppressed*/ + false, /*PanIdSuppressed*/ + { + 0, /*SecurityLevel*/ + 0, /*KeyIdMode*/ + 0, /*KeyIndex*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /*Keysource*/ + } +}; + +static mlme_poll_t poll_req = { + 3, /*CoordAddrMode*/ + 0x1234, /*CoordPANId*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*CoordAddress*/ + { + 0, /*SecurityLevel*/ + 0, /*KeyIdMode*/ + 0, /*KeyIndex*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /*Keysource*/ + } +}; + +static mcps_purge_t purge_req = { + 0 /*msduHandle*/ +}; + +static mlme_set_t set_req = { + (mlme_attr_t)0x39, /*attr*/ + 0, /*attr_index*/ + NULL, /*value_pointer*/ + 0 /*value_size*/ +}; + +static mlme_get_t get_req = { + (mlme_attr_t)0x39, /*attr*/ + 0 /*attr_index*/ +}; + +static mlme_reset_t reset_req = { + true /*SetDefaultPIB*/ +}; + +static mlme_key_id_lookup_descriptor_t lookup_descriptors[LOOKUP_DESCRIPTOR_TABLE_SIZE]; +static mlme_key_device_descriptor_t device_descriptors[DEVICE_DESCRIPTOR_TABLE_SIZE]; +static mlme_key_usage_descriptor_t usage_descriptors[USAGE_DESCRIPTOR_TABLE_SIZE]; +static mlme_key_descriptor_entry_t key_descriptor = { + lookup_descriptors, /*KeyIdLookupList*/ + LOOKUP_DESCRIPTOR_TABLE_SIZE, /*KeyIdLookupListEntries*/ + device_descriptors, /*KeyDeviceList*/ + DEVICE_DESCRIPTOR_TABLE_SIZE, /*KeyDeviceListEntries*/ + usage_descriptors, /*KeyUsageList*/ + USAGE_DESCRIPTOR_TABLE_SIZE, /*KeyUsageListEntries*/ + {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF} /*Key*/ +}; + +struct status_list_t { + uint8_t data_conf; + uint8_t get_conf; + uint8_t scan_conf; + uint8_t poll_conf; + uint8_t purge_conf; + uint8_t comm_status_ind; + uint8_t data_ind_len; + uint8_t *data_ind; +}; + +static struct status_list_t expected_statuses = { + MLME_SUCCESS, + MLME_SUCCESS, + MLME_SUCCESS, + MLME_SUCCESS, + MLME_SUCCESS, + MLME_SUCCESS, + 0, + NULL +}; + +struct beacon_list_t { + size_t count; + char *beacons[MLME_MAC_RES_SIZE_MAX]; + uint8_t beacon_lengths[MLME_MAC_RES_SIZE_MAX]; +}; + +static struct beacon_list_t received_beacons = {}; + +struct ed_scan_result_list_t { + uint8_t count; + uint8_t channel[MLME_MAC_RES_SIZE_MAX]; + uint8_t ED_values[MLME_MAC_RES_SIZE_MAX]; +}; + +static struct ed_scan_result_list_t last_ed_results; + +static void print_security(const mlme_security_t *key) +{ + if (key->SecurityLevel > 0) { + cmd_printf("Key.SecurityLevel: %u\n", key->SecurityLevel); + cmd_printf("Key.KeyIdMode: %u\n", key->KeyIdMode); + cmd_printf("Key.KeyIndex: %hhu\n", key->KeyIndex); + cmd_printf("Key.Keysource %s\n", trace_array(key->Keysource, 8)); + } +} + +static void print_PAN_descriptor(const mlme_pan_descriptor_t *desc) +{ + cmd_printf("PANDescriptor.CoordAddrMode: %u\n", desc->CoordAddrMode); + cmd_printf("PANDescriptor.CoordPANId: 0x%04X\n", desc->CoordPANId); + cmd_printf("PANDescriptor.CoordAddress: %s\n", trace_array(desc->CoordAddress, 8)); + cmd_printf("PANDescriptor.LogicalChannel: %hhu\n", desc->LogicalChannel); + cmd_printf("PANDescriptor.ChannelPage: %hhu\n", desc->ChannelPage); + cmd_printf("PANDescriptor.SuperframeSpec: %02x:%02x\n", desc->SuperframeSpec[0], desc->SuperframeSpec[1]); + cmd_printf("PANDescriptor.GTSPermit: %s\n", desc->GTSPermit ? "true" : "false"); + cmd_printf("PANDescriptor.LinkQuality: %hhu\n", desc->LinkQuality); + cmd_printf("PANDescriptor.Timestamp: %lu\n", desc->Timestamp); + cmd_printf("PANDescriptor.SecurityFailure: %hhu\n", desc->SecurityFailure); + print_security(&desc->Key); +} + +static int handle_security_args(int argc, char *argv[], mlme_security_t *key) +{ + char *str; + int32_t val; + + if (cmd_parameter_int(argc, argv, "--security_level", &val)) { + if (val >= 0 && val <= 7) { + key->SecurityLevel = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--key_id_mode", &val)) { + if (val >= 0 && val <= 3) { + key->KeyIdMode = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--key_index", &val)) { + if (val >= 0 && val <= 255) { + key->KeyIndex = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_val(argc, argv, "--key_source", &str)) { + if (strlen(str) == 2 * 8 + 7) { + if (string_to_bytes(str, key->Keysource, 8) != 0) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + return CMDLINE_RETCODE_SUCCESS; +} + +static void add_beacon(const uint8_t *beacon, uint8_t len) +{ + if (received_beacons.count >= MLME_MAC_RES_SIZE_MAX) { + tr_warn("List of received beacons is full. Discarding %s <%.*s>", trace_array(beacon, len), len, beacon); + return; + } + unsigned int cur_beacon = received_beacons.count; + received_beacons.beacon_lengths[cur_beacon] = len; + received_beacons.beacons[cur_beacon] = (char *)ns_dyn_mem_temporary_alloc(len <= 75 ? 75 : len); + if (len != 0) { + std::memcpy(received_beacons.beacons[cur_beacon], beacon, len); + } + ++received_beacons.count; +} + +static void clear_beacons(void) +{ + for (unsigned int i = 0; i < received_beacons.count; ++i) { + ns_dyn_mem_free(received_beacons.beacons[i]); + received_beacons.beacons[i] = NULL; + received_beacons.beacon_lengths[i] = 0; + } + received_beacons.count = 0; +} + +void mac_commands_init(void) +{ + cmd_add("start", mac_start_command, "Start a PAN", MAN_MAC_START); + cmd_add("scan", mac_scan_command, "Perform a scan", MAN_MAC_SCAN); + cmd_add("data", mac_data_command, "Send data", MAN_MAC_DATA); + cmd_add("poll", mac_poll_command, "Poll for data", MAN_MAC_POLL); + cmd_add("purge", mac_purge_command, "Purge data from the transmission queue", MAN_MAC_PURGE); + cmd_add("mlme-set", mac_set_command, "Writes a given value to the PIB attribute", MAN_MAC_SET); + cmd_add("mlme-get", mac_get_command, "Gets the value of a given PIB attribute", MAN_MAC_GET); + cmd_add("mlme-reset", mac_reset_command, "Resets the MAC sublayer to default values", MAN_MAC_RESET); + cmd_add("addr", mac_address_command, "Configure MAC addresses", MAN_MAC_ADDR); + cmd_add("key", mac_key_command, "Configure or add security keys", MAN_MAC_KEY); + cmd_add("add-neigh", mac_add_neighbour_command, "Add a device to the neighbour table", MAN_MAC_ADD_NEIGHBOUR); + cmd_add("filter", mac_filter_command, "Add or remove filters based on MAC addresses", MAN_MAC_FILTER); + cmd_add("config-status", mac_config_status_command, "Set expected return statuses for confirmations and indications", MAN_MAC_CONFIG_STATUS); + cmd_add("find-beacon", mac_find_beacon_command, "Find a PAN by beacon data", MAN_MAC_FIND_BEACON); + cmd_add("wait", mac_wait_command, "Wait for data", MAN_MAC_WAIT); + cmd_add("analyze-ed", mac_analyze_ed_command, "Analyze the results of the last ED scan", MAN_MAC_ED_ANALYZE); + cmd_add("reset", reset_command, "Reset MCPS/MLME structures to default values", MAN_RESET); + cmd_add("silent-mode", silent_mode_command, "Stop printing fields of MCPS/MLME structures", MAN_SILENT); +} + +void mac_data_confirm_handler(const mac_api_t *api, const mcps_data_conf_t *data) +{ + cmd_printf("MCPS-DATA.confirm\n"); + if (!silent_mode) { + cmd_printf("msduHandle: %hhu\n", data->msduHandle); + cmd_printf("status: %hhu (%s)\n", data->status, mlme_status_string(data->status)); + cmd_printf("timestamp: %lu\n", data->timestamp); + cmd_printf("cca_retries:%hhu\n", data->cca_retries); + cmd_printf("tx_retries: %hhu\n", data->tx_retries); + } + if (data->status == expected_statuses.data_conf) { + cmd_ready(CMDLINE_RETCODE_SUCCESS); + } else { + cmd_ready(CMDLINE_RETCODE_FAIL); + } +} + +void mac_data_indication_handler(const mac_api_t *api, const mcps_data_ind_t *data) +{ + cmd_printf("MCPS-DATA.indication\n"); + if (!silent_mode) { + cmd_printf("SrcAddrMode: %u\n", data->SrcAddrMode); + cmd_printf("SrcPANId: 0x%04X\n", data->SrcPANId); + cmd_printf("SrcAddr: %s\n", trace_array(data->SrcAddr, 8)); + cmd_printf("DstAddrMode: %u\n", data->DstAddrMode); + cmd_printf("DstPANId: 0x%04X\n", data->DstPANId); + cmd_printf("DstAddr: %s\n", trace_array(data->DstAddr, 8)); + cmd_printf("mpduLinkQuality:%hhu\n", data->mpduLinkQuality); + cmd_printf("signal_dbm: %hhi\n", data->signal_dbm); + cmd_printf("timestamp: %lu\n", data->timestamp); + cmd_printf("DSN: %hhi\n", data->DSN); + print_security(&data->Key); + cmd_printf("msduLength %hu\n", data->msduLength); + cmd_printf("msdu_ptr: %s <%.*s>\n", trace_array(data->msdu_ptr, data->msduLength), data->msduLength, data->msdu_ptr); + } + if (data->msdu_ptr && expected_statuses.data_ind) { + if (data->msduLength != expected_statuses.data_ind_len) { + return; + } + if (strncmp((const char *)data->msdu_ptr, (const char *)expected_statuses.data_ind, expected_statuses.data_ind_len) == 0) { + ++data_count; + } else { + tr_warn("Received unexpected data!"); + } + } +} + +void mac_purge_confirm_handler(const mac_api_t *api, mcps_purge_conf_t *data) +{ + cmd_printf("MCPS-PURGE.confirm\n"); + if (!silent_mode) { + cmd_printf("msduHandle: %hhu\n", data->msduHandle); + cmd_printf("status: %hhu (%s)\n", data->status, mlme_status_string(data->status)); + } + if (data->status == expected_statuses.purge_conf) { + cmd_ready(CMDLINE_RETCODE_SUCCESS); + } else { + cmd_ready(CMDLINE_RETCODE_FAIL); + } +} + +void mac_mlme_confirm_handler(const mac_api_t *api, mlme_primitive id, const void *data) +{ + switch (id) { + case MLME_ASSOCIATE: { + break; + } + case MLME_DISASSOCIATE: { + break; + } + case MLME_GET: { + mlme_get_conf_t *get_data = (mlme_get_conf_t *)data; + cmd_printf("MLME-GET.confirm\n"); + if (!silent_mode) { + cmd_printf("status: %hhu (%s)\n", get_data->status, mlme_status_string(get_data->status)); + cmd_printf("attr: %hhu\n", get_data->attr); + cmd_printf("attr_index: %hhu\n", get_data->attr_index); + cmd_printf("value_pointer: %s\n", trace_array((uint8_t *)get_data->value_pointer, get_data->value_size)); + cmd_printf("value_size: %hhu\n", get_data->value_size); + } + if (get_data->status == expected_statuses.get_conf) { + cmd_ready(CMDLINE_RETCODE_SUCCESS); + } else { + cmd_ready(CMDLINE_RETCODE_FAIL); + } + break; + } + case MLME_GTS: { + break; + } + case MLME_RESET: { + break; + } + case MLME_RX_ENABLE: { + break; + } + case MLME_SCAN: { + mlme_scan_conf_t *scan_data = (mlme_scan_conf_t *)data; + cmd_printf("MLME-SCAN.confirm\n"); + if (!silent_mode) { + cmd_printf("status: %hhu (%s)\n", scan_data->status, mlme_status_string(scan_data->status)); + cmd_printf("ScanType: %u\n", scan_data->ScanType); + cmd_printf("ChannelPage: %hhu\n", scan_data->ChannelPage); + cmd_printf("UnscannedChannels: 0x%08lX\n", scan_data->UnscannedChannels.channel_mask[0]); + cmd_printf("ResultListSize: %hhu\n", scan_data->ResultListSize); + } + for (unsigned int i = 0; i < scan_data->ResultListSize; ++i) { + if (scan_data->ScanType == MAC_ED_SCAN_TYPE) { + cmd_printf("Channel %d ED value: %hhu\n", channel_from_mask(scan_req.ScanChannels.channel_mask[0], i), scan_data->ED_values[i]); + memcpy(last_ed_results.ED_values, scan_data->ED_values, scan_data->ResultListSize); + last_ed_results.count = scan_data->ResultListSize; + for (int i = 0; i < scan_data->ResultListSize; ++i) { + last_ed_results.channel[i] = channel_from_mask(scan_req.ScanChannels.channel_mask[0], i); + } + } else if (scan_data->ScanType == MAC_PASSIVE_SCAN) { + print_PAN_descriptor(scan_data->PAN_values[i]); + } + } + if (scan_data->status == expected_statuses.scan_conf || scan_data->status == MLME_LIMIT_REACHED) { + cmd_ready(CMDLINE_RETCODE_SUCCESS); + } else { + cmd_ready(CMDLINE_RETCODE_FAIL); + } + break; + } + case MLME_SET: { + break; + } + case MLME_START: { + break; + } + case MLME_POLL: { + mlme_poll_conf_t *poll_data = (mlme_poll_conf_t *)data; + cmd_printf("MLME-POLL.confirm\n"); + if (!silent_mode) { + cmd_printf("status: %hhu (%s)\n", poll_data->status, mlme_status_string(poll_data->status)); + cmd_printf("data_count %u\n", data_count); + } + if (expected_statuses.poll_conf == MLME_SUCCESS) { + if (data_count == 1 && poll_data->status == MLME_SUCCESS) { + cmd_ready(CMDLINE_RETCODE_SUCCESS); + } else { + cmd_ready(CMDLINE_RETCODE_FAIL); + } + } else if (expected_statuses.poll_conf == poll_data->status) { + cmd_ready(CMDLINE_RETCODE_SUCCESS); + } else { + cmd_ready(CMDLINE_RETCODE_FAIL); + } + break; + } + default: { + cmd_ready(CMDLINE_RETCODE_COMMAND_NOT_IMPLEMENTED); + break; + } + } +} + +void mac_mlme_indication_handler(const mac_api_t *api, mlme_primitive id, const void *data) +{ + switch (id) { + case MLME_ASSOCIATE: { + break; + } + case MLME_DISASSOCIATE: { + break; + } + case MLME_BEACON_NOTIFY: { + const mlme_beacon_ind_t *beacon_ind = (mlme_beacon_ind_t *)data; + cmd_printf("MLME-BEACON-NOTIFY.indication\n"); + if (!silent_mode) { + cmd_printf("BSN: %hhu\n", beacon_ind->BSN); + print_PAN_descriptor(&beacon_ind->PANDescriptor); + cmd_printf("PendAddrSpec.short_address_count %u\n", beacon_ind->PendAddrSpec.short_address_count); + cmd_printf("PendAddrSpec.extended_address_count %u\n", beacon_ind->PendAddrSpec.extended_address_count); + cmd_printf("AddrList %s\n", trace_array(beacon_ind->AddrList, beacon_ind->PendAddrSpec.short_address_count * 2 + + beacon_ind->PendAddrSpec.extended_address_count * 8)); + cmd_printf("beacon_data_length %hu\n", beacon_ind->beacon_data_length); + cmd_printf("beacon_data %s\n", trace_array(beacon_ind->beacon_data, beacon_ind->beacon_data_length)); + } + add_beacon(beacon_ind->beacon_data, beacon_ind->beacon_data_length); + break; + } + case MLME_GTS: { + break; + } + case MLME_ORPHAN: { + break; + } + case MLME_COMM_STATUS: { + cmd_printf("MLME-COMM-STATUS.indication\n"); + const mlme_comm_status_t *comm_status_ind_data = (mlme_comm_status_t *)data; + if (!silent_mode) { + cmd_printf("PANId: 0x%04X\n", comm_status_ind_data->PANId); + cmd_printf("SrcAddrMode: %u\n", comm_status_ind_data->SrcAddrMode); + cmd_printf("SrcAddr: %s\n", trace_array(comm_status_ind_data->SrcAddr, 8)); + cmd_printf("DstAddrMode: %u\n", comm_status_ind_data->DstAddrMode); + cmd_printf("DstAddr: %s\n", trace_array(comm_status_ind_data->DstAddr, 8)); + cmd_printf("status: %hhu (%s)\n", comm_status_ind_data->status, mlme_status_string(comm_status_ind_data->status)); + print_security(&comm_status_ind_data->Key); + } + break; + } + case MLME_SYNC_LOSS: { + break; + } + default: + break; + } +} + +int mac_start_command(int argc, char *argv[]) +{ + char *str; + int32_t val; + bool boolean; + + cmd_printf("MLME-START.request\n"); + if (cmd_parameter_val(argc, argv, "--pan_id", &str)) { + uint32_t pan_id = strtoul(str, NULL, 16); + if (pan_id <= 0xFFFF) { + start_req.PANId = pan_id; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--logical_channel", &val)) { + if (val >= 0 && val <= 26) { + start_req.LogicalChannel = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--channel_page", &val)) { + if (val >= 0 && val <= 2) { + start_req.ChannelPage = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--start_time", &val)) { + start_req.StartTime = val; + } + if (cmd_parameter_int(argc, argv, "--beacon_order", &val)) { + if (val >= 0 && val <= 15) { + start_req.BeaconOrder = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--super_frame_order", &val)) { + if (val >= 0 && val <= 15) { + start_req.SuperframeOrder = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_bool(argc, argv, "--pan_coordinator", &boolean)) { + start_req.PANCoordinator = boolean; + } + if (cmd_parameter_bool(argc, argv, "--battery_life_extension", &boolean)) { + start_req.BatteryLifeExtension = boolean; + } + if (cmd_parameter_bool(argc, argv, "--coord_realignment", &boolean)) { + start_req.CoordRealignment = boolean; + } + mac_interface->mlme_req(mac_interface, MLME_START, &start_req); + return CMDLINE_RETCODE_SUCCESS; +} + +int mac_scan_command(int argc, char *argv[]) +{ + char *str; + int32_t val; + + cmd_printf("MLME-SCAN.request\n"); + if (cmd_parameter_int(argc, argv, "--scan_type", &val)) { + if (val >= 0 && val <= 3) { + scan_req.ScanType = (mac_scan_type_t)val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--channel_page_enum", &val)) { + if (val >= 0 && val <= 10) { + scan_req.ScanChannels.channel_page = (channel_page_e)val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_val(argc, argv, "--channel_mask", &str)) { + scan_req.ScanChannels.channel_mask[0] = strtoul(str, NULL, 16); + } + if (cmd_parameter_int(argc, argv, "--scan_duration", &val)) { + if (val >= 0 && val <= 14) { + scan_req.ScanDuration = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--channel_page", &val)) { + if (val >= 0 && val <= 2) { + scan_req.ChannelPage = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (handle_security_args(argc, argv, &scan_req.Key) != CMDLINE_RETCODE_SUCCESS) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + clear_beacons(); + mac_interface->mlme_req(mac_interface, MLME_SCAN, &scan_req); + return CMDLINE_RETCODE_EXCUTING_CONTINUE; +} + +int mac_data_command(int argc, char *argv[]) +{ + char *str; + int32_t val; + bool boolean; + + cmd_printf("MCPS-DATA.request\n"); + if (cmd_parameter_int(argc, argv, "--src_addr_mode", &val)) { + if (val == 0 || val == 2 || val == 3) { + data_req.SrcAddrMode = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--dst_addr_mode", &val)) { + if (val == 0 || val == 2 || val == 3) { + data_req.DstAddrMode = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_val(argc, argv, "--dst_pan_id", &str)) { + uint32_t pan_id = strtoul(str, NULL, 16); + if (pan_id <= 0xFFFF) { + data_req.DstPANId = pan_id; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_val(argc, argv, "--dst_addr", &str)) { + int len = (data_req.DstAddrMode == 2 ? 2 : 8); + if (string_to_bytes(str, data_req.DstAddr, len) != 0) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--msdu_length", &val)) { + data_req.msduLength = val; + } + if (cmd_parameter_val(argc, argv, "--msdu", &str)) { + ns_dyn_mem_free(data_req.msdu); + if (strlen(str) != data_req.msduLength) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + data_req.msdu = (uint8_t *)ns_dyn_mem_temporary_alloc(data_req.msduLength); + if (data_req.msdu == NULL) { + tr_error("Failed to allocate memory for the msdu"); + return CMDLINE_RETCODE_FAIL; + } + std::memcpy(data_req.msdu, str, data_req.msduLength); + } + if (cmd_parameter_int(argc, argv, "--msdu_handle", &val)) { + if (val >= 0 && val <= 255) { + data_req.msduHandle = val; + } + } + if (cmd_parameter_bool(argc, argv, "--tx_ack_req", &boolean)) { + data_req.TxAckReq = boolean; + } + if (cmd_parameter_bool(argc, argv, "--indirect_tx", &boolean)) { + data_req.InDirectTx = boolean; + } + if (cmd_parameter_bool(argc, argv, "--pending_bit", &boolean)) { + data_req.PendingBit = boolean; + } + if (cmd_parameter_bool(argc, argv, "--wait_for_confirm", &boolean)) { + wait_for_confirm = boolean; + } + if (handle_security_args(argc, argv, &data_req.Key) != CMDLINE_RETCODE_SUCCESS) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + mac_interface->mcps_data_req(mac_interface, &data_req); + if (wait_for_confirm) { + return CMDLINE_RETCODE_EXCUTING_CONTINUE; + } + return CMDLINE_RETCODE_SUCCESS; +} + +int mac_poll_command(int argc, char *argv[]) +{ + char *str; + int32_t val; + + cmd_printf("MLME-POLL.request\n"); + data_count = 0; + if (cmd_parameter_int(argc, argv, "--coord_addr_mode", &val)) { + if (val == 2 || val == 3) { + poll_req.CoordAddrMode = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_val(argc, argv, "--coord_pan_id", &str)) { + unsigned long pan_id = strtoul(str, NULL, 16); + if (pan_id <= 0xFFFF) { + poll_req.CoordPANId = pan_id; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_val(argc, argv, "--coord_address", &str)) { + int len = (poll_req.CoordAddrMode == 2 ? 2 : 8); + if (string_to_bytes(str, poll_req.CoordAddress, len) != 0) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (handle_security_args(argc, argv, &poll_req.Key) != CMDLINE_RETCODE_SUCCESS) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + mac_interface->mlme_req(mac_interface, MLME_POLL, &poll_req); + return CMDLINE_RETCODE_EXCUTING_CONTINUE; +} + +int mac_purge_command(int argc, char *argv[]) +{ + int32_t val; + + cmd_printf("MCPS-PURGE.request\n"); + if (cmd_parameter_int(argc, argv, "--msdu_handle", &val)) { + if (val >= 0 && val <= 255) { + purge_req.msduHandle = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + mac_interface->mcps_purge_req(mac_interface, &purge_req); + return CMDLINE_RETCODE_EXCUTING_CONTINUE; +} + +int mac_set_command(int argc, char *argv[]) +{ + char *str; + int32_t val; + uint8_t val_uint8 = 0; + uint16_t val_uint16 = 0; + uint32_t val_uint32 = 0; + uint8_t *val_ptr_array = NULL; + + cmd_printf("MLME-SET.request\n"); + if (cmd_parameter_val(argc, argv, "--attr", &str)) { + uint32_t attribute = strtoul(str, NULL, 16); + if (attribute <= 255) { + set_req.attr = (mlme_attr_t)attribute; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--attr_index", &val)) { + if (val >= 0 && val <= 255) { + set_req.attr_index = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_val(argc, argv, "--value_ascii", &str)) { + val_ptr_array = (uint8_t *)ns_dyn_mem_temporary_alloc(strlen(str)); + if (val_ptr_array == NULL) { + tr_error("Failed to allocate memory for MLME-SET.request"); + return CMDLINE_RETCODE_FAIL; + } + std::memcpy(val_ptr_array, str, strlen(str)); + set_req.value_pointer = val_ptr_array; + } else if (cmd_parameter_val(argc, argv, "--value_bytes", &str)) { + size_t bytes = (strlen(str) + 1) / 3; + val_ptr_array = (uint8_t *)ns_dyn_mem_temporary_alloc(bytes); + if (val_ptr_array == NULL) { + tr_error("Failed to allocate memory for MLME-SET.request"); + return CMDLINE_RETCODE_FAIL; + } + if (string_to_bytes(str, val_ptr_array, bytes) != 0) { + ns_dyn_mem_free(val_ptr_array); + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + set_req.value_pointer = val_ptr_array; + } else if (cmd_parameter_int(argc, argv, "--value_uint8", &val)) { + if (val >= 0 && val <= 0xFF) { + val_uint8 = val; + set_req.value_pointer = &val_uint8; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else if (cmd_parameter_int(argc, argv, "--value_uint16", &val)) { + if (val >= 0 && val <= 0xFFFF) { + val_uint16 = val; + set_req.value_pointer = &val_uint16; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else if (cmd_parameter_int(argc, argv, "--value_uint32", &val)) { + if (val >= 0 && val <= 0x7FFFFFFF) { + val_uint32 = val; + set_req.value_pointer = &val_uint32; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--value_size", &val)) { + if (val >= 0 && val <= 255) { + set_req.value_size = val; + } + } + + mac_interface->mlme_req(mac_interface, MLME_SET, &set_req); + ns_dyn_mem_free(val_ptr_array); + set_req.value_pointer = NULL; + return CMDLINE_RETCODE_SUCCESS; +} + +int mac_get_command(int argc, char *argv[]) +{ + char *str; + int32_t val; + + cmd_printf("MLME-GET.request\n"); + if (cmd_parameter_val(argc, argv, "--attr", &str)) { + uint32_t attribute = strtoul(str, NULL, 16); + if (attribute <= 255) { + get_req.attr = (mlme_attr_t)attribute; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--attr_index", &val)) { + if (val >= 0 && val <= 255) { + get_req.attr_index = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + mac_interface->mlme_req(mac_interface, MLME_GET, &get_req); + return CMDLINE_RETCODE_SUCCESS; +} + +int mac_reset_command(int argc, char *argv[]) +{ + bool boolean; + + cmd_printf("MLME-RESET.request\n"); + if (cmd_parameter_bool(argc, argv, "--set_default_pib", &boolean)) { + reset_req.SetDefaultPIB = boolean; + } + mac_interface->mlme_req(mac_interface, MLME_RESET, &reset_req); + return CMDLINE_RETCODE_SUCCESS; +} + +int mac_address_command(int argc, char *argv[]) +{ + char *str; + uint8_t ext_addr[8]; + + if (cmd_parameter_val(argc, argv, "--64-bit", &str)) { + if (string_to_bytes(str, ext_addr, 8) != 0) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + mac_interface->mac64_set(mac_interface, ext_addr); + cmd_printf("64-bit MAC address set to: %s\n", trace_array(ext_addr, 8)); + } else if (cmd_parameter_val(argc, argv, "--16-bit", &str)) { + uint32_t short_addr_32 = strtoul(str, NULL, 16); + if (short_addr_32 <= 0xFFFF) { + uint16_t short_addr = short_addr_32; + mlme_set_t set_req; + set_req.attr = macShortAddress; + set_req.value_pointer = &short_addr; + set_req.value_size = 2; + mac_interface->mlme_req(mac_interface, MLME_SET, &set_req); + cmd_printf("16-bit MAC address set to: 0x%04X\n", short_addr); + } else { + tr_warn("Invalid 16-bit MAC address given: %lu", short_addr_32); + } + } else if (argc == 1) { + if (mac_interface->mac64_get(mac_interface, MAC_EXTENDED_READ_ONLY, ext_addr) == 0) { + cmd_printf("EUI64: %s\n", trace_array(ext_addr, 8)); + } else { + tr_warn("Failed to read EUI64"); + return CMDLINE_RETCODE_FAIL; + } + if (mac_interface->mac64_get(mac_interface, MAC_EXTENDED_DYNAMIC, ext_addr) == 0) { + cmd_printf("MAC64: %s\n", trace_array(ext_addr, 8)); + } else { + tr_warn("Failed to read MAC64"); + return CMDLINE_RETCODE_FAIL; + } + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + return CMDLINE_RETCODE_SUCCESS; +} + +static int key_config_command(int argc, char *argv[]) +{ + char *str; + int32_t val; + bool boolean; + int lookup_index = 0, device_index = 0, usage_index = 0; + + if (cmd_parameter_val(argc, argv, "--key", &str)) { + if (strlen(str) == 2 * 16 + 15) { + if (string_to_bytes(str, key_descriptor.Key, 16) != 0) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--key_id_lookup_list_entries", &val)) { + if (val >= 0 && val < LOOKUP_DESCRIPTOR_TABLE_SIZE) { + key_descriptor.KeyIdLookupListEntries = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--key_device_list_entries", &val)) { + if (val >= 0 && val < DEVICE_DESCRIPTOR_TABLE_SIZE) { + key_descriptor.KeyDeviceListEntries = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--key_usage_list_entries", &val)) { + if (val >= 0 && val < USAGE_DESCRIPTOR_TABLE_SIZE) { + key_descriptor.KeyUsageListEntries = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--lookup_index", &val)) { + if (val >= 0 && val < LOOKUP_DESCRIPTOR_TABLE_SIZE) { + lookup_index = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_val(argc, argv, "--lookup_data", &str)) { + if (strlen(str) == 2 * 9 + 8) { + if (string_to_bytes(str, key_descriptor.KeyIdLookupList[lookup_index].LookupData, 9) != 0) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--lookup_data_size", &val)) { + if (val == 0 || val == 1) { + key_descriptor.KeyIdLookupList[lookup_index].LookupDataSize = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--device_list_index", &val)) { + if (val >= 0 && val < DEVICE_DESCRIPTOR_TABLE_SIZE) { + device_index = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--device_descriptor_handle", &val)) { + if (val >= 0 && val <= 255) { + key_descriptor.KeyDeviceList[device_index].DeviceDescriptorHandle = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_bool(argc, argv, "--unique_device", &boolean)) { + key_descriptor.KeyDeviceList[device_index].UniqueDevice = boolean; + } + if (cmd_parameter_bool(argc, argv, "--blacklisted", &boolean)) { + key_descriptor.KeyDeviceList[device_index].Blacklisted = boolean; + } + if (cmd_parameter_int(argc, argv, "--usage_index", &val)) { + if (val >= 0 && val <= USAGE_DESCRIPTOR_TABLE_SIZE) { + usage_index = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--frame_type", &val)) { + if (val >= 0 && val <= 3) { + key_descriptor.KeyUsageList[usage_index].FrameType = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (key_descriptor.KeyUsageList[usage_index].FrameType == 3) { + if (cmd_parameter_int(argc, argv, "--command_frame_identifier", &val)) { + if (val >= 1 && val <= 9) { + key_descriptor.KeyUsageList[usage_index].CommandFrameIdentifier = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + } + return CMDLINE_RETCODE_SUCCESS; +} + +static int key_add_command(int argc, char *argv[]) +{ + mlme_set_t set_req; + int32_t val; + int key_index = 0; + + if (cmd_parameter_int(argc, argv, "--index", &val)) { + if (val >= 0 && val <= 255) { + key_index = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + + set_req.attr = macKeyTable; + set_req.attr_index = key_index; + set_req.value_pointer = &key_descriptor; + set_req.value_size = sizeof(mlme_key_descriptor_entry_t); + mac_interface->mlme_req(mac_interface, MLME_SET, &set_req); + return CMDLINE_RETCODE_SUCCESS; +} + +int mac_key_command(int argc, char *argv[]) +{ + char *cmd = argv[1]; + + if (strcmp(cmd, "config") == 0) { + return key_config_command(argc, argv); + } else if (strcmp(cmd, "add") == 0) { + return key_add_command(argc, argv); + } + return CMDLINE_RETCODE_INVALID_PARAMETERS; +} + +int mac_add_neighbour_command(int argc, char *argv[]) +{ + char *str; + int32_t val; + mlme_device_descriptor_t neighbour; + mlme_set_t set_req; + + neighbour.Exempt = false; + if (cmd_parameter_int(argc, argv, "--frame_ctr", &val)) { + neighbour.FrameCounter = val; + } + if (cmd_parameter_val(argc, argv, "--mac16", &str)) { + uint32_t short_addr = strtoul(str, NULL, 16); + if (short_addr <= 0xFFFF) { + neighbour.ShortAddress = short_addr; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_val(argc, argv, "--mac64", &str)) { + if (strlen(str) == 2 * 8 + 7) { + if (string_to_bytes(str, neighbour.ExtAddress, 8) != 0) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_val(argc, argv, "--pan_id", &str)) { + uint32_t pan_id = strtoul(str, NULL, 16); + if (pan_id <= 0xFFFF) { + neighbour.PANId = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if (cmd_parameter_int(argc, argv, "--index", &val)) { + if (val >= 0 && val <= 255) { + set_req.attr_index = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + + set_req.attr = macDeviceTable; + set_req.value_pointer = &neighbour; + set_req.value_size = sizeof(mlme_device_descriptor_t); + mac_interface->mlme_req(mac_interface, MLME_SET, &set_req); + return CMDLINE_RETCODE_SUCCESS; +} + +#ifndef DISABLE_FILTERING +static int filter_start(int argc, char *argv[]) +{ + char *str; + + if (cmd_parameter_val(argc, argv, "--mode", &str)) { + if (strcmp(str, "allow") == 0) { + return mac_filter_start(mac_interface->parent_id, MAC_FILTER_ALLOWED) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; + } else if (strcmp(str, "block") == 0) { + return mac_filter_start(mac_interface->parent_id, MAC_FILTER_BLOCKED) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS;; + } else if (strcmp(str, "fixed") == 0) { + int32_t lqi, dbm; + if (cmd_parameter_int(argc, argv, "--lqi_m", &lqi) && + cmd_parameter_int(argc, argv, "--dbm_m", &dbm)) { + return mac_filter_start(mac_interface->parent_id, MAC_FILTER_FIXED(lqi, dbm)) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; + } + } + } + return CMDLINE_RETCODE_INVALID_PARAMETERS; +} + +static int filter_add(int argc, char *argv[]) +{ + char *str; + uint32_t short_addr; + uint8_t long_addr[8]; + int32_t lqi_m, lqi_add, dbm_m, dbm_add; + + if (cmd_parameter_int(argc, argv, "--lqi_m", &lqi_m) && + cmd_parameter_int(argc, argv, "--lqi_add", &lqi_add) && + cmd_parameter_int(argc, argv, "--dbm_m", &dbm_m) && + cmd_parameter_int(argc, argv, "--dbm_add", &dbm_add)) { + } else if (cmd_parameter_val(argc, argv, "--mode", &str)) { + if (strcmp(str, "allow")) { + lqi_m = dbm_m = 256; + lqi_add = dbm_add = 0; + } else if (strcmp(str, "block")) { + lqi_m = lqi_add = dbm_m = dbm_add = 0; + } else if (strcmp(str, "fixed")) { + lqi_add = dbm_add = 0; + if (cmd_parameter_int(argc, argv, "--lqi_m", &lqi_m) && + cmd_parameter_int(argc, argv, "--dbm_m", &dbm_m)) { + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + + if (cmd_parameter_val(argc, argv, "--short", &str)) { + short_addr = strtoul(str, NULL, 16); + if (short_addr <= 0xFFFF) { + return mac_filter_add_short(mac_interface->parent_id, short_addr, lqi_m, lqi_add, dbm_m, dbm_add) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else if (cmd_parameter_val(argc, argv, "--long", &str)) { + if (string_to_bytes(str, long_addr, 8) != 0) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + return mac_filter_add_long(mac_interface->parent_id, long_addr, lqi_m, lqi_add, dbm_m, dbm_add) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } +} + +static int filter_remove(int argc, char *argv[]) +{ + char *str; + uint32_t short_addr; + uint8_t long_addr[8]; + + if (cmd_parameter_val(argc, argv, "--short", &str)) { + short_addr = strtoul(str, NULL, 16); + if (short_addr <= 0xFFFF) { + return mac_filter_delete_short(mac_interface->parent_id, short_addr) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else if (cmd_parameter_val(argc, argv, "--long", &str)) { + if (string_to_bytes(str, long_addr, 8) != 0) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + return mac_filter_delete_long(mac_interface->parent_id, long_addr) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } +} + +static int filter_clear(int argc, char *argv[]) +{ + return mac_filter_clear(mac_interface->parent_id) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS; +} + +static int filter_stop(int argc, char *argv[]) +{ + mac_filter_stop(mac_interface->parent_id); + return CMDLINE_RETCODE_SUCCESS; +} +#else +static int filter_start(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + return 0; +} + +static int filter_add(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + return 0; +} +static int filter_remove(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + return 0; +} +static int filter_clear(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + return 0; +} +static int filter_stop(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + return 0; +} +#endif +int mac_filter_command(int argc, char *argv[]) +{ + char *cmd = argv[1]; + + if (strcmp(cmd, "start") == 0) { + return filter_start(argc, argv); + } else if (strcmp(cmd, "add") == 0) { + return filter_add(argc, argv); + } else if (strcmp(cmd, "remove") == 0) { + return filter_remove(argc, argv); + } else if (strcmp(cmd, "clear") == 0) { + return filter_clear(argc, argv); + } else if (strcmp(cmd, "stop") == 0) { + return filter_stop(argc, argv); + } + return CMDLINE_RETCODE_INVALID_PARAMETERS; +} + +int mac_config_status_command(int argc, char *argv[]) +{ + int32_t val; + char *str; + + if (cmd_parameter_int(argc, argv, "--data_conf", &val)) { + if (val >= 0 && val <= 255) { + expected_statuses.data_conf = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else if (cmd_parameter_val(argc, argv, "--data_ind", &str)) { + size_t len = strlen(str); + ns_dyn_mem_free(expected_statuses.data_ind); + expected_statuses.data_ind = (uint8_t *)ns_dyn_mem_temporary_alloc(len); + expected_statuses.data_ind_len = len; + std::memcpy(expected_statuses.data_ind, str, len); + } else if (cmd_parameter_int(argc, argv, "--get", &val)) { + if (val >= 0 && val <= 255) { + expected_statuses.get_conf = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else if (cmd_parameter_int(argc, argv, "--scan", &val)) { + if (val >= 0 && val <= 255) { + expected_statuses.scan_conf = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else if (cmd_parameter_int(argc, argv, "--poll", &val)) { + if (val >= 0 && val <= 255) { + expected_statuses.poll_conf = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else if (cmd_parameter_int(argc, argv, "--purge", &val)) { + if (val >= 0 && val <= 255) { + expected_statuses.purge_conf = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else if (cmd_parameter_int(argc, argv, "--comm_status", &val)) { + if (val >= 0 && val <= 255) { + expected_statuses.comm_status_ind = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else if (cmd_parameter_index(argc, argv, "--list") != -1) { + for (unsigned int i = 0; i < 256; ++i) { + const char *status = mlme_status_string(i); + if (status) { + cmd_printf("%hhu\t%s\n", i, status); + } + } + } else if (cmd_parameter_index(argc, argv, "--reset") != -1) { + expected_statuses.data_conf = MLME_SUCCESS; + expected_statuses.get_conf = MLME_SUCCESS; + expected_statuses.scan_conf = MLME_SUCCESS; + expected_statuses.poll_conf = MLME_SUCCESS; + expected_statuses.purge_conf = MLME_SUCCESS; + expected_statuses.comm_status_ind = MLME_SUCCESS; + expected_statuses.data_ind_len = 0; + expected_statuses.data_ind = NULL; + } else if (argc == 1) { + cmd_printf("MCPS-DATA.confirm: %d (%s)\n", expected_statuses.data_conf, mlme_status_string(expected_statuses.data_conf)); + cmd_printf("MLME-GET.confirm: %d (%s)\n", expected_statuses.get_conf, mlme_status_string(expected_statuses.get_conf)); + cmd_printf("MLME-SCAN.confirm: %d (%s)\n", expected_statuses.scan_conf, mlme_status_string(expected_statuses.scan_conf)); + cmd_printf("MLME-POLL.confirm: %d (%s)\n", expected_statuses.poll_conf, mlme_status_string(expected_statuses.poll_conf)); + cmd_printf("MCPS.PURGE.confirm. %d (%s)\n", expected_statuses.purge_conf, mlme_status_string(expected_statuses.purge_conf)); + cmd_printf("MLME-COMM-STATUS.indication: %d (%s)\n", expected_statuses.comm_status_ind, mlme_status_string(expected_statuses.comm_status_ind)); + cmd_printf("MCPS-DATA.indication: %s <%.*s>\n", trace_array(expected_statuses.data_ind, expected_statuses.data_ind_len), expected_statuses.data_ind_len, expected_statuses.data_ind); + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + return CMDLINE_RETCODE_SUCCESS; +} + +int mac_find_beacon_command(int argc, char *argv[]) +{ + char *str; + + if (cmd_parameter_val(argc, argv, "--data", &str)) { + for (int i = 0; i < MLME_MAC_RES_SIZE_MAX; ++i) { + if (received_beacons.beacons[i] == NULL) { + continue; + } + if (strncmp(received_beacons.beacons[i], str, received_beacons.beacon_lengths[i]) == 0) { + return CMDLINE_RETCODE_SUCCESS; + } + } + return CMDLINE_RETCODE_FAIL; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } +} + +int mac_wait_command(int argc, char *argv[]) +{ + int32_t val; + static uint32_t timeout_ms = 1000; + int remaining_ms = timeout_ms; + if (cmd_parameter_int(argc, argv, "--timeout", &val)) { + if (val >= 0) { + timeout_ms = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + while (data_count < 1) { + ThisThread::sleep_for(10); + remaining_ms -= 10; + if (remaining_ms <= 0) { + return CMDLINE_RETCODE_FAIL; + } + } + data_count = 0; + return CMDLINE_RETCODE_SUCCESS; +} + +int mac_analyze_ed_command(int argc, char *argv[]) +{ + int32_t val; + int channel; + + if (cmd_parameter_int(argc, argv, "--channel", &val)) { + if (val >= 0 && val <= 26) { + channel = val; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + + if (cmd_parameter_int(argc, argv, "--above", &val)) { + for (int i = 0; i < last_ed_results.count; ++i) { + if (last_ed_results.channel[i] == channel) { + return last_ed_results.ED_values[i] >= val ? CMDLINE_RETCODE_SUCCESS : CMDLINE_RETCODE_FAIL; + } + } + } else if (cmd_parameter_int(argc, argv, "--below", &val)) { + for (int i = 0; i < last_ed_results.count; ++i) { + if (last_ed_results.channel[i] == channel) { + return last_ed_results.ED_values[i] <= val ? CMDLINE_RETCODE_SUCCESS : CMDLINE_RETCODE_FAIL; + } + } + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + return CMDLINE_RETCODE_FAIL; +} + +static void reset_security(mlme_security_t *sec) +{ + sec->SecurityLevel = 0; + sec->KeyIdMode = 0; + sec->KeyIndex = 0; + memset(sec->Keysource, 0, 8); +} + +int reset_command(int argc, char *argv[]) +{ + wait_for_confirm = true; + silent_mode = false; + data_count = 0; + + start_req.PANId = 0x1234; + start_req.LogicalChannel = 11; + start_req.ChannelPage = 0; + start_req.StartTime = 0; + start_req.BeaconOrder = 15; + start_req.SuperframeOrder = 15; + start_req.PANCoordinator = true; + start_req.BatteryLifeExtension = false; + start_req.CoordRealignment = false; + reset_security(&start_req.CoordRealignKey); + reset_security(&start_req.BeaconRealignKey); + + scan_req.ScanType = MAC_ACTIVE_SCAN; + scan_req.ScanChannels.channel_page = CHANNEL_PAGE_0; + scan_req.ScanChannels.channel_mask[0] = 0x07FFF800; + reset_security(&scan_req.Key); + + data_req.SrcAddrMode = 3; + data_req.DstAddrMode = 3; + data_req.DstPANId = 0x1234; + memset(data_req.DstAddr, 0, 8); + data_req.msduLength = 0; + data_req.msdu = NULL; + data_req.msduHandle = 0; + data_req.TxAckReq = true; + data_req.InDirectTx = false; + data_req.PendingBit = false; + reset_security(&data_req.Key); + + poll_req.CoordAddrMode = 3; + poll_req.CoordPANId = 0x1234; + memset(poll_req.CoordAddress, 0, 8); + reset_security(&poll_req.Key); + + purge_req.msduHandle = 0; + + set_req.attr = (mlme_attr_t)0x39; + set_req.attr_index = 0; + set_req.value_pointer = NULL; + set_req.value_size = 0; + + get_req.attr = (mlme_attr_t)0x39; + get_req.attr_index = 0; + + reset_req.SetDefaultPIB = true; + + return CMDLINE_RETCODE_SUCCESS; +} + +int silent_mode_command(int argc, char *argv[]) +{ + char *cmd; + if (argc < 2) { + return CMDLINE_RETCODE_FAIL; + } + cmd = argv[1]; + if (strcmp(cmd, "on") == 0) { + silent_mode = true; + return CMDLINE_RETCODE_SUCCESS; + } else if (strcmp(cmd, "off") == 0) { + silent_mode = false; + return CMDLINE_RETCODE_SUCCESS; + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } +} diff --git a/TEST_APPS/device/nanostack_mac_tester/source/mac_commands.h b/TEST_APPS/device/nanostack_mac_tester/source/mac_commands.h new file mode 100644 index 0000000000..a57e97fc31 --- /dev/null +++ b/TEST_APPS/device/nanostack_mac_tester/source/mac_commands.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017, 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. + */ +#ifndef MAC_COMMANDS_H_ +#define MAC_COMMANDS_H_ + +#include +#include + +#include "ns_cmdline.h" +#include "nsdynmemLIB.h" +#include "mbed_trace.h" +#include "mac_api.h" +#include "mlme.h" +#include "mac_mcps.h" +#include "mac_common_defines.h" +#include "mac_filter_api.h" +#include "util.h" + +#define LOOKUP_DESCRIPTOR_TABLE_SIZE 2 +#define DEVICE_DESCRIPTOR_TABLE_SIZE 2 +#define USAGE_DESCRIPTOR_TABLE_SIZE 2 +#define KEY_DESCRIPTOR_TABLE_SIZE 2 + +void mac_commands_init(void); + +void mac_data_confirm_handler(const mac_api_t *api, const mcps_data_conf_t *data); +void mac_data_indication_handler(const mac_api_t *api, const mcps_data_ind_t *data); +void mac_purge_confirm_handler(const mac_api_t *api, mcps_purge_conf_t *data); +void mac_mlme_confirm_handler(const mac_api_t *api, mlme_primitive id, const void *data); +void mac_mlme_indication_handler(const mac_api_t *api, mlme_primitive id, const void *data); + +int mac_start_command(int argc, char *argv[]); +int mac_scan_command(int argc, char *argv[]); +int mac_data_command(int argc, char *argv[]); +int mac_poll_command(int argc, char *argv[]); +int mac_purge_command(int argc, char *argv[]); +int mac_set_command(int argc, char *argv[]); +int mac_get_command(int argc, char *argv[]); +int mac_reset_command(int argc, char *argv[]); +int mac_address_command(int argc, char *argv[]); +int mac_key_command(int argc, char *argv[]); +int mac_add_neighbour_command(int argc, char *argv[]); +int mac_filter_command(int argc, char *argv[]); +int mac_config_status_command(int argc, char *argv[]); +int mac_find_beacon_command(int argc, char *argv[]); +int mac_wait_command(int argc, char *argv[]); +int mac_analyze_ed_command(int argc, char *argv[]); +int reset_command(int argc, char *argv[]); +int silent_mode_command(int argc, char *argv[]); + +#endif diff --git a/TEST_APPS/device/nanostack_mac_tester/source/util.cpp b/TEST_APPS/device/nanostack_mac_tester/source/util.cpp new file mode 100644 index 0000000000..7a914a7edb --- /dev/null +++ b/TEST_APPS/device/nanostack_mac_tester/source/util.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2017, 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. + */ +#include "util.h" + +int string_to_bytes(const char *str, uint8_t *buf, int bytes) +{ + int len = strlen(str); + + if (len <= (3 * bytes - 1)) { + int i; + + for (i = 0; i < bytes; ++i) { + if (i * 3 < len) { + buf[i] = (uint8_t)strtoul(str + i * 3, NULL, 16); + } else { + buf[i] = 0; + } + } + return 0; + } + return -1; +} + +const char *mlme_status_string(uint8_t status) +{ + switch (status) { + case MLME_SUCCESS: + return "MLME_SUCCESS"; + case MLME_BUSY_CHAN: + return "MLME_BUSY_CHAN"; + case MLME_BUSY_RX: + return "MLME_BUSY_RX"; + case MLME_BUSY_TX: + return "MLME_BUSY_TX"; + case MLME_FORCE_TRX_OFF: + return "MLME_FORCE_TRX_OFF"; + case MLME_IDLE: + return "MLME_IDLE"; + case MLME_RX_ON: + return "MLME_RX_ON"; + case MLME_TRX_OFF: + return "MLME_TRX_OFF"; + case MLME_TX_ON: + return "MLME_TX_ON"; + case MLME_COUNTER_ERROR: + return "MLME_COUNTER_ERROR"; + case MLME_IMPROPER_KEY_TYPE: + return "MLME_IMPROPER_KEY_TYPE"; + case MLME_IMPROPER_SECURITY_LEVEL: + return "MLME_IMPROPER_SECURITY_LEVEL"; + case MLME_UNSUPPORTED_LEGACY: + return "MLME_UNSUPPORTED_LEGACY"; + case MLME_UNSUPPORTED_SECURITY: + return "MLME_UNSUPPORTED_SECURITY"; + case MLME_SECURITY_FAIL: + return "MLME_SECURITY_FAIL"; + case MLME_FRAME_TOO_LONG: + return "MLME_FRAME_TOO_LONG"; + case MLME_INVALID_HANDLE: + return "MLME_INVALID_HANDLE"; + case MLME_INVALID_PARAMETER: + return "MLME_INVALID_PARAMETER"; + case MLME_TX_NO_ACK: + return "MLME_TX_NO_ACK"; + case MLME_NO_BEACON: + return "MLME_NO_BEACON"; + case MLME_NO_DATA: + return "MLME_NO_DATA"; + case MLME_NO_SHORT_ADDRESS: + return "MLME_NO_SHORT_ADDRESS"; + case MLME_PAN_ID_CONFLICT: + return "MLME_PAN_ID_CONFLICT"; + case MLME_TRANSACTION_EXPIRED: + return "MLME_TRANSACTION_EXPIRED"; + case MLME_TRANSACTION_OVERFLOW: + return "MLME_TRANSACTION_OVERFLOW"; + case MLME_UNAVAILABLE_KEY: + return "MLME_UNAVAILABLE_KEY"; + case MLME_UNSUPPORTED_ATTRIBUTE: + return "MLME_UNSUPPORTED_ATTRIBUTE"; + case MLME_INVALID_ADDRESS: + return "MLME_INVALID_ADDRESS"; + case MLME_INVALID_INDEX: + return "MLME_INVALID_INDEX"; + case MLME_LIMIT_REACHED: + return "MLME_LIMIT_REACHED"; + case MLME_READ_ONLY: + return "MLME_READ_ONLY"; + case MLME_SCAN_IN_PROGRESS: + return "MLME_SCAN_IN_PROGRESS"; + case MLME_DATA_POLL_NOTIFICATION: + return "MLME_DATA_POLL_NOTIFICATION"; + default: + return NULL; + } +} + +int channel_from_mask(uint32_t channel_mask, int index) +{ + int expected_index = 0; + for (int i = 0; i < 27; ++i) { + if ((channel_mask >> i) & 1) { + if (expected_index == index) { + return i; + } + ++expected_index; + } + } + return -1; +} diff --git a/UNITTESTS/target_h/ip6string.h b/TEST_APPS/device/nanostack_mac_tester/source/util.h similarity index 70% rename from UNITTESTS/target_h/ip6string.h rename to TEST_APPS/device/nanostack_mac_tester/source/util.h index d1d4ac28c5..a792731427 100644 --- a/UNITTESTS/target_h/ip6string.h +++ b/TEST_APPS/device/nanostack_mac_tester/source/util.h @@ -14,23 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef UTIL_H_ +#define UTIL_H_ + +#include +#include + +#include "mbed.h" +#include "mlme.h" + +int string_to_bytes(const char *str, uint8_t *buf, int bytes); +const char *mlme_status_string(uint8_t status); +int channel_from_mask(uint32_t channel_mask, int index); -#ifndef IP6STRING_H -#define IP6STRING_H -#ifdef __cplusplus -extern "C" { -#endif - -#include - -uint_fast8_t ip6tos(const void *ip6addr, char *p) -{ - return 0; -} - -void stoip6(const char *ip6addr, size_t len, void *dest) {} - -#ifdef __cplusplus -} -#endif #endif diff --git a/TEST_APPS/device/socket_app/cmd_socket.cpp b/TEST_APPS/device/socket_app/cmd_socket.cpp index 4aefe700dc..7ecf176133 100644 --- a/TEST_APPS/device/socket_app/cmd_socket.cpp +++ b/TEST_APPS/device/socket_app/cmd_socket.cpp @@ -18,13 +18,13 @@ #include "UDPSocket.h" #include "TCPSocket.h" #include "TCPServer.h" +#include "TLSSocket.h" #include "NetworkInterface.h" #include "SocketAddress.h" #include "Queue.h" #include #include -#include #include #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS @@ -42,23 +42,26 @@ #define SIGNAL_SIGIO 0x1 #define PACKET_SIZE_ARRAY_LEN 5 +#define CERT_BUFFER_SIZE 1648 + #define MAN_SOCKET "\r\nSOCKET API\r\n"\ "\r\n"\ "socket [options]\r\n\r\n"\ " new \r\n" \ - " type: UDPSocket|TCPSocket|TCPServer\r\n"\ + " type: UDPSocket|TCPSocket|TCPServer|TLSSocket [--cert_file |--cert_default]\r\n"\ " return socket id\r\n"\ " delete\r\n"\ " remote the space allocated for Socket\r\n"\ - " open\r\n"\ + " open [--if ] \r\n"\ + " interface (or use default interface) \r\n"\ " close\r\n"\ " bind [port] [addr ]\r\n"\ " set_blocking \r\n"\ " set_timeout \r\n"\ " register_sigio_cb\r\n"\ " set_RFC_864_pattern_check \r\n"\ - "\r\nFor UDPSocket\r\n"\ + " set_root_ca_cert --cert_url |--cert_file |--cert_default\r\n"\ " sendto (\"msg\" | --data_len )\r\n"\ " \"msg\" Send packet with defined string content\r\n"\ " --data_len Send packet with random content with size \r\n"\ @@ -66,7 +69,6 @@ " start_udp_receiver_thread --max_data_len [--packets ]\r\n"\ " --max_data_len Size of input buffer to fill up\r\n"\ " --packets Receive N number of packets, default 1\r\n"\ - "\r\nFor TCPSocket\r\n"\ " connect \r\n"\ " send (\"msg\" | --data_len )\r\n"\ " recv \r\n"\ @@ -79,28 +81,60 @@ " join_bg_traffic_thread\r\n"\ " setsockopt_keepalive \r\n"\ " getsockopt_keepalive\r\n"\ - "\r\nFor TCPServer\r\n"\ " listen [backlog]\r\n"\ + " accept\r\n" \ + " accept new connection and returns new socket ID\r\n" \ + "\r\nFor TCPServer\r\n"\ " accept \r\n"\ " accept new connection into socket. Requires to be pre-allocated.\r\n"\ "\r\nOther options\r\n"\ " print-mode [--string|--hex|--disabled] [--col-width ]" -class SInfo; -static Queue event_queue; -static int id_count = 0; + + +const char *cert = \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n" \ + "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \ + "DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n" \ + "SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n" \ + "GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n" \ + "AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n" \ + "q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n" \ + "SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n" \ + "Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n" \ + "a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n" \ + "/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n" \ + "AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n" \ + "CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n" \ + "bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n" \ + "c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n" \ + "VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n" \ + "ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n" \ + "MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n" \ + "Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n" \ + "AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n" \ + "uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n" \ + "wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n" \ + "X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n" \ + "PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n" \ + "KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n" \ + "-----END CERTIFICATE-----\n"; class SInfo { public: enum SocketType { - TCP_CLIENT, + IP, TCP_SERVER, - UDP + OTHER, +#if defined(MBEDTLS_SSL_CLI_C) + TLS +#endif }; - SInfo(TCPSocket *sock): + SInfo(InternetSocket *sock, bool delete_on_exit = true): _id(id_count++), _sock(sock), - _type(SInfo::TCP_CLIENT), + _type(SInfo::IP), _blocking(true), _dataLen(0), _maxRecvLen(0), @@ -111,11 +145,12 @@ public: _senderThreadId(NULL), _receiverThreadId(NULL), _packetSizes(NULL), - _check_pattern(false) + _check_pattern(false), + _delete_on_exit(delete_on_exit) { - assert(sock); + MBED_ASSERT(sock); } - SInfo(TCPServer *sock): + SInfo(TCPServer *sock, bool delete_on_exit = true): _id(id_count++), _sock(sock), _type(SInfo::TCP_SERVER), @@ -129,14 +164,15 @@ public: _senderThreadId(NULL), _receiverThreadId(NULL), _packetSizes(NULL), - _check_pattern(false) + _check_pattern(false), + _delete_on_exit(delete_on_exit) { - assert(sock); + MBED_ASSERT(sock); } - SInfo(UDPSocket *sock): + SInfo(Socket *sock, bool delete_on_exit = true): _id(id_count++), _sock(sock), - _type(SInfo::UDP), + _type(SInfo::OTHER), _blocking(true), _dataLen(0), _maxRecvLen(0), @@ -147,10 +183,32 @@ public: _senderThreadId(NULL), _receiverThreadId(NULL), _packetSizes(NULL), - _check_pattern(false) + _check_pattern(false), + _delete_on_exit(delete_on_exit) { - assert(sock); + MBED_ASSERT(sock); } +#if defined(MBEDTLS_SSL_CLI_C) + SInfo(TLSSocket *sock, bool delete_on_exit = true): + _id(id_count++), + _sock(sock), + _type(SInfo::TLS), + _blocking(true), + _dataLen(0), + _maxRecvLen(0), + _repeatBufferFill(1), + _receivedTotal(0), + _receiverThread(NULL), + _receiveBuffer(NULL), + _senderThreadId(NULL), + _receiverThreadId(NULL), + _packetSizes(NULL), + _check_pattern(false), + _delete_on_exit(delete_on_exit) + { + MBED_ASSERT(sock); + } +#endif ~SInfo() { this->_sock->sigio(Callback()); @@ -161,7 +219,9 @@ public: if (this->_receiveBuffer) { delete this->_receiveBuffer; } - delete this->_sock; + if (_delete_on_exit) { + delete this->_sock; + } } int id() const { @@ -175,18 +235,20 @@ public: { return *(this->_sock); } - TCPSocket *tcp_socket() + InternetSocket *internetsocket() { - return this->_type == SInfo::TCP_CLIENT ? static_cast(this->_sock) : NULL; + return this->_type == SInfo::IP ? static_cast(this->_sock) : NULL; } TCPServer *tcp_server() { return this->_type == SInfo::TCP_SERVER ? static_cast(this->_sock) : NULL; } - UDPSocket *udp_socket() +#if defined(MBEDTLS_SSL_CLI_C) + TLSSocket *tls_socket() { - return this->_type == SInfo::UDP ? static_cast(this->_sock) : NULL; + return this->_type == SInfo::TLS ? static_cast(this->_sock) : NULL; } +#endif SInfo::SocketType type() const { return this->_type; @@ -285,17 +347,22 @@ public: { const char *str; switch (this->_type) { - case SInfo::TCP_CLIENT: - str = "TCPSocket"; + case SInfo::IP: + str = "InternetSocket"; break; case SInfo::TCP_SERVER: str = "TCPServer"; break; - case SInfo::UDP: - str = "UDPSocket"; + case SInfo::OTHER: + str = "Socket"; break; +#if defined(MBEDTLS_SSL_CLI_C) + case SInfo::TLS: + str = "TLSSocket"; + break; +#endif default: - assert(0); + MBED_ASSERT(0); break; } return str; @@ -309,39 +376,8 @@ public: socket().set_blocking(blocking); this->_blocking = blocking; } - bool can_connect() - { - return (this->type() == SInfo::TCP_CLIENT); - } - bool can_bind() - { - return (this->type() == SInfo::UDP || this->type() == SInfo::TCP_SERVER); - } - bool can_send() - { - return (this->type() == SInfo::TCP_CLIENT); - } - bool can_recv() - { - return (this->type() == SInfo::TCP_CLIENT); - } - bool can_sendto() - { - return (this->type() == SInfo::UDP); - } - bool can_recvfrom() - { - return (this->type() == SInfo::UDP); - } - bool can_listen() - { - return (this->type() == SInfo::TCP_SERVER); - } - bool can_accept() - { - return (this->type() == SInfo::TCP_SERVER); - } private: + static int id_count; const int _id; Socket *_sock; const SInfo::SocketType _type; @@ -357,9 +393,11 @@ private: int *_packetSizes; bool _available; bool _check_pattern; + bool _delete_on_exit; SInfo(); }; +int SInfo::id_count = 0; static std::vector m_sockets; @@ -389,22 +427,43 @@ static void print_data_as_hex(const uint8_t *buf, int len, int col_width); * \param offset Start pattern from offset * \param len Length of pattern to generate. */ -static void generate_RFC_864_pattern(size_t offset, uint8_t *buf, size_t len) +static void generate_RFC_864_pattern(size_t offset, uint8_t *buf, size_t len, bool is_xinetd) { + const int row_size = 74; // Number of chars in single row + const int row_count = 95; // Number of rows in pattern after which pattern start from beginning + const int chars_scope = is_xinetd ? 93 : 95; // Number of chars from ASCII table used in pattern + const char first_char = is_xinetd ? '!' : ' '; // First char from ASCII table used in pattern while (len--) { - if (offset % 74 == 72) { + if (offset % row_size == (row_size - 2)) { *buf++ = '\r'; - } else if (offset % 74 == 73) { + } else if (offset % row_size == (row_size - 1)) { *buf++ = '\n'; } else { - *buf++ = ' ' + (offset % 74 + offset / 74) % 95 ; + *buf++ = first_char + (offset % row_size + ((offset / row_size) % row_count)) % chars_scope; } offset++; } } +static int get_cert_from_file(const char *filename, char **cert) +{ + int filedesc = open(filename, O_RDONLY); + if (filedesc < 0) { + cmd_printf("Cannot open file: %s\r\n", filename); + return CMDLINE_RETCODE_FAIL; + } + + if (read(filedesc, *cert, CERT_BUFFER_SIZE) != CERT_BUFFER_SIZE) { + cmd_printf("Cannot read from file %s\r\n", filename); + return CMDLINE_RETCODE_FAIL; + } + + return CMDLINE_RETCODE_SUCCESS; +} + bool SInfo::check_pattern(void *buffer, size_t len) { + static bool is_xinetd = false; if (!_check_pattern) { return true; } @@ -412,8 +471,14 @@ bool SInfo::check_pattern(void *buffer, size_t len) if (!buf) { return false; } + size_t offset = _receivedTotal; - generate_RFC_864_pattern(offset, (uint8_t *)buf, len); + + if (offset == 0) { + is_xinetd = ((uint8_t *)buffer)[0] == '!'; + } + + generate_RFC_864_pattern(offset, (uint8_t *)buf, len, is_xinetd); bool match = memcmp(buf, buffer, len) == 0; if (!match) { cmd_printf("Pattern check failed\r\nWAS:%.*s\r\nREF:%.*s\r\n", len, (char *)buffer, len, (char *)buf); @@ -435,6 +500,9 @@ static void sigio_handler(SInfo *info) void cmd_socket_init(void) { cmd_add("socket", cmd_socket, "socket", MAN_SOCKET); + cmd_alias_add("socket help", "socket -h"); + cmd_alias_add("socket --help", "socket -h"); + cmd_alias_add("ping server start", "socket echo-server new start"); } int handle_nsapi_error(const char *function, nsapi_error_t ret) @@ -479,13 +547,46 @@ static int del_sinfo(SInfo *info) return CMDLINE_RETCODE_FAIL; } +#if defined(MBEDTLS_SSL_CLI_C) +static int tls_set_cert(int argc, char *argv[], SInfo *info) +{ + static char read_cert[CERT_BUFFER_SIZE]; + char *ptr_cert = NULL; + char *src = NULL; + if (cmd_parameter_val(argc, argv, "--cert_file", &src)) { + tr_debug("Root ca certificate read from file: %s", src); + ptr_cert = read_cert; + if (get_cert_from_file(src, &ptr_cert) == CMDLINE_RETCODE_FAIL) { + cmd_printf("Cannot read from url: %s\r\n", src); + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else if (cmd_parameter_index(argc, argv, "--cert_default") != -1) { + cmd_printf("Using default certificate\r\n"); + ptr_cert = (char *)cert; + } else { + cmd_printf("No cert specified. Use set_root_ca_cert to set it.\r\n"); + // Do not return error, allow the certificate not to be set. + return CMDLINE_RETCODE_SUCCESS; + } + + int ret = info->tls_socket()->set_root_ca_cert(ptr_cert); + if (ret != NSAPI_ERROR_OK) { + cmd_printf("Invalid root certificate\r\n"); + return CMDLINE_RETCODE_FAIL; + } + + return CMDLINE_RETCODE_SUCCESS; +} +#endif + static int cmd_socket_new(int argc, char *argv[]) { const char *s; SInfo *info; + nsapi_error_t ret; - if (cmd_parameter_last(argc, argv)) { - s = cmd_parameter_last(argc, argv); + if (argc > 2) { + s = argv[2]; if (strcmp(s, "UDPSocket") == 0) { tr_debug("Creating a new UDPSocket"); info = new SInfo(new UDPSocket); @@ -495,6 +596,16 @@ static int cmd_socket_new(int argc, char *argv[]) } else if (strcmp(s, "TCPServer") == 0) { tr_debug("Creating a new TCPServer"); info = new SInfo(new TCPServer); +#if defined(MBEDTLS_SSL_CLI_C) + } else if (strcmp(s, "TLSSocket") == 0) { + tr_debug("Creating a new TLSSocket"); + info = new SInfo(new TLSSocket); + ret = tls_set_cert(argc, argv, info); + if (ret) { + delete info; + return ret; + } +#endif } else { cmd_printf("unsupported protocol: %s\r\n", s); return CMDLINE_RETCODE_INVALID_PARAMETERS; @@ -518,10 +629,10 @@ static void udp_receiver_thread(SInfo *info) int *packetSizes = info->getPacketSizeArray(); nsapi_size_or_error_t ret = 0; - info->setReceiverThreadId(Thread::gettid()); + info->setReceiverThreadId(ThisThread::get_id()); while (i < n) { - ret = static_cast(info->socket()).recvfrom(&addr, info->getReceiveBuffer() + received, info->getDataCount() - received); + ret = info->socket().recvfrom(&addr, info->getReceiveBuffer() + received, info->getDataCount() - received); if (ret > 0) { if (!info->check_pattern(info->getReceiveBuffer() + received, ret)) { return; @@ -531,9 +642,9 @@ static void udp_receiver_thread(SInfo *info) i++; info->setRecvTotal(info->getRecvTotal() + ret); } else if (ret == NSAPI_ERROR_WOULD_BLOCK) { - Thread::signal_wait(SIGNAL_SIGIO); + ThisThread::flags_wait_any(SIGNAL_SIGIO); } else { - handle_nsapi_size_or_error("Thread: UDPSocket::recvfrom()", ret); + handle_nsapi_size_or_error("Thread: Socket::recvfrom()", ret); return; } } @@ -612,7 +723,12 @@ static nsapi_size_or_error_t udp_sendto_command_handler(SInfo *info, int argc, c } } - nsapi_size_or_error_t ret = static_cast(info->socket()).sendto(host, port, data, len); + SocketAddress addr(NULL, port); + nsapi_size_or_error_t ret = get_interface()->gethostbyname(host, &addr); + if (ret) { + return handle_nsapi_size_or_error("NetworkInterface::gethostbyname()", ret); + } + ret = info->socket().sendto(addr, data, len); if (ret > 0) { cmd_printf("sent: %d bytes\r\n", ret); } @@ -620,7 +736,7 @@ static nsapi_size_or_error_t udp_sendto_command_handler(SInfo *info, int argc, c free(data); } - return handle_nsapi_size_or_error("UDPSocket::sendto()", ret); + return handle_nsapi_size_or_error("Socket::sendto()", ret); } static nsapi_size_or_error_t udp_recvfrom_command_handler(SInfo *info, int argc, char *argv[]) @@ -638,9 +754,9 @@ static nsapi_size_or_error_t udp_recvfrom_command_handler(SInfo *info, int argc, cmd_printf("malloc() failed\r\n"); return CMDLINE_RETCODE_FAIL; } - nsapi_size_or_error_t ret = static_cast(info->socket()).recvfrom(&addr, data, len); + nsapi_size_or_error_t ret = info->socket().recvfrom(&addr, data, len); if (ret > 0) { - cmd_printf("UDPSocket::recvfrom, addr=%s port=%d\r\n", addr.get_ip_address(), addr.get_port()); + cmd_printf("Socket::recvfrom, addr=%s port=%d\r\n", addr.get_ip_address(), addr.get_port()); cmd_printf("received: %d bytes\r\n", ret); print_data((const uint8_t *)data, len); if (!info->check_pattern(data, len)) { @@ -649,7 +765,7 @@ static nsapi_size_or_error_t udp_recvfrom_command_handler(SInfo *info, int argc, info->setRecvTotal(info->getRecvTotal() + ret); } free(data); - return handle_nsapi_size_or_error("UDPSocket::recvfrom()", ret); + return handle_nsapi_size_or_error("Socket::recvfrom()", ret); } static void tcp_receiver_thread(SInfo *info) @@ -660,12 +776,12 @@ static void tcp_receiver_thread(SInfo *info) int bufferSize = info->getDataCount(); nsapi_size_or_error_t ret = 0; - info->setReceiverThreadId(Thread::gettid()); + info->setReceiverThreadId(ThisThread::get_id()); for (i = 0; i < n; i++) { received = 0; while (received < bufferSize) { - ret = static_cast(info->socket()).recv(info->getReceiveBuffer() + received, recv_len - received); + ret = info->socket().recv(info->getReceiveBuffer() + received, recv_len - received); if (ret > 0) { if (!info->check_pattern(info->getReceiveBuffer() + received, ret)) { return; @@ -673,9 +789,9 @@ static void tcp_receiver_thread(SInfo *info) received += ret; info->setRecvTotal(info->getRecvTotal() + ret); } else if (ret == NSAPI_ERROR_WOULD_BLOCK) { - Thread::signal_wait(SIGNAL_SIGIO); + ThisThread::flags_wait_all(SIGNAL_SIGIO); } else { - handle_nsapi_size_or_error("Thread: TCPSocket::recv()", ret); + handle_nsapi_size_or_error("Thread: Socket::recv()", ret); return; } } @@ -729,7 +845,7 @@ static nsapi_size_or_error_t tcp_send_command_handler(SInfo *info, int argc, cha void *data; nsapi_size_or_error_t ret = 0; - info->setSenderThreadId(Thread::gettid()); + info->setSenderThreadId(ThisThread::get_id()); if (cmd_parameter_int(argc, argv, "--data_len", &len)) { data = malloc(len); @@ -742,7 +858,7 @@ static nsapi_size_or_error_t tcp_send_command_handler(SInfo *info, int argc, cha len = strlen(argv[3]); } - ret = static_cast(info->socket()).send(data, len); + ret = info->socket().send(data, len); if (ret > 0) { cmd_printf("sent: %d bytes\r\n", ret); @@ -750,7 +866,7 @@ static nsapi_size_or_error_t tcp_send_command_handler(SInfo *info, int argc, cha if (data != argv[3]) { free(data); } - return handle_nsapi_size_or_error("TCPSocket::send()", ret); + return handle_nsapi_size_or_error("Socket::send()", ret); } static nsapi_size_or_error_t tcp_recv_command_handler(SInfo *info, int argc, char *argv[]) @@ -768,7 +884,7 @@ static nsapi_size_or_error_t tcp_recv_command_handler(SInfo *info, int argc, cha return CMDLINE_RETCODE_FAIL; } - nsapi_size_or_error_t ret = static_cast(info->socket()).recv(data, len); + nsapi_size_or_error_t ret = info->socket().recv(data, len); if (ret > 0) { cmd_printf("received: %d bytes\r\n", ret); print_data((const uint8_t *)data, ret); @@ -778,7 +894,7 @@ static nsapi_size_or_error_t tcp_recv_command_handler(SInfo *info, int argc, cha info->setRecvTotal(info->getRecvTotal() + ret); } free(data); - return handle_nsapi_size_or_error("TCPSocket::recv()", ret); + return handle_nsapi_size_or_error("Socket::recv()", ret); } static nsapi_size_or_error_t recv_all(char *const rbuffer, const int expt_len, SInfo *const info) @@ -790,7 +906,7 @@ static nsapi_size_or_error_t recv_all(char *const rbuffer, const int expt_len, S rhead = rbuffer; while (rtotal < expt_len) { - rbytes = info->tcp_socket()->recv(rhead, expt_len); + rbytes = info->socket().recv(rhead, expt_len); if (rbytes <= 0) { // Connection closed abruptly rbuffer[rtotal] = '\0'; return rbytes; @@ -809,7 +925,7 @@ static void bg_traffic_thread(SInfo *info) char sbuffer[data_len + 1] = "dummydata_"; char rbuffer[data_len + 1]; int scount, rtotal = 0; - info->setSenderThreadId(Thread::gettid()); + info->setSenderThreadId(ThisThread::get_id()); for (;;) { if (!info->available()) { @@ -817,7 +933,7 @@ static void bg_traffic_thread(SInfo *info) break; } sbuffer[data_len - 1] = 'A' + (rand() % 26); - scount = info->tcp_socket()->send(sbuffer, data_len); + scount = info->socket().send(sbuffer, data_len); rtotal = recv_all(rbuffer, data_len, info); if (scount != rtotal || (strcmp(sbuffer, rbuffer) != 0)) { @@ -920,14 +1036,18 @@ static int cmd_socket(int argc, char *argv[]) } switch (info->type()) { - case SInfo::TCP_CLIENT: - return handle_nsapi_error("Socket::open()", info->tcp_socket()->open(interface)); - case SInfo::UDP: - return handle_nsapi_error("Socket::open()", info->udp_socket()->open(interface)); + case SInfo::IP: + return handle_nsapi_error("Socket::open()", info->internetsocket()->open(interface)); case SInfo::TCP_SERVER: - return handle_nsapi_error("Socket::open()", info->tcp_server()->open(interface)); + return handle_nsapi_error("TCPServer::open()", info->tcp_server()->open(interface)); +#if defined(MBEDTLS_SSL_CLI_C) + case SInfo::TLS: + return handle_nsapi_error("Socket::open()", info->tls_socket()->open(interface)); +#endif + default: + cmd_printf("Not a IP socket\r\n"); + return CMDLINE_RETCODE_FAIL; } - } else if (COMMAND_IS("close")) { return handle_nsapi_error("Socket::close()", info->socket().close()); @@ -986,12 +1106,6 @@ static int cmd_socket(int argc, char *argv[]) * Commands related to UDPSocket: * sendto, recvfrom */ - if ((COMMAND_IS("sendto") || COMMAND_IS("recvfrom") || COMMAND_IS("start_udp_receiver_thread") - || COMMAND_IS("last_data_received")) && info->type() != SInfo::UDP) { - cmd_printf("Not UDPSocket\r\n"); - return CMDLINE_RETCODE_FAIL; - } - if (COMMAND_IS("sendto")) { return udp_sendto_command_handler(info, argc, argv); } else if (COMMAND_IS("recvfrom")) { @@ -1013,22 +1127,13 @@ static int cmd_socket(int argc, char *argv[]) } thread_clean_up(info); - return handle_nsapi_error("UDPSocket::last_data_received()", NSAPI_ERROR_OK); + return handle_nsapi_error("Socket::last_data_received()", NSAPI_ERROR_OK); } /* - * Commands related to TCPSocket + * Commands related to TCPSocket, TLSSocket * connect, send, recv */ - if ((COMMAND_IS("connect") || COMMAND_IS("recv") - || COMMAND_IS("start_tcp_receiver_thread") || COMMAND_IS("join_tcp_receiver_thread") - || COMMAND_IS("start_bg_traffic_thread") || COMMAND_IS("join_bg_traffic_thread") - || COMMAND_IS("setsockopt_keepalive") || COMMAND_IS("getsockopt_keepalive")) - && info->type() != SInfo::TCP_CLIENT) { - cmd_printf("Not TCPSocket\r\n"); - return CMDLINE_RETCODE_FAIL; - } - if (COMMAND_IS("connect")) { char *host; int32_t port; @@ -1046,7 +1151,18 @@ static int cmd_socket(int argc, char *argv[]) } cmd_printf("Host name: %s port: %" PRId32 "\r\n", host, port); - return handle_nsapi_error("TCPSocket::connect()", static_cast(info->socket()).connect(host, port)); + if (info->type() == SInfo::IP) { + SocketAddress addr(NULL, port); + nsapi_error_t ret = get_interface()->gethostbyname(host, &addr); + if (ret) { + return handle_nsapi_error("NetworkInterface::gethostbyname()", ret); + } + return handle_nsapi_error("Socket::connect()", info->socket().connect(addr)); +#if defined(MBEDTLS_SSL_CLI_C) + } else if (info->type() == SInfo::TLS) { + return handle_nsapi_error("TLSSocket::connect()", static_cast(info->socket()).connect(host, port)); +#endif + } } else if (COMMAND_IS("send")) { return tcp_send_command_handler(info, argc, argv); @@ -1091,7 +1207,7 @@ static int cmd_socket(int argc, char *argv[]) ret = info->socket().setsockopt(NSAPI_SOCKET, NSAPI_KEEPALIVE, &seconds, sizeof(seconds)); - return handle_nsapi_error("TCPSocket::setsockopt()", ret); + return handle_nsapi_error("Socket::setsockopt()", ret); } else if (COMMAND_IS("getsockopt_keepalive")) { int32_t optval; unsigned optlen = sizeof(optval); @@ -1103,47 +1219,72 @@ static int cmd_socket(int argc, char *argv[]) return CMDLINE_RETCODE_FAIL; } if (ret < 0) { - return handle_nsapi_error("TCPSocket::getsockopt()", ret); + return handle_nsapi_error("Socket::getsockopt()", ret); } - return handle_nsapi_size_or_error("TCPSocket::getsockopt()", optval); + return handle_nsapi_size_or_error("Socket::getsockopt()", optval); } /* * Commands for TCPServer * listen, accept */ - if ((COMMAND_IS("listen") || COMMAND_IS("accept")) && info->type() != SInfo::TCP_SERVER) { - cmd_printf("Not TCPServer\r\n"); - return CMDLINE_RETCODE_FAIL; - } if (COMMAND_IS("listen")) { int32_t backlog; if (cmd_parameter_int(argc, argv, "listen", &backlog)) { - return handle_nsapi_error("TCPServer::listen()", static_cast(info->socket()).listen(backlog)); + return handle_nsapi_error("TCPServer::listen()", info->socket().listen(backlog)); } else { - return handle_nsapi_error("TCPServer::listen()", static_cast(info->socket()).listen()); + return handle_nsapi_error("TCPServer::listen()", info->socket().listen()); } } else if (COMMAND_IS("accept")) { - SocketAddress addr; - int32_t id; - if (!cmd_parameter_int(argc, argv, "accept", &id)) { - cmd_printf("Need new socket id\r\n"); - return CMDLINE_RETCODE_INVALID_PARAMETERS; + nsapi_error_t ret; + + if (info->type() != SInfo::TCP_SERVER) { + Socket *new_sock = info->socket().accept(&ret); + if (ret == NSAPI_ERROR_OK) { + SInfo *new_info = new SInfo(new_sock, false); + m_sockets.push_back(new_info); + cmd_printf("Socket::accept() new socket sid: %d\r\n", new_info->id()); + } + return handle_nsapi_error("Socket::accept()", ret); + } else { // Old TCPServer API + int32_t id; + SocketAddress addr; + + if (!cmd_parameter_int(argc, argv, "accept", &id)) { + cmd_printf("Need new socket id\r\n"); + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + SInfo *new_info = get_sinfo(id); + if (!new_info) { + cmd_printf("Invalid socket id\r\n"); + return CMDLINE_RETCODE_FAIL; + } + TCPSocket *new_sock = static_cast(&new_info->socket()); + nsapi_error_t ret = static_cast(info->socket()).accept(new_sock, &addr); + if (ret == NSAPI_ERROR_OK) { + cmd_printf("TCPServer::accept() new socket sid: %d connection from %s port %d\r\n", + new_info->id(), addr.get_ip_address(), addr.get_port()); + } + return handle_nsapi_error("TCPServer::accept()", ret); } - SInfo *new_info = get_sinfo(id); - if (!new_info) { - cmd_printf("Invalid socket id\r\n"); + } + + + /* + * Commands for TLSSocket + * set_root_ca_cert + */ +#if defined(MBEDTLS_SSL_CLI_C) + if (COMMAND_IS("set_root_ca_cert")) { + if (info->type() != SInfo::TLS) { + cmd_printf("Not a TLS socket.\r\n"); return CMDLINE_RETCODE_FAIL; } - TCPSocket *new_sock = static_cast(&new_info->socket()); - nsapi_error_t ret = static_cast(info->socket()).accept(new_sock, &addr); - if (ret == NSAPI_ERROR_OK) { - cmd_printf("TCPServer::accept() new socket sid: %d connection from %s port %d\r\n", - new_info->id(), addr.get_ip_address(), addr.get_port()); - } - return handle_nsapi_error("TCPServer::accept()", ret); + return handle_nsapi_error("TLSSocket::tls_set_cert", tls_set_cert(argc, argv, info)); } +#endif + return CMDLINE_RETCODE_INVALID_PARAMETERS; } @@ -1159,7 +1300,7 @@ void print_data(const uint8_t *buf, int len) case PRINT_DISABLED: break; default: - assert(0); + MBED_ASSERT(0); } } diff --git a/TEST_APPS/testcases/nanostack_mac_tester/ED_scan.py b/TEST_APPS/testcases/nanostack_mac_tester/ED_scan.py new file mode 100644 index 0000000000..1eac278fba --- /dev/null +++ b/TEST_APPS/testcases/nanostack_mac_tester/ED_scan.py @@ -0,0 +1,107 @@ +""" +Copyright (c) 2017, 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 threading +import os,sys +from icetea_lib.bench import Bench + +class Testcase(Bench): + def __init__(self): + Bench.__init__(self, name = "ED_scan", + title = "ED scan test", + status = "development", + type = "smoke", + subtype = "", + execution = { + "skip": { + "value": False, + "reason": "" + } + }, + author = "Valtteri Erkkila", + purpose = "Tests reading the ED values from channels 11-16", + feature = ["MLME-SCAN (ED)"], + component = ["MAC"], + requirements = { + "duts": { + '*': { + "count":3, + "type": "hardware", + "allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW24D", "UBLOX_EVK_ODIN_W2"], + "application": { + "name": "TEST_APPS-device-nanostack_mac_tester" + } + }, + "1":{"nick": "First"}, + "2":{"nick": "Second"}, + "3":{"nick": "Third"} + }} + ) + + def setUp(self): + self.channel = 11 + self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01") + self.command("Second", "addr --64-bit 01:02:03:00:00:00:00:02") + self.command("Third", "addr --64-bit 01:02:03:00:00:00:00:03") + + def spam_channel(self, event): + while not event.wait(0.1): + self.lock_th.acquire() + self.command("First", "data --dst_addr 01:02:03:00:00:00:00:03 --msdu {} --msdu_length {} --wait_for_confirm false".format(self.payload, len(self.payload))) + self.command("Third", "data --dst_addr 01:02:03:00:00:00:00:01 --msdu {} --msdu_length {} --wait_for_confirm false".format(self.payload, len(self.payload))) + self.lock_th.release() + + def mask_from_channel_list(self, channels): + res = 0 + for ch in channels: + res = res | ( 1 << ch) + return hex(res) + + def case(self): + self.lock_th = threading.Lock() + self.payload = "01234567890123456789012345678901234567890123456789" + + self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel)) + self.command("Second", "start --pan_coordinator false --logical_channel {}".format(self.channel)) + self.command("Third", "start --pan_coordinator false --logical_channel {}".format(self.channel)) + + #No reason to print their spamming + self.command("First", "silent-mode on") + self.command("Third", "silent-mode on") + + self.stop_event = threading.Event() + self.th = threading.Thread(target=self.spam_channel, args=(self.stop_event,)) + self.th.start() + self.stopped = True + channels = range(11,27) + for i in range(0, 3): + self.lock_th.acquire() + self.command("First", "mlme-reset") + self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel)) + self.command("Third", "mlme-reset") + self.command("Third", "start --pan_coordinator false --logical_channel {}".format(self.channel)) + self.lock_th.release() + self.command("Second", "scan --scan_type 0 --scan_duration 7 --channel_mask {}".format(self.mask_from_channel_list(channels))) + self.command("Second", "analyze-ed --channel {} --above 100".format(self.channel)) + + def tearDown(self): + self.command("First", "silent-mode off") + self.command("Third", "silent-mode off") + self.stop_event.set() + self.th.join() + del self.th + self.reset_dut() diff --git a/TEST_APPS/testcases/nanostack_mac_tester/__init__.py b/TEST_APPS/testcases/nanostack_mac_tester/__init__.py new file mode 100644 index 0000000000..4265cc3e6c --- /dev/null +++ b/TEST_APPS/testcases/nanostack_mac_tester/__init__.py @@ -0,0 +1 @@ +#!/usr/bin/env python diff --git a/TEST_APPS/testcases/nanostack_mac_tester/address_read_and_write.py b/TEST_APPS/testcases/nanostack_mac_tester/address_read_and_write.py new file mode 100644 index 0000000000..d05efa4ed2 --- /dev/null +++ b/TEST_APPS/testcases/nanostack_mac_tester/address_read_and_write.py @@ -0,0 +1,65 @@ +""" +Copyright (c) 2017, 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 os,sys +from icetea_lib.bench import Bench + +class Testcase(Bench): + def __init__(self): + Bench.__init__(self, name = "address_read_and_write", + title = "MAC address and PAN id read/write test", + status = "development", + type = "smoke", + subtype = "", + execution = { + "skip": { + "value": False, + "reason": "" + } + }, + author = "Valtteri Erkkila", + purpose = "Tests reading a MAC address from the driver, and writing to the modifiable MAC address", + feature = ["MLME-SET"], + component = ["MAC"], + requirements = { + "duts": { + '*': { + "count":1, + "type": "hardware", + "allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW24D", "UBLOX_EVK_ODIN_W2"], + "application": { + "name": "TEST_APPS-device-nanostack_mac_tester" + } + }, + "1":{"nick": "First"} + }} + ) + + def setUp(self): + pass + + def case(self): + self.command("First", "addr") + self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01") + self.command("First", "addr --16-bit 0xABCD") + #macPANId + self.command("First", "mlme-set --attr 0x50 --value_bytes CD:CD --value_size 2") + self.command("First", "addr") + self.verify_trace(1, "MAC64: 01:02:03:00:00:00:00:01") + + def tearDown(self): + self.reset_dut() diff --git a/TEST_APPS/testcases/nanostack_mac_tester/create_and_join_PAN.py b/TEST_APPS/testcases/nanostack_mac_tester/create_and_join_PAN.py new file mode 100644 index 0000000000..c141df269a --- /dev/null +++ b/TEST_APPS/testcases/nanostack_mac_tester/create_and_join_PAN.py @@ -0,0 +1,86 @@ +""" +Copyright (c) 2017, 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 os,sys +from icetea_lib.bench import Bench + +class Testcase(Bench): + def __init__(self): + Bench.__init__(self, name = "create_and_join_PAN", + title = "Create a PAN and have a device join it", + status = "development", + type = "smoke", + subtype = "", + execution = { + "skip": { + "value": False, + "reason": "" + } + }, + author = "Valtteri Erkkila", + purpose = "", + feature = ["MLME-START", "MLME-SCAN (active)"], + component = ["MAC"], + requirements = { + "duts": { + '*': { + "count":3, + "type": "hardware", + "allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW24D", "UBLOX_EVK_ODIN_W2"], + "application": { + "name": "TEST_APPS-device-nanostack_mac_tester" + } + }, + "1":{"nick": "First"}, + "2":{"nick": "Second"}, + "3":{"nick": "Third"} + }} + ) + + def mask_from_channel_list(self, channels): + res = 0 + for ch in channels: + res = res | ( 1 << ch) + return hex(res) + + def setUp(self): + self.channel = 11 + + def case(self): + #Beacon payload & length + self.command("First", "mlme-set --attr 0x45 --value_ascii mac-tester --value_size 10") + self.command("First", "mlme-set --attr 0x46 --value_uint8 10 --value_size 1") + + self.command("Second", "mlme-set --attr 0x45 --value_ascii second-mac-tester --value_size 17") + self.command("Second", "mlme-set --attr 0x46 --value_uint8 17 --value_size 1") + + self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel)) + self.command("Second", "start --pan_coordinator true --logical_channel {}".format(int(self.channel)+1)) + self.delay(3) + if self.channel == 11: + channels = [11,12] + elif self.channel == 26: + channels = [25,26] + else: + channels = [self.channel, self.channel+1] + self.command("Third", "scan --channel_mask {}".format(self.mask_from_channel_list(channels))) + self.delay(0.2) + self.command("Third", "find-beacon --data mac-tester") + self.command("Third", "find-beacon --data second-mac-tester") + + def tearDown(self): + self.reset_dut() diff --git a/TEST_APPS/testcases/nanostack_mac_tester/send_data.py b/TEST_APPS/testcases/nanostack_mac_tester/send_data.py new file mode 100644 index 0000000000..575b00c545 --- /dev/null +++ b/TEST_APPS/testcases/nanostack_mac_tester/send_data.py @@ -0,0 +1,66 @@ +""" +Copyright (c) 2017, 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 os,sys +from icetea_lib.bench import Bench + +class Testcase(Bench): + def __init__(self): + Bench.__init__(self, name = "send_data", + title = "Simple data transmission test", + status = "development", + type = "smoke", + subtype = "", + execution = { + "skip": { + "value": False, + "reason": "" + } + }, + author = "Valtteri Erkkila", + purpose = "Tests that sending data works", + feature = ["MCPS-DATA"], + component = ["MAC"], + requirements = { + "duts": { + '*': { + "count":2, + "type": "hardware", + "allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW24D", "UBLOX_EVK_ODIN_W2"], + "application": { + "name": "TEST_APPS-device-nanostack_mac_tester" + } + }, + "1":{"nick": "First"}, + "2":{"nick": "Second"} + }} + ) + + def setUp(self): + self.channel = 11 + self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01") + self.command("Second", "addr --64-bit 01:02:03:00:00:00:00:02") + + def case(self): + self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel)) + self.command("Second", "start --pan_coordinator false --logical_channel {}".format(self.channel)) + + self.command("First", "data --dst_addr 01:02:03:00:00:00:00:02 --msdu_length 5 --msdu abcde") + self.command("Second", "data --dst_addr 01:02:03:00:00:00:00:01 --msdu_length 5 --msdu 12345") + + def tearDown(self): + self.reset_dut() diff --git a/TEST_APPS/testcases/nanostack_mac_tester/send_data_indirect.py b/TEST_APPS/testcases/nanostack_mac_tester/send_data_indirect.py new file mode 100644 index 0000000000..241db37b4b --- /dev/null +++ b/TEST_APPS/testcases/nanostack_mac_tester/send_data_indirect.py @@ -0,0 +1,96 @@ +""" +Copyright (c) 2017, 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 os,sys +from icetea_lib.bench import Bench + +class Testcase(Bench): + def __init__(self): + Bench.__init__(self, name = "send_data_indirect", + title = "Indirect data transmission test", + status = "development", + type = "smoke", + subtype = "", + execution = { + "skip": { + "value": False, + "reason": "" + } + }, + author = "Valtteri Erkkila", + purpose = "Tests sending data indirectly, i.e polling the coordinator for data", + feature = ["MCPS-DATA", "MLME-POLL"], + component = ["MAC"], + requirements = { + "duts": { + '*': { + "count":3, + "type": "hardware", + "allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW24D", "UBLOX_EVK_ODIN_W2"], + "application": { + "name": "TEST_APPS-device-nanostack_mac_tester" + } + }, + "1":{"nick": "First"}, + "2":{"nick": "Second"}, + "3":{"nick": "Third"} + }} + ) + + def setUp(self): + self.channel = 11 + self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01") + self.command("Second", "addr --64-bit 01:02:03:00:00:00:00:02") + self.command("Third", "addr --64-bit 01:02:03:00:00:00:00:03") + + def case(self): + self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel)) + self.command("Second", "start --pan_coordinator false --logical_channel {}".format(self.channel)) + self.command("Third", "start --pan_coordinator false --logical_channel {}".format(self.channel)) + + #macRxOnWhenIdle + self.command("Second", "mlme-set --attr 0x52 --value_uint8 0 --value_size 1") + self.command("Third", "mlme-set --attr 0x52 --value_uint8 0 --value_size 1") + + self.command("First", "add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:02 --pan_id 0x1234 --index 0") + self.command("First", "add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:03 --pan_id 0x1234 --index 1") + self.command("Second", "add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:01 --pan_id 0x1234 --index 0") + self.command("Third", "add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:01 --pan_id 0x1234 --index 0") + + self.command("Second", "config-status --data_ind abcde") + self.command("Third", "config-status --data_ind 12345") + + #Runs into timing issues if extensive printing is enabled + self.command("*", "silent-mode on") + self.command("First", "data --dst_addr 01:02:03:00:00:00:00:02 --msdu_length 5 --msdu abcde --indirect_tx true --wait_for_confirm false") + self.command("Second", "poll --coord_address 01:02:03:00:00:00:00:01") + + self.command("First", "data") + self.command("First", "data") + self.command("Second", "poll") + self.command("Second", "poll") + self.command("Second", "config-status --poll 235") + self.command("Second", "poll") + + self.command("Second", "config-status --poll 235") + self.command("First", "data --dst_addr 01:02:03:00:00:00:00:03 --msdu 12345") + self.command("Second", "poll") + self.command("Third", "poll --coord_address 01:02:03:00:00:00:00:01") + self.command("*", "silent-mode off") + + def tearDown(self): + self.reset_dut() diff --git a/TEST_APPS/testcases/nanostack_mac_tester/send_large_payloads.py b/TEST_APPS/testcases/nanostack_mac_tester/send_large_payloads.py new file mode 100644 index 0000000000..32121f2493 --- /dev/null +++ b/TEST_APPS/testcases/nanostack_mac_tester/send_large_payloads.py @@ -0,0 +1,79 @@ +""" +Copyright (c) 2017, 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 os,sys +from icetea_lib.bench import Bench + +class Testcase(Bench): + def __init__(self): + Bench.__init__(self, name = "send_large_payloads", + title = "Data transmission test with large packets", + status = "development", + type = "reliability", + subtype = "", + execution = { + "skip": { + "value": False, + "reason": "" + } + }, + author = "Valtteri Erkkila", + purpose = "Repeatedly sends long packets, checking that the payload is correct in each one", + feature = ["MCPS-DATA"], + component = ["MAC"], + requirements = { + "duts": { + '*': { + "count":2, + "type": "hardware", + "allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW24D", "UBLOX_EVK_ODIN_W2"], + "application": { + "name": "TEST_APPS-device-nanostack_mac_tester" + } + }, + "1":{"nick": "First"}, + "2":{"nick": "Second"} + }} + ) + + def setUp(self): + self.channel = 11 + self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01") + self.command("Second", "addr --64-bit 01:02:03:00:00:00:00:02") + + def case(self): + #104 characters, headers are 2+1+2+8+8+2=23 bytes, resulting in a packet size of 127 (max) + large_payload = "0123456789abcdefghjiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZZZZZZZZZ0123456789012345678901234567891234" + self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel)) + self.command("Second", "start --pan_coordinator false --logical_channel {}".format(self.channel)) + + self.command("First", "config-status --data_ind {}".format(large_payload)) + self.command("Second", "config-status --data_ind {}".format(large_payload)) + + self.command("First", "data --dst_addr 01:02:03:00:00:00:00:02 --msdu_length {} --msdu {}".format(len(large_payload), large_payload)) + self.command("Second", "wait --timeout 500") + + self.command("Second", "data --dst_addr 01:02:03:00:00:00:00:01 --msdu_length {} --msdu {}".format(len(large_payload), large_payload)) + self.command("First", "wait --timeout 500") + for i in range(0, 25): + self.command("First", "data") + self.command("Second", "wait") + self.command("Second", "data") + self.command("First", "wait") + + def tearDown(self): + self.reset_dut() diff --git a/TEST_APPS/testcases/nanostack_mac_tester/template b/TEST_APPS/testcases/nanostack_mac_tester/template new file mode 100644 index 0000000000..4335851efd --- /dev/null +++ b/TEST_APPS/testcases/nanostack_mac_tester/template @@ -0,0 +1,65 @@ +""" +Copyright (c) 2017, 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 os,sys +# ensure that test/ directory is first choice for imports +test_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +if not test_dir in sys.path: + sys.path.insert(0, test_dir) +from GenericTestcase import Bench +from Error import TestStepFail + +class Testcase(Bench): + def __init__(self): + Bench.__init__(self, name = "template", # Name should be the same as the filename + title = "TITLE", + status = "development", + type = "TYPE", + subtype = "", + execution = { + "skip": { + "value": False, + "reason": "" + } + }, + author = "Valtteri Erkkila", + purpose = "", + feature = [""], + component = ["MAC"], + requirements = { + "duts": { + '*': { + "count":2, # Count must reflect the amount of specified devices below + "type": "hardware", + "application":{ "name":"generalTestApplication", "version": "1.0"}, + "rf_channel": 11 + }, + "1":{"nick": "First"}, + "2":{"nick": "Second"} + }} + ) + + def setUp(self): + pass + + def case(self): + pass + + def tearDown(self): + pass + +if __name__=='__main__': + sys.exit( Testcase().run() ) diff --git a/TEST_APPS/testcases/netsocket/SOCKET_BIND_PORT.py b/TEST_APPS/testcases/netsocket/SOCKET_BIND_PORT.py index 4c601e770d..a0d300d7b6 100644 --- a/TEST_APPS/testcases/netsocket/SOCKET_BIND_PORT.py +++ b/TEST_APPS/testcases/netsocket/SOCKET_BIND_PORT.py @@ -43,15 +43,15 @@ class MultipleTestcase(Bench): def socket_bind_port(self, socket_type): response = self.command("dut1", "socket new " + socket_type) - socket_id = int(response.parsed['socket_id']) + self.socket_id = int(response.parsed['socket_id']) - self.command("dut1", "socket " + str(socket_id) + " open") + self.command("dut1", "socket " + str(self.socket_id) + " open") - self.command("dut1", "socket " + str(socket_id) + " bind port 1024") - - self.command("dut1", "socket " + str(socket_id) + " delete") + self.command("dut1", "socket " + str(self.socket_id) + " bind port 1024") def teardown(self): + self.command("dut1", "socket " + str(self.socket_id) + " delete") + self.command("dut1", "ifdown") diff --git a/TEST_APPS/testcases/netsocket/TCPSERVER_ACCEPT.py b/TEST_APPS/testcases/netsocket/TCPSERVER_ACCEPT.py index e975d68359..d5d2124251 100644 --- a/TEST_APPS/testcases/netsocket/TCPSERVER_ACCEPT.py +++ b/TEST_APPS/testcases/netsocket/TCPSERVER_ACCEPT.py @@ -62,15 +62,15 @@ class Testcase(Bench): self.used_port = 2000 response = self.command("dut1", "socket new TCPServer") - server_base_socket_id = int(response.parsed['socket_id']) + self.server_base_socket_id = int(response.parsed['socket_id']) - self.command("dut1", "socket " + str(server_base_socket_id) + " open") - self.command("dut1", "socket " + str(server_base_socket_id) + " bind port " + str(self.used_port)) - self.command("dut1", "socket " + str(server_base_socket_id) + " listen") + self.command("dut1", "socket " + str(self.server_base_socket_id) + " open") + self.command("dut1", "socket " + str(self.server_base_socket_id) + " bind port " + str(self.used_port)) + self.command("dut1", "socket " + str(self.server_base_socket_id) + " listen") response = self.command("dut1", "socket new TCPSocket") - server_socket_id = int(response.parsed['socket_id']) - self.command("dut1", "socket " + str(server_socket_id) + " open") + self.server_socket_id = int(response.parsed['socket_id']) + self.command("dut1", "socket " + str(self.server_socket_id) + " open") response = self.command("dut2", "socket new TCPSocket") zero = response.timedelta @@ -81,7 +81,7 @@ class Testcase(Bench): t.start() wait = 5 - response = self.command("dut1", "socket " + str(server_base_socket_id) + " accept " + str(server_socket_id)) + response = self.command("dut1", "socket " + str(self.server_base_socket_id) + " accept " + str(self.server_socket_id)) response.verify_response_duration(expected=wait, zero=zero, threshold_percent=10, break_in_fail=True) socket_id = int(response.parsed['socket_id']) @@ -94,10 +94,10 @@ class Testcase(Bench): if data != "hello": raise TestStepFail("Received data doesn't match the sent data") - self.command("dut1", "socket " + str(server_socket_id) + " delete") - self.command("dut1", "socket " + str(server_base_socket_id) + " delete") - self.command("dut2", "socket " + str(self.client_socket_id) + " delete") - def teardown(self): + self.command("dut1", "socket " + str(self.server_socket_id) + " delete") + self.command("dut1", "socket " + str(self.server_base_socket_id) + " delete") + self.command("dut2", "socket " + str(self.client_socket_id) + " delete") + interfaceDown(self, ["dut1"]) interfaceDown(self, ["dut2"]) diff --git a/TEST_APPS/testcases/netsocket/TCPSOCKET_ACCEPT.py b/TEST_APPS/testcases/netsocket/TCPSOCKET_ACCEPT.py new file mode 100644 index 0000000000..49cee2ff1e --- /dev/null +++ b/TEST_APPS/testcases/netsocket/TCPSOCKET_ACCEPT.py @@ -0,0 +1,106 @@ +""" +Copyright 2018 ARM Limited +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 threading +import time + +from icetea_lib.bench import Bench +from interface import interfaceUp, interfaceDown +#from mbed_clitest.tools import test_case +#from mbed_clitest.TestStepError import SkippedTestcaseException +from icetea_lib.TestStepError import TestStepFail + +class Testcase(Bench): + def __init__(self): + Bench.__init__(self, + name="TCPSOCKET_ACCEPT", + title = "TCPSOCKET_ACCEPT", + purpose = "Test that TCPSocket::bind(), TCPSocket::listen() and TCPSocket::accept() works", + status = "released", + component= ["mbed-os", "netsocket"], + type="smoke", + subtype="socket", + requirements={ + "duts": { + '*': { #requirements for all nodes + "count":2, + "type": "hardware", + "application": { + "name": "TEST_APPS-device-socket_app" + } + }, + "1": {"nick": "dut1"}, + "2": {"nick": "dut2"} + } + } + ) + + def setup(self): + interface = interfaceUp(self, ["dut1"]) + self.server_ip = interface["dut1"]["ip"] + interface = interfaceUp(self, ["dut2"]) + self.client_ip = interface["dut2"]["ip"] + + def clientThread(self): + self.logger.info("Starting") + time.sleep(5) #wait accept from server + self.command("dut2", "socket " + str(self.client_socket_id) + " open") + self.command("dut2", "socket " + str(self.client_socket_id) + " connect " + str(self.server_ip) + " " + str(self.used_port)) + + + def case(self): + self.used_port = 2000 + + response = self.command("dut1", "socket new TCPSocket") + self.server_base_socket_id = int(response.parsed['socket_id']) + + self.command("dut1", "socket " + str(self.server_base_socket_id) + " open") + response = self.command("dut1", "socket " + str(self.server_base_socket_id) + " bind port " + str(self.used_port), report_cmd_fail = False) + if response.retcode == -1: + if (response.verify_trace("NSAPI_ERROR_UNSUPPORTED", break_in_fail = False)): + raise SkippedTestcaseException("UNSUPPORTED") + else: + TestStepFail("Bind port failed") + self.command("dut1", "socket " + str(self.server_base_socket_id) + " listen") + + response = self.command("dut2", "socket new TCPSocket") + self.client_socket_id = int(response.parsed['socket_id']) + + #Create a thread which calls client connect() + t = threading.Thread(name='clientThread', target=self.clientThread) + t.start() + + response = self.command("dut1", "socket " + str(self.server_base_socket_id) + " accept") + + t.join() + self.accept_socket_id = int(response.parsed['socket_id']) + if response.timedelta < 5.0: # Check that socket accept call blocks + raise TestStepFail("Longer response time expected") + + self.command("dut1", "socket " + str(self.accept_socket_id) + " send hello") + + response = self.command("dut2", "socket " + str(self.client_socket_id) + " recv 5") + data = response.parsed['data'].replace(":","") + + if data != "hello": + raise TestStepFail("Received data doesn't match the sent data") + + def teardown(self): + response = self.command("dut2", "socket " + str(self.client_socket_id) + " delete") + response = self.command("dut1", "socket " + str(self.server_base_socket_id) + " delete") + response = self.command("dut1", "socket " + str(self.accept_socket_id) + " close") + + interfaceDown(self, ["dut1"]) + interfaceDown(self, ["dut2"]) diff --git a/TEST_APPS/testcases/netsocket/TCPSOCKET_ECHOTEST_BURST_SHORT.py b/TEST_APPS/testcases/netsocket/TCPSOCKET_ECHOTEST_BURST_SHORT.py index 3ac98da062..521db0e516 100644 --- a/TEST_APPS/testcases/netsocket/TCPSOCKET_ECHOTEST_BURST_SHORT.py +++ b/TEST_APPS/testcases/netsocket/TCPSOCKET_ECHOTEST_BURST_SHORT.py @@ -48,31 +48,30 @@ class Testcase(Bench): def case(self): response = self.command("dut1", "socket new TCPSocket") - socket_id = int(response.parsed['socket_id']) + self.socket_id = int(response.parsed['socket_id']) - self.command("dut1", "socket " + str(socket_id) + " open") - self.command("dut1", "socket " + str(socket_id) + " connect echo.mbedcloudtesting.com 7") + self.command("dut1", "socket " + str(self.socket_id) + " open") + self.command("dut1", "socket " + str(self.socket_id) + " connect echo.mbedcloudtesting.com 7") for i in range(2): sentData = "" for size in (100, 200, 300, 120, 500): packet = Randomize.random_string(max_len=size, min_len=size, chars=string.ascii_uppercase) sentData += packet - response = self.command("dut1", "socket " + str(socket_id) + " send " + str(packet)) - response.verify_trace("TCPSocket::send() returned: " + str(size)) + response = self.command("dut1", "socket " + str(self.socket_id) + " send " + str(packet)) + response.verify_trace("Socket::send() returned: " + str(size)) received = 0 data = "" totalSize = 1220 while received < totalSize: - response = self.command("dut1", "socket " + str(socket_id) + " recv " + str(totalSize)) + response = self.command("dut1", "socket " + str(self.socket_id) + " recv " + str(totalSize)) data += response.parsed['data'].replace(":", "") received += int(response.parsed['received_bytes']) if data != sentData: raise TestStepFail("Received data doesn't match the sent data") - self.command("dut1", "socket " + str(socket_id) + " delete") - def teardown(self): + self.command("dut1", "socket " + str(self.socket_id) + " delete") self.command("dut1", "ifdown") diff --git a/UNITTESTS/CMakeLists.txt b/UNITTESTS/CMakeLists.txt index a50455c689..15dcb0681e 100644 --- a/UNITTESTS/CMakeLists.txt +++ b/UNITTESTS/CMakeLists.txt @@ -119,6 +119,13 @@ set(unittest-includes-base "${PROJECT_SOURCE_DIR}/../features/cellular/framework/AT" "${PROJECT_SOURCE_DIR}/../features/cellular/framework" "${PROJECT_SOURCE_DIR}/../features/cellular/framework/common" + "${PROJECT_SOURCE_DIR}/../features/lorawan" + "${PROJECT_SOURCE_DIR}/../features/lorawan/lorastack" + "${PROJECT_SOURCE_DIR}/../features/lorawan/lorastack/mac" + "${PROJECT_SOURCE_DIR}/../features/lorawan/lorastack/phy" + "${PROJECT_SOURCE_DIR}/../features/lorawan/system" + "${PROJECT_SOURCE_DIR}/../features/mbedtls" + "${PROJECT_SOURCE_DIR}/../features/mbedtls/inc" ) # Create a list for test suites. diff --git a/UNITTESTS/README.md b/UNITTESTS/README.md index 4d40a7120e..9757cef939 100644 --- a/UNITTESTS/README.md +++ b/UNITTESTS/README.md @@ -1,6 +1,6 @@ ## Unit testing -This document describes how to write and test unit tests for Mbed OS. To prevent and solve problems, please see the [troubleshooting](#troubleshooting) section. +This document describes how to write and test unit tests for Arm Mbed OS. To prevent and solve problems, please see the [troubleshooting](#troubleshooting) section. ### Introduction @@ -11,12 +11,12 @@ Unit tests test code in small sections on a host machine. Unlike other testing t Please install the following dependencies to use Mbed OS unit testing. - GNU toolchains. - - GCC 6 or later. We recommend you use MinGW-W64 on Windows, but any Windows port of the above GCC versions works. + - GCC 6 or later. We recommend you use MinGW-W64 on Windows, but any Windows port of the above GCC versions works. Default compilers can be used on Mac OS instead of GCC to shorten build times, but code coverage results can then differ. - CMake 3.0 or newer. - Python 2.7.x, 3.5 or newer. - Pip 10.0 or newer. - Gcovr 4.1 or newer. -- Mbed CLI 1.8.0 or newer. +- Arm Mbed CLI 1.8.0 or newer. Detailed instructions for supported operating systems are below. @@ -30,12 +30,13 @@ Detailed instructions for supported operating systems are below. sudo easy_install pip ``` -1. Install Gcovr and [Mbed CLI](https://os.mbed.com/docs/latest/tools/arm-mbed-cli.html) with `pip install "gcovr>=4.1" mbed-cli`. +1. Install Gcovr and [Mbed CLI](https://os.mbed.com/docs/latest/tools/developing-arm-mbed-cli.html) with `pip install "gcovr>=4.1" mbed-cli`. #### Installing dependencies on macOS 1. Install [Homebrew](https://brew.sh/). -1. Install GCC compilers and CMake with: `brew install gcc cmake`. +1. Install Xcode Command Line Tools with `xcode-select --install`. +1. Install CMake with: `brew install cmake`. 1. Install Python and Pip: ``` @@ -43,7 +44,8 @@ Detailed instructions for supported operating systems are below. sudo easy_install pip ``` -1. Install Gcovr and [Mbed CLI](https://os.mbed.com/docs/latest/tools/arm-mbed-cli.html) with `pip install "gcovr>=4.1" mbed-cli`. +1. Install Gcovr and [Mbed CLI](https://os.mbed.com/docs/latest/tools/developing-arm-mbed-cli.html) with `pip install "gcovr>=4.1" mbed-cli`. +1. (Optional) Install GCC with `brew install gcc`. #### Installing dependencies on Windows @@ -51,7 +53,7 @@ Detailed instructions for supported operating systems are below. 1. Download CMake binaries from https://cmake.org/download/, and run the installer. 1. Download Python 2.7 or Python 3 from https://www.python.org/getit/, and run the installer. 1. Add MinGW, CMake and Python into system PATH. -1. Install Gcovr and [Mbed CLI](https://os.mbed.com/docs/latest/tools/arm-mbed-cli.html) with `pip install "gcovr>=4.1" mbed-cli`. +1. Install Gcovr and [Mbed CLI](https://os.mbed.com/docs/latest/tools/developing-arm-mbed-cli.html) with `pip install "gcovr>=4.1" mbed-cli`. ### Test code structure @@ -69,7 +71,7 @@ The build system automatically generates names of test suites. The name is const ### Unit testing with Mbed CLI -Mbed CLI supports unit tests through `mbed test --unittests` command. For information on using Mbed CLI, please see the [CLI documentation in handbook](https://os.mbed.com/docs/latest/tools/arm-mbed-cli.html). +Mbed CLI supports unit tests through `mbed test --unittests` command. For information on using Mbed CLI, please see the [CLI documentation](https://os.mbed.com/docs/latest/tools/developing-arm-mbed-cli.html). ### Writing unit tests @@ -154,7 +156,7 @@ TEST_F(TestSemaphore, constructor) ### Building and running unit tests -Use Mbed CLI to build and run unit tests. For advanced use, you can run CMake and a make program directly. +Use Mbed CLI to build and run unit tests. For advanced use, you can run CMake and a Make program directly. #### Build tests directly with CMake @@ -162,9 +164,11 @@ Use Mbed CLI to build and run unit tests. For advanced use, you can run CMake an 1. Move to the build directory `cd UNITTESTS/build`. 1. Run CMake using a relative path to `UNITTESTS` folder as the argument. So from `UNITTESTS/build` use `cmake ..`: - Add `-g [generator]` if generating other than Unix Makefiles such in case of MinGW use `-g "MinGW Makefiles"`. - - Add `-DCOVERAGE:True` to add coverage compiler flags. + - Add `-DCMAKE_MAKE_PROGRAM=`, `-DCMAKE_CXX_COMPILER=` and `-DCMAKE_C_COMPILER=` to use a specific Make program and compilers. + - Add `-DCMAKE_BUILD_TYPE=Debug` to build a debug build. + - Add `-DCOVERAGE=True` to add coverage compiler flags. - See the [CMake manual](https://cmake.org/cmake/help/v3.0/manual/cmake.1.html) for more information. -1. Run a make program (Make, Gmake, Mingw32-make and so on) to build the tests. +1. Run a Make program to build the tests. #### Run tests directly with CTest @@ -177,14 +181,27 @@ Run a test binary in the build directory to run a unit test suite. To run multip 1. Add test executables into the list. 1. Run them. +### Debugging + +1. Use Mbed CLI to build a debug build. For advanced use, run CMake directly with `-DCMAKE_BUILD_TYPE=Debug`, and then run a Make program. +1. Run GDB with a test executable as an argument to debug unit tests. + ### Get code coverage -Use Mbed CLI to generate code coverage reports. For advanced use, you can run Gcovr or any other code coverage tool directly in the build directory. +Use Mbed CLI to generate code coverage reports. For advanced use, follow these steps: + +1. Run CMake with both `-DCMAKE_BUILD_TYPE=Debug` and `-DCOVERAGE=True`. +1. Run a Make program to build the tests. +1. Run the tests. +1. Run Gcovr or any other code coverage tool directly in the build directory. ### Troubleshooting **Problem:** Generic problems with CMake or with the build process. -* **Solution**: Delete the build directory. Make sure that CMake, g++, gcc and a make program can be found in the path and are correct versions. +* **Solution**: Delete the build directory. Make sure that CMake, g++, GCC and a Make program can be found in the path and are correct versions. **Problem:** Virus protection identifies files generated by CMake as malicious and quarantines the files on Windows. * **Solution**: Restore the false positive files from the quarantine. + +**Problem:** CMake compiler check fails on Mac OS Mojave when using GCC-8. +* **Solution**: Make sure gnm (binutils) is not installed. Uninstall binutils with `brew uninstall binutils`. diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp b/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp index 7ab8f742f3..0722fc501f 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp @@ -26,10 +26,12 @@ using namespace events; class TestAT_CellularDevice : public testing::Test { protected: - void SetUp() { + void SetUp() + { } - void TearDown() { + void TearDown() + { } }; diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake index b3771ae7a3..9330d8a8da 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake @@ -20,17 +20,17 @@ set(unittest-sources # Test files set(unittest-test-sources features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp - stubs/AT_CellularNetwork_stub.cpp - stubs/ATHandler_stub.cpp - stubs/AT_CellularSMS_stub.cpp - stubs/AT_CellularSIM_stub.cpp - stubs/AT_CellularPower_stub.cpp - stubs/AT_CellularInformation_stub.cpp - stubs/CellularUtil_stub.cpp - stubs/AT_CellularBase_stub.cpp - stubs/NetworkInterface_stub.cpp - stubs/EventQueue_stub.cpp - stubs/FileHandle_stub.cpp - stubs/mbed_assert_stub.cpp + stubs/AT_CellularNetwork_stub.cpp + stubs/ATHandler_stub.cpp + stubs/AT_CellularSMS_stub.cpp + stubs/AT_CellularSIM_stub.cpp + stubs/AT_CellularPower_stub.cpp + stubs/AT_CellularInformation_stub.cpp + stubs/CellularUtil_stub.cpp + stubs/AT_CellularBase_stub.cpp + stubs/NetworkInterface_stub.cpp + stubs/EventQueue_stub.cpp + stubs/FileHandle_stub.cpp + stubs/mbed_assert_stub.c stubs/CellularDevice_stub.cpp ) diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularinformation/at_cellularinformationtest.cpp b/UNITTESTS/features/cellular/framework/AT/at_cellularinformation/at_cellularinformationtest.cpp index 4f2be58fbe..0a6d649e74 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularinformation/at_cellularinformationtest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularinformation/at_cellularinformationtest.cpp @@ -60,7 +60,7 @@ TEST_F(TestAT_CellularInformation, test_AT_CellularInformation_get_manufacturer) AT_CellularInformation aci(ah); ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; - ATHandler_stub::read_string_value = "some"; + ATHandler_stub::read_string_value = (char *)"some"; ATHandler_stub::ssize_value = 4; char buf[8]; @@ -82,7 +82,7 @@ TEST_F(TestAT_CellularInformation, test_AT_CellularInformation_get_model) AT_CellularInformation aci(ah); ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; - ATHandler_stub::read_string_value = "model"; + ATHandler_stub::read_string_value = (char *)"model"; ATHandler_stub::ssize_value = 5; char buf[8]; EXPECT_TRUE(NSAPI_ERROR_OK == aci.get_model(buf, 8)); @@ -105,7 +105,7 @@ TEST_F(TestAT_CellularInformation, test_AT_CellularInformation_get_revision) AT_CellularInformation *aci = new AT_CellularInformation(ah); ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; - ATHandler_stub::read_string_value = "revision"; + ATHandler_stub::read_string_value = (char *)"revision"; ATHandler_stub::ssize_value = 8; char buf[9]; @@ -129,7 +129,7 @@ TEST_F(TestAT_CellularInformation, test_AT_CellularInformation_get_serial_number AT_CellularInformation aci(ah); ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; - ATHandler_stub::read_string_value = "1234567"; + ATHandler_stub::read_string_value = (char *)"1234567"; ATHandler_stub::ssize_value = 7; char buf[8]; @@ -147,7 +147,7 @@ TEST_F(TestAT_CellularInformation, test_AT_CellularInformation_get_serial_number EXPECT_TRUE(strlen(buf) == 0); ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; - ATHandler_stub::read_string_value = "1234567"; + ATHandler_stub::read_string_value = (char *)"1234567"; ATHandler_stub::ssize_value = 7; AT_CellularBase_stub::supported_bool = true; EXPECT_TRUE(NSAPI_ERROR_OK == aci.get_serial_number(buf, 8, CellularInformation::IMEI)); diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularinformation/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellularinformation/unittest.cmake index 9a0a7435ce..57748f5e83 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularinformation/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularinformation/unittest.cmake @@ -20,9 +20,9 @@ set(unittest-sources # Test files set(unittest-test-sources features/cellular/framework/AT//at_cellularinformation/at_cellularinformationtest.cpp - stubs/ATHandler_stub.cpp - stubs/AT_CellularBase_stub.cpp - stubs/EventQueue_stub.cpp - stubs/FileHandle_stub.cpp - stubs/mbed_assert_stub.cpp + stubs/ATHandler_stub.cpp + stubs/AT_CellularBase_stub.cpp + stubs/EventQueue_stub.cpp + stubs/FileHandle_stub.cpp + stubs/mbed_assert_stub.c ) diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp b/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp index e54a8d2844..5e5c4b7d1b 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp @@ -252,7 +252,7 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_activate_context) ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::bool_value = false; ATHandler_stub::read_string_index = 1; - ATHandler_stub::read_string_table[0] = ""; + ATHandler_stub::read_string_table[0] = (char *)""; ATHandler_stub::int_value = 1; EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == cn.activate_context()); @@ -261,7 +261,7 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_activate_context) ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::bool_value = false; ATHandler_stub::read_string_index = 1; - ATHandler_stub::read_string_table[0] = "IPV6"; + ATHandler_stub::read_string_table[0] = (char *)"IPV6"; ATHandler_stub::int_value = 1; EXPECT_TRUE(NSAPI_ERROR_NO_CONNECTION == cn.activate_context()); @@ -270,8 +270,8 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_activate_context) ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::bool_value = false; ATHandler_stub::read_string_index = 2; - ATHandler_stub::read_string_table[0] = "internet"; - ATHandler_stub::read_string_table[1] = "IP"; + ATHandler_stub::read_string_table[0] = (char *)"internet"; + ATHandler_stub::read_string_table[1] = (char *)"IP"; ATHandler_stub::int_value = 1; EXPECT_TRUE(NSAPI_ERROR_OK == my_cn.set_credentials("apn", CellularNetwork::CHAP, "user", "passwd")); EXPECT_TRUE(NSAPI_ERROR_OK == my_cn.activate_context()); @@ -281,8 +281,8 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_activate_context) ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::bool_value = false; ATHandler_stub::read_string_index = 2; - ATHandler_stub::read_string_table[0] = "internet"; - ATHandler_stub::read_string_table[1] = "IPV4V6"; + ATHandler_stub::read_string_table[0] = (char *)"internet"; + ATHandler_stub::read_string_table[1] = (char *)"IPV4V6"; ATHandler_stub::int_value = 1; EXPECT_TRUE(NSAPI_ERROR_OK == my_cn.set_stack_type(IPV4_STACK)); EXPECT_TRUE(NSAPI_ERROR_OK == my_cn.set_credentials("internet")); @@ -293,8 +293,8 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_activate_context) ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::bool_value = false; ATHandler_stub::read_string_index = 2; - ATHandler_stub::read_string_table[0] = "internet"; - ATHandler_stub::read_string_table[1] = "IPV6"; + ATHandler_stub::read_string_table[0] = (char *)"internet"; + ATHandler_stub::read_string_table[1] = (char *)"IPV6"; ATHandler_stub::int_value = 1; EXPECT_TRUE(NSAPI_ERROR_OK == my_cnipv6.set_stack_type(IPV6_STACK)); EXPECT_TRUE(NSAPI_ERROR_OK == my_cnipv6.set_credentials("internet")); @@ -305,8 +305,8 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_activate_context) ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::bool_value = false; ATHandler_stub::read_string_index = 2; - ATHandler_stub::read_string_table[0] = "internet"; - ATHandler_stub::read_string_table[1] = "IPV4V6"; + ATHandler_stub::read_string_table[0] = (char *)"internet"; + ATHandler_stub::read_string_table[1] = (char *)"IPV4V6"; ATHandler_stub::int_value = 1; EXPECT_TRUE(NSAPI_ERROR_OK == my_cn.set_stack_type(DEFAULT_STACK)); EXPECT_TRUE(NSAPI_ERROR_OK == my_cn.set_credentials("internet")); @@ -317,8 +317,8 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_activate_context) ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::bool_value = false; ATHandler_stub::read_string_index = 2; - ATHandler_stub::read_string_table[0] = "internet"; - ATHandler_stub::read_string_table[1] = "IPV4V6"; + ATHandler_stub::read_string_table[0] = (char *)"internet"; + ATHandler_stub::read_string_table[1] = (char *)"IPV4V6"; ATHandler_stub::int_value = 1; EXPECT_TRUE(NSAPI_ERROR_OK == my_cnipv6.set_stack_type(DEFAULT_STACK)); EXPECT_TRUE(NSAPI_ERROR_OK == my_cnipv6.set_credentials("internet")); @@ -329,8 +329,8 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_activate_context) ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::bool_value = false; ATHandler_stub::read_string_index = 2; - ATHandler_stub::read_string_table[0] = "internet"; - ATHandler_stub::read_string_table[1] = "IPV6"; + ATHandler_stub::read_string_table[0] = (char *)"internet"; + ATHandler_stub::read_string_table[1] = (char *)"IPV6"; ATHandler_stub::int_value = 1; EXPECT_TRUE(NSAPI_ERROR_OK == my_cnipv6.set_stack_type(DEFAULT_STACK)); EXPECT_TRUE(NSAPI_ERROR_OK == my_cnipv6.set_credentials("internet")); @@ -341,8 +341,8 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_activate_context) ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::bool_value = false; ATHandler_stub::read_string_index = 2; - ATHandler_stub::read_string_table[0] = "internet"; - ATHandler_stub::read_string_table[1] = "IP"; + ATHandler_stub::read_string_table[0] = (char *)"internet"; + ATHandler_stub::read_string_table[1] = (char *)"IP"; ATHandler_stub::int_value = 1; EXPECT_TRUE(NSAPI_ERROR_OK == my_cn.set_stack_type(DEFAULT_STACK)); EXPECT_TRUE(NSAPI_ERROR_OK == my_cn.set_credentials("internet")); @@ -434,7 +434,7 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_set_registration) EXPECT_TRUE(NSAPI_ERROR_OK == cn.set_registration("12345")); } -TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_registration_status) +TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_registration_params) { EventQueue que; FileHandle_stub fh1; @@ -443,33 +443,86 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_registration_status) AT_CellularNetwork cn(at); ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::int_value = 3; - CellularNetwork::RegistrationStatus stat = CellularNetwork::NotRegistered; - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_status(CellularNetwork::C_EREG, stat)); - EXPECT_TRUE(stat == CellularNetwork::RegistrationDenied); - stat = CellularNetwork::NotRegistered; - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_status(CellularNetwork::C_GREG, stat)); - EXPECT_TRUE(stat == CellularNetwork::RegistrationDenied); + CellularNetwork::registration_params_t reg_params; + CellularNetwork::registration_params_t reg_params_check; + + EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(CellularNetwork::C_EREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::RegistrationDenied); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_EGPRS); + EXPECT_TRUE(reg_params._cell_id == -1); + + ATHandler_stub::read_string_index = 4; + ATHandler_stub::read_string_table[3] = "00C3"; + ATHandler_stub::read_string_table[2] = "1234FFC1";//== cellid and in dec: 305463233 + ATHandler_stub::read_string_table[1] = "00100100"; + ATHandler_stub::read_string_table[0] = "01000111"; + EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(CellularNetwork::C_EREG, reg_params)); + EXPECT_TRUE(reg_params._cell_id == 305463233); + EXPECT_TRUE(reg_params._active_time == 240); + EXPECT_TRUE(reg_params._periodic_tau == 70 * 60 * 60); + ATHandler_stub::read_string_index = kRead_string_table_size; + ATHandler_stub::read_string_value = NULL; + ATHandler_stub::ssize_value = 0; + // Check get_registration_params without specifying the registration type + EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(reg_params_check)); + EXPECT_TRUE(reg_params_check._status == CellularNetwork::RegistrationDenied); + EXPECT_TRUE(reg_params_check._act == CellularNetwork::RAT_EGPRS); + EXPECT_TRUE(reg_params_check._cell_id == 305463233); + EXPECT_TRUE(reg_params_check._active_time == 240); + EXPECT_TRUE(reg_params_check._periodic_tau == 70 * 60 * 60); + + reg_params._status = CellularNetwork::NotRegistered; + reg_params._act = CellularNetwork::RAT_GSM; + reg_params._cell_id = 1; + EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(CellularNetwork::C_GREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::RegistrationDenied); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_EGPRS); + EXPECT_TRUE(reg_params._cell_id == -1); my_AT_CN nw(at); - stat = CellularNetwork::NotRegistered; - EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == nw.get_registration_status(CellularNetwork::C_GREG, stat)); - EXPECT_TRUE(stat == CellularNetwork::NotRegistered); - EXPECT_TRUE(NSAPI_ERROR_OK == nw.get_registration_status(CellularNetwork::C_EREG, stat)); - EXPECT_TRUE(stat == CellularNetwork::RegistrationDenied); + reg_params._status = CellularNetwork::NotRegistered; + reg_params._act = CellularNetwork::RAT_GSM; + EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == nw.get_registration_params(CellularNetwork::C_GREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::NotRegistered); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_GSM); + + EXPECT_TRUE(NSAPI_ERROR_OK == nw.get_registration_params(CellularNetwork::C_EREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::RegistrationDenied); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_EGPRS); ATHandler_stub::nsapi_error_value = NSAPI_ERROR_DEVICE_ERROR; - stat = CellularNetwork::NotRegistered; - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_status(CellularNetwork::C_EREG, stat)); - EXPECT_TRUE(stat == -1); - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_status(CellularNetwork::C_GREG, stat)); - EXPECT_TRUE(stat == -1); + reg_params._status = CellularNetwork::NotRegistered; + reg_params._act = CellularNetwork::RAT_GSM; + reg_params._cell_id = 1; + reg_params._active_time = 2; + reg_params._periodic_tau = 3; - stat = CellularNetwork::NotRegistered; - EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == nw.get_registration_status(CellularNetwork::C_GREG, stat)); - EXPECT_TRUE(stat == CellularNetwork::NotRegistered); - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == nw.get_registration_status(CellularNetwork::C_EREG, stat)); - EXPECT_TRUE(stat == -1); + EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_params(CellularNetwork::C_EREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::StatusNotAvailable); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_UNKNOWN); + EXPECT_TRUE(reg_params._cell_id == -1 && reg_params._active_time == -1 && reg_params._periodic_tau == -1); + + EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_params(CellularNetwork::C_GREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::StatusNotAvailable); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_UNKNOWN); + EXPECT_TRUE(reg_params._cell_id == -1); + + reg_params._status = CellularNetwork::SearchingNetwork; + reg_params._act = CellularNetwork::RAT_GSM; + reg_params._cell_id = 1; + reg_params._active_time = 2; + reg_params._periodic_tau = 3; + + EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == nw.get_registration_params(CellularNetwork::C_EREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::StatusNotAvailable); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_UNKNOWN); + EXPECT_TRUE(reg_params._cell_id == -1 && reg_params._active_time == -1 && reg_params._periodic_tau == -1); + // Check get_registration_params without specifying the registration type + EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(reg_params_check)); + EXPECT_TRUE(reg_params_check._status == CellularNetwork::StatusNotAvailable); + EXPECT_TRUE(reg_params_check._act == CellularNetwork::RAT_UNKNOWN); + EXPECT_TRUE(reg_params_check._cell_id == -1 && reg_params_check._active_time == -1 && reg_params_check._periodic_tau == -1); } TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_network_registering_mode) @@ -762,19 +815,6 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_set_access_technology) EXPECT_TRUE(NSAPI_ERROR_OK == my_cn.set_access_technology(CellularNetwork::RAT_GSM_COMPACT)); } -TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_access_technology) -{ - EventQueue que; - FileHandle_stub fh1; - ATHandler at(&fh1, que, 0, ","); - - AT_CellularNetwork cn(at); - CellularNetwork::RadioAccessTechnology rat; - - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_access_technology(rat)); - EXPECT_TRUE(CellularNetwork::RAT_UNKNOWN == rat); -} - TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_scan_plmn) { EventQueue que; @@ -795,9 +835,9 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_scan_plmn) ATHandler_stub::read_string_index = 3; - ATHandler_stub::read_string_table[0] = "44444"; - ATHandler_stub::read_string_table[1] = "33333"; - ATHandler_stub::read_string_table[2] = "12345"; + ATHandler_stub::read_string_table[0] = (char *)"44444"; + ATHandler_stub::read_string_table[1] = (char *)"33333"; + ATHandler_stub::read_string_table[2] = (char *)"12345"; ATHandler_stub::int_value = 1; ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::info_elem_true_counter = 1; @@ -922,13 +962,13 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_pdpcontext_params) ATHandler_stub::int_valid_count_table[0] = 9; ATHandler_stub::read_string_index = 7; - ATHandler_stub::read_string_table[6] = "internet"; - ATHandler_stub::read_string_table[5] = "1.2.3.4.5.6.7.8.9.10.11.112.13.14.15.16.1.2.3.44.55.6.7.8.9.10.11.12.13.14.15.16"; - ATHandler_stub::read_string_table[4] = "23.33.44.1.2.3.55.123.225.34.11.1.0.0.123.234"; - ATHandler_stub::read_string_table[3] = "1.2.3.4"; - ATHandler_stub::read_string_table[2] = "0.255.0.255"; - ATHandler_stub::read_string_table[1] = "25.66.77.88"; - ATHandler_stub::read_string_table[0] = "004.003.002.001"; + ATHandler_stub::read_string_table[6] = (char *)"internet"; + ATHandler_stub::read_string_table[5] = (char *)"1.2.3.4.5.6.7.8.9.10.11.112.13.14.15.16.1.2.3.44.55.6.7.8.9.10.11.12.13.14.15.16"; + ATHandler_stub::read_string_table[4] = (char *)"23.33.44.1.2.3.55.123.225.34.11.1.0.0.123.234"; + ATHandler_stub::read_string_table[3] = (char *)"1.2.3.4"; + ATHandler_stub::read_string_table[2] = (char *)"0.255.0.255"; + ATHandler_stub::read_string_table[1] = (char *)"25.66.77.88"; + ATHandler_stub::read_string_table[0] = (char *)"004.003.002.001"; EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_pdpcontext_params(list)); CellularNetwork::pdpcontext_params_t *params = list.get_head(); @@ -989,34 +1029,6 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_signal_quality) EXPECT_TRUE(rs == 1 && ber == 1); } -TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_cell_id) -{ - EventQueue que; - FileHandle_stub fh1; - ATHandler at(&fh1, que, 0, ","); - - AT_CellularNetwork cn(at); - int id = 0; - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_cell_id(id)); - EXPECT_TRUE(id == -1); - - ATHandler_stub::nsapi_error_value = NSAPI_ERROR_DEVICE_ERROR; - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_cell_id(id)); - EXPECT_TRUE(id == -1); - - ATHandler_stub::read_string_index = 2; - ATHandler_stub::read_string_table[1] = "00C3"; - ATHandler_stub::read_string_table[0] = "1234FFC1"; //== cellid and in dec: 305463233 - ATHandler_stub::int_value = 1; - // Get registration status to modify cell_id - CellularNetwork::RegistrationType type; - CellularNetwork::RegistrationStatus status; - ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_status(CellularNetwork::C_EREG, status)); - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_cell_id(id)); - EXPECT_TRUE(id == 305463233); -} - TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_3gpp_error) { EventQueue que; @@ -1043,7 +1055,7 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_operator_params) ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::int_value = 0; ATHandler_stub::read_string_index = 1; - ATHandler_stub::read_string_table[0] = "12345"; + ATHandler_stub::read_string_table[0] = (char *)"12345"; EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_operator_params(format, ops)); EXPECT_TRUE(format == 0); EXPECT_TRUE(strcmp(ops.op_long, "12345") == 0); @@ -1054,7 +1066,7 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_operator_params) ops.op_long[0] = 0; ATHandler_stub::int_value = 1; ATHandler_stub::read_string_index = 1; - ATHandler_stub::read_string_table[0] = "12345"; + ATHandler_stub::read_string_table[0] = (char *)"12345"; EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_operator_params(format, ops)); EXPECT_TRUE(format == 1); EXPECT_TRUE(strlen(ops.op_long) == 0); @@ -1065,7 +1077,7 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_operator_params) ops.op_short[0] = 0; ATHandler_stub::int_value = 2; ATHandler_stub::read_string_index = 1; - ATHandler_stub::read_string_table[0] = "12345"; + ATHandler_stub::read_string_table[0] = (char *)"12345"; EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_operator_params(format, ops)); EXPECT_TRUE(format == 2); EXPECT_TRUE(strlen(ops.op_long) == 0); @@ -1097,8 +1109,8 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_operator_names) ATHandler_stub::resp_info_true_counter = 1; ATHandler_stub::bool_value = false; ATHandler_stub::read_string_index = 2; - ATHandler_stub::read_string_table[1] = "12345"; - ATHandler_stub::read_string_table[0] = "56789"; + ATHandler_stub::read_string_table[1] = (char *)"12345"; + ATHandler_stub::read_string_table[0] = (char *)"56789"; ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; name_list.delete_all(); EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_operator_names(name_list)); diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/unittest.cmake index 194109d8d2..48f7eae3ca 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/unittest.cmake @@ -21,14 +21,14 @@ set(unittest-sources # Test files set(unittest-test-sources features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp - stubs/ATHandler_stub.cpp - stubs/AT_CellularBase_stub.cpp - stubs/EventQueue_stub.cpp - stubs/FileHandle_stub.cpp - stubs/NetworkInterface_stub.cpp - stubs/NetworkStack_stub.cpp - stubs/us_ticker_stub.cpp - stubs/mbed_assert_stub.cpp - stubs/SocketAddress_stub.cpp - stubs/randLIB_stub.cpp + stubs/ATHandler_stub.cpp + stubs/AT_CellularBase_stub.cpp + stubs/EventQueue_stub.cpp + stubs/FileHandle_stub.cpp + stubs/NetworkInterface_stub.cpp + stubs/NetworkStack_stub.cpp + stubs/us_ticker_stub.cpp + stubs/mbed_assert_stub.c + stubs/SocketAddress_stub.cpp + stubs/randLIB_stub.cpp ) diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularpower/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellularpower/unittest.cmake index bf177affd9..82dc0e9b38 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularpower/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularpower/unittest.cmake @@ -24,5 +24,5 @@ set(unittest-test-sources stubs/EventQueue_stub.cpp stubs/FileHandle_stub.cpp stubs/CellularUtil_stub.cpp - stubs/mbed_assert_stub.cpp + stubs/mbed_assert_stub.c ) diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularsim/at_cellularsimtest.cpp b/UNITTESTS/features/cellular/framework/AT/at_cellularsim/at_cellularsimtest.cpp index eb82bc6c9a..e4fe6a1ce1 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularsim/at_cellularsimtest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularsim/at_cellularsimtest.cpp @@ -73,7 +73,7 @@ TEST_F(TestAT_CellularSIM, test_AT_CellularSIM_set_pin) EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == sim.set_pin("12")); ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; - ATHandler_stub::read_string_value = "READY"; + ATHandler_stub::read_string_value = (char *)"READY"; ATHandler_stub::ssize_value = 5; EXPECT_TRUE(NSAPI_ERROR_OK == sim.set_pin("12")); @@ -131,22 +131,22 @@ TEST_F(TestAT_CellularSIM, test_AT_CellularSIM_get_sim_state) EXPECT_TRUE(NSAPI_ERROR_OK == sim.get_sim_state(state)); EXPECT_TRUE(CellularSIM::SimStateUnknown == state); - ATHandler_stub::read_string_value = "READY"; + ATHandler_stub::read_string_value = (char *)"READY"; ATHandler_stub::ssize_value = 5; EXPECT_TRUE(NSAPI_ERROR_OK == sim.get_sim_state(state)); EXPECT_TRUE(CellularSIM::SimStateReady == state); - ATHandler_stub::read_string_value = "SIM PIN"; + ATHandler_stub::read_string_value = (char *)"SIM PIN"; ATHandler_stub::ssize_value = 7; EXPECT_TRUE(NSAPI_ERROR_OK == sim.get_sim_state(state)); EXPECT_TRUE(CellularSIM::SimStatePinNeeded == state); - ATHandler_stub::read_string_value = "SIM PUK"; + ATHandler_stub::read_string_value = (char *)"SIM PUK"; ATHandler_stub::ssize_value = 7; EXPECT_TRUE(NSAPI_ERROR_OK == sim.get_sim_state(state)); EXPECT_TRUE(CellularSIM::SimStatePukNeeded == state); - ATHandler_stub::read_string_value = "SOME CRAP"; + ATHandler_stub::read_string_value = (char *)"SOME CRAP"; ATHandler_stub::ssize_value = 9; EXPECT_TRUE(NSAPI_ERROR_OK == sim.get_sim_state(state)); EXPECT_TRUE(CellularSIM::SimStateUnknown == state); @@ -161,7 +161,7 @@ TEST_F(TestAT_CellularSIM, test_AT_CellularSIM_get_imsi) char imsi[16]; AT_CellularSIM sim(at); ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; - ATHandler_stub::read_string_value = "123456789012345"; + ATHandler_stub::read_string_value = (char *)"123456789012345"; ATHandler_stub::ssize_value = 15; EXPECT_TRUE(NSAPI_ERROR_OK == sim.get_imsi(imsi)); EXPECT_TRUE(strcmp(ATHandler_stub::read_string_value, imsi) == 0); @@ -190,7 +190,7 @@ TEST_F(TestAT_CellularSIM, test_AT_CellularSIM_get_iccid) char buf[16]; AT_CellularSIM sim(at); ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; - ATHandler_stub::read_string_value = "123456789012345"; + ATHandler_stub::read_string_value = (char *)"123456789012345"; ATHandler_stub::ssize_value = 15; EXPECT_TRUE(NSAPI_ERROR_OK == sim.get_iccid(buf, 16)); EXPECT_TRUE(strcmp(ATHandler_stub::read_string_value, buf) == 0); diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularsim/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellularsim/unittest.cmake index d3a6709606..7adbfef871 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularsim/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularsim/unittest.cmake @@ -25,5 +25,5 @@ set(unittest-test-sources stubs/FileHandle_stub.cpp stubs/CellularUtil_stub.cpp stubs/us_ticker_stub.cpp - stubs/mbed_assert_stub.cpp + stubs/mbed_assert_stub.c ) diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularsms/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellularsms/unittest.cmake index e9816c2ea3..616b49e49a 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularsms/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularsms/unittest.cmake @@ -25,6 +25,6 @@ set(unittest-test-sources stubs/FileHandle_stub.cpp stubs/CellularUtil_stub.cpp stubs/us_ticker_stub.cpp - stubs/mbed_assert_stub.cpp + stubs/mbed_assert_stub.c stubs/mbed_wait_api_stub.cpp ) diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularstack/at_cellularstacktest.cpp b/UNITTESTS/features/cellular/framework/AT/at_cellularstack/at_cellularstacktest.cpp index 40e2aebe9c..6ebd484dd4 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularstack/at_cellularstacktest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularstack/at_cellularstacktest.cpp @@ -175,13 +175,13 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_get_ip_address) ATHandler at(&fh1, que, 0, ","); MyStack st(at, 0, IPV6_STACK); - EXPECT_TRUE(0 == strlen(st.get_ip_address())); + EXPECT_EQ(strlen(st.get_ip_address()), 0); char table[] = "1.2.3.4.5.65.7.8.9.10.11\0"; ATHandler_stub::ssize_value = -1; ATHandler_stub::bool_value = true; ATHandler_stub::read_string_value = table; - EXPECT_TRUE(NULL == st.get_ip_address()); + EXPECT_TRUE(st.get_ip_address() == NULL); ATHandler_stub::ssize_value = strlen(table); ATHandler_stub::bool_value = true; @@ -197,18 +197,18 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_open) MyStack st(at, 0, IPV6_STACK); st.bool_value = false; - EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == st.socket_open(NULL, NSAPI_TCP)); + EXPECT_EQ(st.socket_open(NULL, NSAPI_TCP), NSAPI_ERROR_UNSUPPORTED); st.bool_value = true; st.max_sock_value = 0; nsapi_socket_t sock = &st.socket; - EXPECT_TRUE(NSAPI_ERROR_NO_SOCKET == st.socket_open(&sock, NSAPI_TCP)); + EXPECT_EQ(st.socket_open(&sock, NSAPI_TCP), NSAPI_ERROR_NO_SOCKET); MyStack st2(at, 0, IPV6_STACK); st2.bool_value = true; st2.max_sock_value = 1; sock = &st2.socket; - EXPECT_TRUE(NSAPI_ERROR_OK == st2.socket_open(&sock, NSAPI_TCP)); + EXPECT_EQ(st2.socket_open(&sock, NSAPI_TCP), NSAPI_ERROR_OK); } TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_close) @@ -218,21 +218,21 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_close) ATHandler at(&fh1, que, 0, ","); MyStack st(at, 0, IPV6_STACK); - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_close(&st.socket)); + EXPECT_EQ(st.socket_close(&st.socket), NSAPI_ERROR_DEVICE_ERROR); nsapi_socket_t sock = &st.socket; st.bool_value = true; st.max_sock_value = 1; - EXPECT_TRUE(NSAPI_ERROR_OK == st.socket_open(&sock, NSAPI_TCP)); + EXPECT_EQ(st.socket_open(&sock, NSAPI_TCP), NSAPI_ERROR_OK); st.max_sock_value = 0; - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_close(sock)); + EXPECT_EQ(st.socket_close(sock), NSAPI_ERROR_DEVICE_ERROR); MyStack st2(at, 0, IPV6_STACK); st2.max_sock_value = 1; st2.bool_value = true; sock = &st2.socket; - EXPECT_TRUE(NSAPI_ERROR_OK == st2.socket_open(&sock, NSAPI_TCP)); - EXPECT_TRUE(NSAPI_ERROR_OK == st2.socket_close(sock)); + EXPECT_EQ(st2.socket_open(&sock, NSAPI_TCP), NSAPI_ERROR_OK); + EXPECT_EQ(st2.socket_close(sock), NSAPI_ERROR_OK); } TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_bind) @@ -244,9 +244,9 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_bind) MyStack st(at, 0, IPV6_STACK); SocketAddress addr; ATHandler_stub::nsapi_error_value = NSAPI_ERROR_ALREADY; - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_bind(NULL, addr)); + EXPECT_EQ(st.socket_bind(NULL, addr), NSAPI_ERROR_DEVICE_ERROR); - EXPECT_TRUE(NSAPI_ERROR_ALREADY == st.socket_bind(&st.socket, addr)); + EXPECT_EQ(st.socket_bind(&st.socket, addr), NSAPI_ERROR_ALREADY); } TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_listen) @@ -256,7 +256,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_listen) ATHandler at(&fh1, que, 0, ","); MyStack st(at, 0, IPV6_STACK); - EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == st.socket_listen(&st.socket, 4)); + EXPECT_EQ(st.socket_listen(&st.socket, 4), NSAPI_ERROR_UNSUPPORTED); } TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_connect) @@ -267,9 +267,9 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_connect) MyStack st(at, 0, IPV6_STACK); SocketAddress addr; - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_connect(NULL, addr)); + EXPECT_EQ(st.socket_connect(NULL, addr), NSAPI_ERROR_DEVICE_ERROR); - EXPECT_TRUE(NSAPI_ERROR_OK == st.socket_connect(&st.socket, addr)); + EXPECT_EQ(st.socket_connect(&st.socket, addr), NSAPI_ERROR_OK); } TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_accept) @@ -280,7 +280,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_accept) MyStack st(at, 0, IPV6_STACK); nsapi_socket_t sock = &st.socket; - EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == st.socket_accept(NULL, &sock)); + EXPECT_EQ(st.socket_accept(NULL, &sock), NSAPI_ERROR_UNSUPPORTED); } TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_send) @@ -290,9 +290,9 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_send) ATHandler at(&fh1, que, 0, ","); MyStack st(at, 0, IPV6_STACK); - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_send(NULL, "addr", 4)); + EXPECT_EQ(st.socket_send(NULL, "addr", 4), NSAPI_ERROR_DEVICE_ERROR); - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_send(&st.socket, "addr", 4)); + EXPECT_EQ(st.socket_send(&st.socket, "addr", 4), NSAPI_ERROR_DEVICE_ERROR); SocketAddress addr; st.max_sock_value = 1; @@ -300,7 +300,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_send) nsapi_socket_t sock = &st.socket; st.socket_open(&sock, NSAPI_TCP); st.socket_connect(sock, addr); - EXPECT_TRUE(NSAPI_ERROR_OK == st.socket_send(sock, "addr", 4)); + EXPECT_EQ(st.socket_send(sock, "addr", 4), NSAPI_ERROR_OK); } TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_sendto) @@ -312,7 +312,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_sendto) MyStack st(at, 0, IPV6_STACK); SocketAddress addr; - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_sendto(NULL, addr, "addr", 4)); + EXPECT_EQ(st.socket_sendto(NULL, addr, "addr", 4), NSAPI_ERROR_DEVICE_ERROR); st.max_sock_value = 1; st.bool_value = true; @@ -320,10 +320,10 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_sendto) st.socket_open(&sock, NSAPI_TCP); st.socket_connect(sock, addr); st.create_error = NSAPI_ERROR_CONNECTION_LOST; - EXPECT_TRUE(NSAPI_ERROR_CONNECTION_LOST == st.socket_sendto(sock, addr, "addr", 4)); + EXPECT_EQ(st.socket_sendto(sock, addr, "addr", 4), NSAPI_ERROR_CONNECTION_LOST); st.create_error = NSAPI_ERROR_OK; - EXPECT_TRUE(NSAPI_ERROR_OK == st.socket_sendto(sock, addr, "addr", 4)); + EXPECT_EQ(st.socket_sendto(sock, addr, "addr", 4), NSAPI_ERROR_OK); } TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recv) @@ -334,7 +334,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recv) MyStack st(at, 0, IPV6_STACK); char table[4]; - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_recv(NULL, table, 4)); + EXPECT_EQ(st.socket_recv(NULL, table, 4), NSAPI_ERROR_DEVICE_ERROR); } TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recvfrom) @@ -345,7 +345,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recvfrom) MyStack st(at, 0, IPV6_STACK); char table[4]; - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_recvfrom(NULL, NULL, table, 4)); + EXPECT_EQ(st.socket_recvfrom(NULL, NULL, table, 4), NSAPI_ERROR_DEVICE_ERROR); SocketAddress addr; st.max_sock_value = 1; @@ -354,10 +354,10 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recvfrom) st.socket_open(&sock, NSAPI_TCP); st.socket_connect(sock, addr); st.create_error = NSAPI_ERROR_CONNECTION_LOST; - EXPECT_TRUE(NSAPI_ERROR_CONNECTION_LOST == st.socket_recvfrom(sock, &addr, table, 4)); + EXPECT_EQ(st.socket_recvfrom(sock, &addr, table, 4), NSAPI_ERROR_CONNECTION_LOST); st.create_error = NSAPI_ERROR_OK; - EXPECT_TRUE(NSAPI_ERROR_OK == st.socket_recvfrom(sock, &addr, table, 4)); + EXPECT_EQ(st.socket_recvfrom(sock, &addr, table, 4), NSAPI_ERROR_OK); } TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_attach) diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularstack/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellularstack/unittest.cmake index 5087e2f82e..2f1a243e02 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularstack/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularstack/unittest.cmake @@ -27,5 +27,5 @@ set(unittest-test-sources stubs/us_ticker_stub.cpp stubs/NetworkStack_stub.cpp stubs/SocketAddress_stub.cpp - stubs/mbed_assert_stub.cpp + stubs/mbed_assert_stub.c ) diff --git a/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp b/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp index 7a49a70c42..3f5d033a72 100644 --- a/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp @@ -143,7 +143,7 @@ TEST_F(TestATHandler, test_ATHandler_remove_urc_handler) at.set_urc_handler(ch, cb); //This does nothing!!! - at.remove_urc_handler(ch, cb); + at.remove_urc_handler(ch); } TEST_F(TestATHandler, test_ATHandler_get_last_error) @@ -460,7 +460,7 @@ TEST_F(TestATHandler, test_ATHandler_skip_param) fh1.short_value = POLLIN; at.resp_start(); at.skip_param(); - EXPECT_TRUE(at.get_last_error() == NSAPI_ERROR_DEVICE_ERROR); + EXPECT_TRUE(at.get_last_error() == NSAPI_ERROR_OK); char table1[] = "ss,sssssssssssss,sssssssssssOK\r\n\0"; filehandle_stub_table = table1; @@ -579,7 +579,7 @@ TEST_F(TestATHandler, test_ATHandler_read_string) EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == at.get_last_error()); at.clear_error(); // Device error because empty buffer and attempt to fill_buffer by consume_char('\"') - EXPECT_TRUE(-1 == at.read_string(buf1, 1)); + EXPECT_TRUE(0 == at.read_string(buf1, 1)); // *** 1 BYTE *** at.clear_error(); @@ -599,7 +599,7 @@ TEST_F(TestATHandler, test_ATHandler_read_string) // *** CRLF *** at.clear_error(); - char table3[] = "\r\ns\r\n\0"; + char table3[] = "\r\n,s\r\n\0"; at.flush(); filehandle_stub_table = table3; filehandle_stub_table_pos = 0; @@ -670,13 +670,9 @@ TEST_F(TestATHandler, test_ATHandler_read_string) at.resp_start(); // TO read 1 byte from: "s"OK\r\n -> read " at.read_bytes(buf5, 1); - // TO read max 1 byte from: s"OK\r\n -> read s + // TO read max 1 byte from: s"OK\r\n -> read s + read to stop_tag(OKCRLF) EXPECT_TRUE(1 == at.read_string(buf4, 1 + 1/*for NULL*/)); - // *** Consume " and run into OKCRLF *** - // TO read max 1 byte from: "OK\r\n -> consume " and find stop tag OKCRLF - EXPECT_TRUE(0 == at.read_string(buf4, 1 + 1/*for NULL*/)); - // *** Try to read after stop tag was found *** // stop tag found do not read further EXPECT_TRUE(-1 == at.read_string(buf4, 1 + 1/*for NULL*/)); @@ -706,7 +702,7 @@ TEST_F(TestATHandler, test_ATHandler_read_string) mbed_poll_stub::revents_value = POLLIN; mbed_poll_stub::int_value = 1; at.resp_start("s"); - // TO read from buffer having only " -> consume " -> trying to read when nothing in buffer + // TO read from buffer having only " -> trying to find delimiter or stop_tag(OKCRLF) EXPECT_TRUE(-1 == at.read_string(buf4, 5)); EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == at.get_last_error()); @@ -739,6 +735,21 @@ TEST_F(TestATHandler, test_ATHandler_read_string) // TO read from EXPECT_TRUE(6 == at.read_string(buf9, 6 + 1/*for NULL*/)); + at.clear_error(); + char table11[] = "\"1016\",\"39AB\",9\r\n\0"; + mbed_poll_stub::int_value = 0; + at.flush(); + filehandle_stub_table = table11; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + at.resp_start(); + EXPECT_TRUE(4 == at.read_string(buf4, 4 + 1/*for NULL*/)); + EXPECT_TRUE(!strncmp(buf4, "1016", 4)); + EXPECT_TRUE(4 == at.read_string(buf4, 4 + 1/*for NULL*/)); + EXPECT_TRUE(!strncmp(buf4, "39AB", 4)); + EXPECT_TRUE(9 == at.read_int()); + // *** CRLF part of the string *** at.clear_error(); char table10[] = "\"s\"\r\nOK\r\n\0"; @@ -924,15 +935,88 @@ TEST_F(TestATHandler, test_ATHandler_resp_start) filehandle_stub_table_pos = 0; at.resp_start(); - char table7[] = "ssssss\0"; + char table7[] = "urc: info\r\nresponseOK\r\n\0"; + at.flush(); + at.clear_error(); filehandle_stub_table = table7; filehandle_stub_table_pos = 0; + at.set_urc_handler("urc: ", NULL); + at.resp_start(); // recv_buff: "responseOK\r\n\0" + at.resp_stop(); // consumes to OKCRLF -> OK + EXPECT_TRUE(at.get_last_error() == NSAPI_ERROR_OK); + + char table8[] = "urc: info\r\nresponse\0"; at.flush(); at.clear_error(); - at.set_urc_handler("ss", NULL); + filehandle_stub_table = table8; filehandle_stub_table_pos = 0; + + at.set_urc_handler("urc: ", NULL); at.resp_start(); + at.resp_stop(); + // No stop tag(OKCRLF) found + EXPECT_TRUE(at.get_last_error() == NSAPI_ERROR_DEVICE_ERROR); + + char table9[] = "urc: prefix: infoOK\r\n\0"; + at.flush(); + at.clear_error(); + filehandle_stub_table = table9; + filehandle_stub_table_pos = 0; + + at.set_urc_handler("urc: ", NULL); + at.resp_start(); + // Match URC consumes to CRLF -> nothing to read after that -> ERROR + EXPECT_TRUE(at.get_last_error() == NSAPI_ERROR_DEVICE_ERROR); + + char table10[] = "urc: info\r\ngarbage\r\nprefix: info\r\nOK\r\n\0"; + at.flush(); + at.clear_error(); + filehandle_stub_table = table10; + filehandle_stub_table_pos = 0; + + at.set_urc_handler("urc: ", NULL); + at.resp_start("prefix"); // match URC -> consumes to first CRLF -> consumes the garbage because there is expected prefix and no match found -> then prefix match + at.resp_stop(); //ends the info scope -> consumes to CRLF -> ends the resp scope -> consumes to OKCRLF + EXPECT_TRUE(at.get_last_error() == NSAPI_ERROR_OK); + + // No stop tag(OKCRLF) will be found because, after match URC consumed everything to CRLF, rest of buffer + // is consumed to next/last CRLF because there is expected prefix and no match found + // -> nothing to read after that -> ERROR + char table11[] = "urc: info\r\ngarbageprefix: infoOK\r\n\0"; + at.flush(); + at.clear_error(); + filehandle_stub_table = table11; + filehandle_stub_table_pos = 0; + + at.set_urc_handler("urc: ", NULL); + at.resp_start("prefix"); + EXPECT_TRUE(at.get_last_error() == NSAPI_ERROR_DEVICE_ERROR); + + // After URC match no prefix match -> try to read more -> no more to read + char table12[] = "urc: infoprefix: info\0"; + at.flush(); + at.clear_error(); + filehandle_stub_table = table12; + filehandle_stub_table_pos = 0; + + at.set_urc_handler("urc: ", NULL); + at.resp_start("prefix"); + EXPECT_TRUE(at.get_last_error() == NSAPI_ERROR_DEVICE_ERROR); + + // Will run into mem_str check of identical strings + char table13[] = "\r\n\r\n\0"; + at.flush(); + at.clear_error(); + filehandle_stub_table = table13; + filehandle_stub_table_pos = 0; + + char buf[3]; + at.resp_start(); + EXPECT_TRUE(2 == at.read_string(buf, 3)); + EXPECT_TRUE(!strncmp(buf, "\r\n", 2)); + // Consume to delimiter or stop_tag OKCRLF fails -> ERROR + EXPECT_TRUE(at.get_last_error() == NSAPI_ERROR_DEVICE_ERROR); } TEST_F(TestATHandler, test_ATHandler_resp_stop) @@ -1052,6 +1136,27 @@ TEST_F(TestATHandler, test_ATHandler_consume_to_stop_tag) ATHandler at(&fh1, que, 0, ","); EXPECT_TRUE(at.consume_to_stop_tag()); + + at.clear_error(); + char table1[] = "\r\n\r\r\r\nOOK\r\n"; + at.flush(); + filehandle_stub_table = table1; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + char buf1[6]; + at.resp_start(); + EXPECT_TRUE(at.consume_to_stop_tag()); + + at.clear_error(); + char table2[] = "OKOK\r\n"; + at.flush(); + filehandle_stub_table = table2; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + char buf2[6]; + EXPECT_TRUE(at.consume_to_stop_tag()); } TEST_F(TestATHandler, test_ATHandler_set_debug) diff --git a/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake index 6fbe35d4aa..26bf570221 100644 --- a/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake @@ -25,12 +25,12 @@ set(unittest-test-sources stubs/FileHandle_stub.cpp stubs/us_ticker_stub.cpp stubs/mbed_wait_api_stub.cpp - stubs/mbed_assert_stub.cpp + stubs/mbed_assert_stub.c stubs/mbed_poll_stub.cpp stubs/Timer_stub.cpp stubs/equeue_stub.c stubs/Kernel_stub.cpp - stubs/Thread_stub.cpp + stubs/ThisThread_stub.cpp stubs/randLIB_stub.cpp ) diff --git a/UNITTESTS/features/cellular/framework/common/util/utiltest.cpp b/UNITTESTS/features/cellular/framework/common/util/utiltest.cpp index 4c00da93c2..09f87c87e1 100644 --- a/UNITTESTS/features/cellular/framework/common/util/utiltest.cpp +++ b/UNITTESTS/features/cellular/framework/common/util/utiltest.cpp @@ -35,6 +35,23 @@ protected: }; // *INDENT-ON* +TEST_F(Testutil, test_util_binary_str_to_uint) +{ + char binary_str[] = "011001011101101000"; + uint32_t value = binary_str_to_uint(binary_str, strlen(binary_str) + 1); + EXPECT_TRUE(value == 104296); + value = binary_str_to_uint(binary_str, strlen(binary_str)); + EXPECT_TRUE(value == 104296); + value = binary_str_to_uint(binary_str, strlen(binary_str) - 1); + EXPECT_TRUE(value == 52148); + value = binary_str_to_uint(binary_str, strlen(binary_str) - 3); + EXPECT_TRUE(value == 13037); + value = binary_str_to_uint(binary_str + 5, strlen(binary_str) - 5); + EXPECT_TRUE(value == 5992); + EXPECT_TRUE(0 == binary_str_to_uint(NULL, 5)); + EXPECT_TRUE(0 == binary_str_to_uint(binary_str, 0)); +} + TEST_F(Testutil, test_util_uint_to_binary_string) { char str[33]; @@ -193,7 +210,7 @@ TEST_F(Testutil, get_dynamic_ip_port) TEST_F(Testutil, int_to_hex_str) { char buf[2]; - int_to_hex_str(100, (char*)buf); + int_to_hex_str(100, (char *)buf); EXPECT_TRUE(buf[0] == '6'); EXPECT_TRUE(buf[1] == '4'); diff --git a/UNITTESTS/features/lorawan/loramac/Test_LoRaMac.cpp b/UNITTESTS/features/lorawan/loramac/Test_LoRaMac.cpp new file mode 100644 index 0000000000..8d73070983 --- /dev/null +++ b/UNITTESTS/features/lorawan/loramac/Test_LoRaMac.cpp @@ -0,0 +1,595 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaMac.h" +#include "LoRaPHY_stub.h" +#include "LoRaMacCrypto_stub.h" +#include "LoRaMacCommand_stub.h" +#include "LoRaWANTimer_stub.h" +#include "EventQueue_stub.h" + +using namespace events; + +class my_phy : public LoRaPHY { +public: + my_phy() + { + }; + + virtual ~my_phy() + { + }; +}; + +class Test_LoRaMac : public testing::Test { +protected: + LoRaMac *object; + + virtual void SetUp() + { + object = new LoRaMac(); + LoRaWANTimer_stub::time_value = 1; + } + + virtual void TearDown() + { + delete object; + } +}; + +TEST_F(Test_LoRaMac, constructor) +{ + EXPECT_TRUE(object); +} + +void my_cb() +{ + +} + +TEST_F(Test_LoRaMac, initialize) +{ + my_phy phy; + object->bind_phy(phy); + + lorawan_connect_t conn; + memset(&conn, 0, sizeof(conn)); + uint8_t key[16]; + memset(key, 0, sizeof(key)); + conn.connection_u.otaa.app_key = key; + conn.connection_u.otaa.app_eui = key; + conn.connection_u.otaa.dev_eui = key; + conn.connection_u.otaa.nb_trials = 2; + object->prepare_join(&conn, true); + + LoRaWANTimer_stub::call_cb_immediately = true; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize(NULL, my_cb)); +} + +TEST_F(Test_LoRaMac, disconnect) +{ + object->disconnect(); +} + +TEST_F(Test_LoRaMac, nwk_joined) +{ + EXPECT_EQ(false, object->nwk_joined()); +} + +TEST_F(Test_LoRaMac, add_channel_plan) +{ + lorawan_channelplan_t plan; + EXPECT_EQ(LORAWAN_STATUS_OK, object->add_channel_plan(plan)); + + object->set_tx_ongoing(true); + EXPECT_EQ(LORAWAN_STATUS_BUSY, object->add_channel_plan(plan)); +} + +TEST_F(Test_LoRaMac, remove_channel_plan) +{ + EXPECT_EQ(LORAWAN_STATUS_OK, object->remove_channel_plan()); + + object->set_tx_ongoing(true); + EXPECT_EQ(LORAWAN_STATUS_BUSY, object->remove_channel_plan()); +} + +TEST_F(Test_LoRaMac, get_channel_plan) +{ + lorawan_channelplan_t plan; + EXPECT_EQ(LORAWAN_STATUS_OK, object->get_channel_plan(plan)); +} + +TEST_F(Test_LoRaMac, remove_single_channel) +{ + EXPECT_EQ(LORAWAN_STATUS_OK, object->remove_single_channel(1)); + + object->set_tx_ongoing(true); + EXPECT_EQ(LORAWAN_STATUS_BUSY, object->remove_single_channel(1)); +} + +TEST_F(Test_LoRaMac, multicast_channel_link) +{ + multicast_params_t p; + memset(&p, 0, sizeof(p)); + + EXPECT_EQ(LORAWAN_STATUS_PARAMETER_INVALID, object->multicast_channel_link(NULL)); + + object->set_tx_ongoing(true); + EXPECT_EQ(LORAWAN_STATUS_BUSY, object->multicast_channel_link(&p)); + + object->set_tx_ongoing(false); + EXPECT_EQ(LORAWAN_STATUS_OK, object->multicast_channel_link(&p)); +} + +TEST_F(Test_LoRaMac, multicast_channel_unlink) +{ + multicast_params_t p; + memset(&p, 0, sizeof(p)); + + EXPECT_EQ(LORAWAN_STATUS_PARAMETER_INVALID, object->multicast_channel_unlink(NULL)); + + object->set_tx_ongoing(true); + EXPECT_EQ(LORAWAN_STATUS_BUSY, object->multicast_channel_unlink(&p)); + + object->set_tx_ongoing(false); + EXPECT_EQ(LORAWAN_STATUS_OK, object->multicast_channel_unlink(&p)); +} + +TEST_F(Test_LoRaMac, send) +{ + loramac_mhdr_t mac_hdr; + memset(&mac_hdr, 0, sizeof(mac_hdr)); + uint8_t buf[15]; + memset(buf, 0, sizeof(buf)); + mac_hdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP; + object->send(&mac_hdr, 1, buf, 15); +} + +TEST_F(Test_LoRaMac, get_default_tx_datarate) +{ + object->get_default_tx_datarate(); +} + +TEST_F(Test_LoRaMac, enable_adaptive_datarate) +{ + object->enable_adaptive_datarate(true); +} + +TEST_F(Test_LoRaMac, set_channel_data_rate) +{ + object->set_channel_data_rate(8); +} + +TEST_F(Test_LoRaMac, tx_ongoing) +{ + object->tx_ongoing(); +} + +TEST_F(Test_LoRaMac, set_tx_ongoing) +{ + object->set_tx_ongoing(true); +} + +TEST_F(Test_LoRaMac, reset_ongoing_tx) +{ + object->reset_ongoing_tx(true); +} + +TEST_F(Test_LoRaMac, prepare_ongoing_tx) +{ + uint8_t buf[16]; + memset(buf, 0, sizeof(buf)); + object->prepare_ongoing_tx(1, buf, 16, 1, 0); +} + +TEST_F(Test_LoRaMac, send_ongoing_tx) +{ + object->send_ongoing_tx(); +} + +TEST_F(Test_LoRaMac, get_device_class) +{ + object->get_device_class(); +} + +void exp_cb() +{ + +} + +TEST_F(Test_LoRaMac, set_device_class) +{ + object->set_device_class(CLASS_B, exp_cb); +} + +TEST_F(Test_LoRaMac, setup_link_check_request) +{ + object->setup_link_check_request(); +} + +TEST_F(Test_LoRaMac, prepare_join) +{ + lorawan_connect_t conn; + memset(&conn, 0, sizeof(conn)); + object->prepare_join(&conn, false); + + my_phy phy; + object->bind_phy(phy); + EXPECT_EQ(LORAWAN_STATUS_OK, object->join(false)); + + uint8_t key[16]; + conn.connection_u.otaa.app_key = NULL; + conn.connection_u.otaa.app_eui = NULL; + conn.connection_u.otaa.dev_eui = NULL; + conn.connection_u.otaa.nb_trials = 0; + EXPECT_EQ(LORAWAN_STATUS_PARAMETER_INVALID, object->prepare_join(&conn, true)); + + conn.connection_u.otaa.app_key = key; + conn.connection_u.otaa.app_eui = NULL; + conn.connection_u.otaa.dev_eui = NULL; + conn.connection_u.otaa.nb_trials = 0; + EXPECT_EQ(LORAWAN_STATUS_PARAMETER_INVALID, object->prepare_join(&conn, true)); + + conn.connection_u.otaa.app_key = key; + conn.connection_u.otaa.app_eui = key; + conn.connection_u.otaa.dev_eui = NULL; + conn.connection_u.otaa.nb_trials = 0; + EXPECT_EQ(LORAWAN_STATUS_PARAMETER_INVALID, object->prepare_join(&conn, true)); + + conn.connection_u.otaa.app_key = key; + conn.connection_u.otaa.app_eui = key; + conn.connection_u.otaa.dev_eui = key; + conn.connection_u.otaa.nb_trials = 0; + EXPECT_EQ(LORAWAN_STATUS_PARAMETER_INVALID, object->prepare_join(&conn, true)); + + LoRaPHY_stub::bool_table[0] = false; + LoRaPHY_stub::bool_counter = 0; + conn.connection_u.otaa.app_key = key; + conn.connection_u.otaa.app_eui = key; + conn.connection_u.otaa.dev_eui = key; + conn.connection_u.otaa.nb_trials = 2; + EXPECT_EQ(LORAWAN_STATUS_OK, object->prepare_join(&conn, true)); + + conn.connection_u.abp.dev_addr = 0; + conn.connection_u.abp.nwk_id = 0; + conn.connection_u.abp.nwk_skey = NULL; + conn.connection_u.abp.app_skey = NULL; + EXPECT_EQ(LORAWAN_STATUS_PARAMETER_INVALID, object->prepare_join(&conn, false)); + + conn.connection_u.abp.dev_addr = 1; + conn.connection_u.abp.nwk_id = 0; + conn.connection_u.abp.nwk_skey = NULL; + conn.connection_u.abp.app_skey = NULL; + EXPECT_EQ(LORAWAN_STATUS_PARAMETER_INVALID, object->prepare_join(&conn, false)); + + conn.connection_u.abp.dev_addr = 1; + conn.connection_u.abp.nwk_id = 2; + conn.connection_u.abp.nwk_skey = NULL; + conn.connection_u.abp.app_skey = NULL; + EXPECT_EQ(LORAWAN_STATUS_PARAMETER_INVALID, object->prepare_join(&conn, false)); + + conn.connection_u.abp.dev_addr = 1; + conn.connection_u.abp.nwk_id = 2; + conn.connection_u.abp.nwk_skey = key; + conn.connection_u.abp.app_skey = NULL; + EXPECT_EQ(LORAWAN_STATUS_PARAMETER_INVALID, object->prepare_join(&conn, false)); + + conn.connection_u.abp.dev_addr = 1; + conn.connection_u.abp.nwk_id = 2; + conn.connection_u.abp.nwk_skey = key; + conn.connection_u.abp.app_skey = key; + EXPECT_EQ(LORAWAN_STATUS_OK, object->prepare_join(&conn, false)); + + EXPECT_EQ(LORAWAN_STATUS_OK, object->prepare_join(NULL, false)); +} + +TEST_F(Test_LoRaMac, join) +{ + my_phy phy; + object->bind_phy(phy); + EXPECT_EQ(LORAWAN_STATUS_OK, object->join(false)); + + lorawan_connect_t conn; + memset(&conn, 0, sizeof(conn)); + uint8_t key[16]; + memset(key, 0, sizeof(key)); + conn.connection_u.otaa.app_key = key; + conn.connection_u.otaa.app_eui = key; + conn.connection_u.otaa.dev_eui = key; + conn.connection_u.otaa.nb_trials = 2; + object->prepare_join(&conn, true); + EXPECT_EQ(LORAWAN_STATUS_CONNECT_IN_PROGRESS, object->join(true)); +} + +TEST_F(Test_LoRaMac, on_radio_tx_done) +{ + my_phy phy; + object->bind_phy(phy); + object->on_radio_tx_done(100); +} + +TEST_F(Test_LoRaMac, on_radio_rx_done) +{ + uint8_t buf[16]; + memset(buf, 0, sizeof(buf)); + object->on_radio_rx_done(buf, 16, 0, 0); +} + +TEST_F(Test_LoRaMac, on_radio_tx_timeout) +{ + object->on_radio_tx_timeout(); +} + +TEST_F(Test_LoRaMac, on_radio_rx_timeout) +{ + object->on_radio_rx_timeout(true); +} + +TEST_F(Test_LoRaMac, continue_joining_process) +{ + my_phy phy; + object->bind_phy(phy); + lorawan_connect_t conn; + memset(&conn, 0, sizeof(conn)); + uint8_t key[16]; + memset(key, 0, sizeof(key)); + conn.connection_u.otaa.app_key = key; + conn.connection_u.otaa.app_eui = key; + conn.connection_u.otaa.dev_eui = key; + conn.connection_u.otaa.nb_trials = 2; + object->prepare_join(&conn, true); + object->continue_joining_process(); +} + +TEST_F(Test_LoRaMac, continue_sending_process) +{ + my_phy phy; + object->bind_phy(phy); + object->continue_sending_process(); +} + +TEST_F(Test_LoRaMac, get_mcps_confirmation) +{ + object->get_mcps_confirmation(); +} + +TEST_F(Test_LoRaMac, get_mcps_indication) +{ + object->get_mcps_indication(); +} + +TEST_F(Test_LoRaMac, get_mlme_confirmation) +{ + object->get_mlme_confirmation(); +} + +TEST_F(Test_LoRaMac, get_mlme_indication) +{ + object->get_mlme_indication(); +} + +TEST_F(Test_LoRaMac, post_process_mcps_req) +{ + uint8_t data[16]; + memset(data, 0, sizeof(data)); + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + + my_phy phy; + object->bind_phy(phy); + object->join(false); + + object->prepare_ongoing_tx(1, data, 15, 0x01, 2); + object->send_ongoing_tx(); + object->post_process_mcps_req(); + + LoRaPHY_stub::bool_counter = 0; + object->prepare_ongoing_tx(1, data, 15, 0x02, 2); + object->send_ongoing_tx(); + object->post_process_mcps_req(); + + //_mcps_confirmation.ack_received missing here + uint8_t payload[16] = {}; + LoRaPHY_stub::uint16_value = 5; + payload[0] = FRAME_TYPE_DATA_CONFIRMED_DOWN << 5; + payload[5] = 1 << 5; + + //address != _params.dev_addr + payload[2] = 2; + object->on_radio_rx_done(payload, 16, 0, 0); + object->post_process_mcps_req(); + + payload[2] = 0; + //mic failure + payload[13] = 2; + object->on_radio_rx_done(payload, 16, 0, 0); + object->post_process_mcps_req(); + + payload[13] = 0; + //crypto failure + LoRaMacCrypto_stub::int_table_idx_value = 0; + LoRaMacCrypto_stub::int_table[0] = 4; + LoRaMacCrypto_stub::int_table[1] = 4; +// LoRaPHY_stub::uint16_value = 0; + object->on_radio_rx_done(payload, 16, 0, 0); + object->post_process_mcps_req(); + + //process_mac_commands failure + LoRaMacCommand_stub::status_value = LORAWAN_STATUS_BUSY; + LoRaMacCrypto_stub::int_table[0] = 0; + LoRaMacCrypto_stub::int_table[1] = 0; + payload[7] = 1; + object->on_radio_rx_done(payload, 16, 0, 0); + object->post_process_mcps_req(); + + //FOpts_len != 0 + payload[5] = (1 << 5) + 1; + payload[7] = 0; + LoRaMacCommand_stub::status_value = LORAWAN_STATUS_OK; + payload[0] = FRAME_TYPE_DATA_UNCONFIRMED_DOWN << 5; + + object->on_radio_rx_done(payload, 13, 0, 0); + + //_mac_commands.process_mac_commands fails + LoRaMacCommand_stub::status_value = LORAWAN_STATUS_DATARATE_INVALID; + object->on_radio_rx_done(payload, 13, 0, 0); + + object->post_process_mcps_req(); + + payload[9] = 1; + LoRaMacCommand_stub::status_value = LORAWAN_STATUS_OK; + payload[0] = FRAME_TYPE_PROPRIETARY << 5; + object->on_radio_rx_done(payload, 16, 0, 0); + object->post_process_mcps_req(); + + payload[9] = 0; + payload[5] = 1 << 5; + LoRaMacCommand_stub::status_value = LORAWAN_STATUS_OK; + object->on_radio_rx_done(payload, 16, 0, 0); + object->post_process_mcps_req(); + + LoRaPHY_stub::bool_counter = 0; + object->prepare_ongoing_tx(1, data, 15, 0x04, 2); + object->send_ongoing_tx(); + object->post_process_mcps_req(); + + LoRaPHY_stub::bool_counter = 0; + object->prepare_ongoing_tx(1, data, 15, 0x08, 2); + object->send_ongoing_tx(); + object->post_process_mcps_req(); +} + +TEST_F(Test_LoRaMac, handle_join_accept_frame) +{ + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + + my_phy phy; + object->bind_phy(phy); + + uint8_t payload[16] = {}; + LoRaPHY_stub::uint16_value = 5; + payload[0] = FRAME_TYPE_JOIN_ACCEPT << 5; + payload[5] = 1 << 5; + + LoRaMacCrypto_stub::int_table_idx_value = 0; + LoRaMacCrypto_stub::int_table[0] = 4; + LoRaMacCrypto_stub::int_table[1] = 4; + LoRaMacCrypto_stub::int_table[2] = 4; + LoRaMacCrypto_stub::int_table[3] = 4; + object->on_radio_rx_done(payload, 16, 0, 0); + + LoRaMacCrypto_stub::int_table_idx_value = 0; + LoRaMacCrypto_stub::int_table[0] = 0; + object->on_radio_rx_done(payload, 16, 0, 0); + + LoRaMacCrypto_stub::int_table_idx_value = 0; + LoRaMacCrypto_stub::int_table[1] = 0; + object->on_radio_rx_done(payload, 16, 0, 0); + + //mic failure case + payload[13] = 17; + LoRaMacCrypto_stub::int_table_idx_value = 0; + object->on_radio_rx_done(payload, 16, 0, 0); + + payload[13] = 0; + LoRaMacCrypto_stub::int_table_idx_value = 0; + LoRaMacCrypto_stub::int_table[2] = 0; + object->on_radio_rx_done(payload, 16, 0, 0); +} + +TEST_F(Test_LoRaMac, post_process_mcps_ind) +{ + object->post_process_mcps_ind(); +} + +TEST_F(Test_LoRaMac, post_process_mlme_request) +{ + object->post_process_mlme_request(); +} + +TEST_F(Test_LoRaMac, post_process_mlme_ind) +{ + object->post_process_mlme_ind(); +} + +uint8_t batt_cb() +{ + +} + +TEST_F(Test_LoRaMac, set_batterylevel_callback) +{ + object->set_batterylevel_callback(batt_cb); +} + +TEST_F(Test_LoRaMac, get_backoff_timer_event_id) +{ + object->get_backoff_timer_event_id(); +} + +TEST_F(Test_LoRaMac, clear_tx_pipe) +{ + EXPECT_EQ(LORAWAN_STATUS_NO_OP, object->clear_tx_pipe()); //timer id == 0 + + my_phy phy; + object->bind_phy(phy); + + lorawan_connect_t conn; + memset(&conn, 0, sizeof(conn)); + uint8_t key[16]; + memset(key, 0, sizeof(key)); + conn.connection_u.otaa.app_key = key; + conn.connection_u.otaa.app_eui = key; + conn.connection_u.otaa.dev_eui = key; + conn.connection_u.otaa.nb_trials = 2; + object->prepare_join(&conn, true); + + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize(NULL, my_cb)); + EventQueue_stub::int_value = 0; + EXPECT_EQ(LORAWAN_STATUS_BUSY, object->clear_tx_pipe()); + loramac_mhdr_t machdr; + machdr.bits.mtype = MCPS_UNCONFIRMED; + uint8_t buf[1]; + buf[0] = 'T'; + LoRaPHY_stub::lorawan_status_value = LORAWAN_STATUS_DUTYCYCLE_RESTRICTED; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->send(&machdr, 15, buf, 1)); + + EventQueue_stub::int_value = 1; + EXPECT_EQ(LORAWAN_STATUS_OK, object->clear_tx_pipe()); +} + +TEST_F(Test_LoRaMac, get_current_time) +{ + object->get_current_time(); +} + +TEST_F(Test_LoRaMac, get_current_slot) +{ + object->get_current_slot(); +} + +TEST_F(Test_LoRaMac, get_QOS_level) +{ + EXPECT_EQ(0, object->get_QOS_level()); +} + +TEST_F(Test_LoRaMac, get_prev_QOS_level) +{ + EXPECT_EQ(1, object->get_prev_QOS_level()); +} diff --git a/UNITTESTS/features/lorawan/loramac/unittest.cmake b/UNITTESTS/features/lorawan/loramac/unittest.cmake new file mode 100644 index 0000000000..aff97c0412 --- /dev/null +++ b/UNITTESTS/features/lorawan/loramac/unittest.cmake @@ -0,0 +1,58 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaMac") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/mac/LoRaMac.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/mac +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loramac/Test_LoRaMac.cpp + stubs/LoRaPHY_stub.cpp + stubs/LoRaWANStack_stub.cpp + stubs/mbed_assert_stub.c + stubs/LoRaMacCrypto_stub.cpp + stubs/LoRaMacChannelPlan_stub.cpp + stubs/LoRaWANTimer_stub.cpp + stubs/LoRaMacCommand_stub.cpp + stubs/EventQueue_stub.cpp + +) + +# defines +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_ADR_ON=true -DMBED_CONF_LORA_PUBLIC_NETWORK=true -DMBED_CONF_LORA_NB_TRIALS=2 -DMBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_ADR_ON=true -DMBED_CONF_LORA_PUBLIC_NETWORK=true -DMBED_CONF_LORA_NB_TRIALS=2 -DMBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH=5") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_DUTY_CYCLE_ON=true -DMBED_CONF_LORA_MAX_SYS_RX_ERROR=10 -DMBED_CONF_LORA_NWKSKEY=\"{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}\"") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_DUTY_CYCLE_ON=true -DMBED_CONF_LORA_MAX_SYS_RX_ERROR=10 -DMBED_CONF_LORA_NWKSKEY=\"{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}\"") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_APPSKEY=\"{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}\"") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_APPSKEY=\"{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}\"") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_DEVICE_ADDRESS=\"0x00000000\"") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_DEVICE_ADDRESS=\"0x00000000\"") + diff --git a/UNITTESTS/features/lorawan/loramacchannelplan/Test_LoRaMacChannelPlan.cpp b/UNITTESTS/features/lorawan/loramacchannelplan/Test_LoRaMacChannelPlan.cpp new file mode 100644 index 0000000000..7150ec14b4 --- /dev/null +++ b/UNITTESTS/features/lorawan/loramacchannelplan/Test_LoRaMacChannelPlan.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaMacChannelPlan.h" +#include "LoRaPHY_stub.h" +#include "LoRaPHY.h" + +class my_LoRaPHY : public LoRaPHY { +public: + my_LoRaPHY() + { + }; + + virtual ~my_LoRaPHY() + { + }; +}; + + +class Test_LoRaMacChannelPlan : public testing::Test { +protected: + LoRaMacChannelPlan *object; + my_LoRaPHY phy; + + virtual void SetUp() + { + object = new LoRaMacChannelPlan(); + object->activate_channelplan_subsystem(&phy); + + LoRaPHY_stub::uint8_value = 0; + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::lorawan_status_value = LORAWAN_STATUS_OK; + LoRaPHY_stub::uint16_value = 0; + memcpy(LoRaPHY_stub::bool_table, "0", 20); + } + + virtual void TearDown() + { + delete object; + } +}; + +TEST_F(Test_LoRaMacChannelPlan, constructor) +{ + EXPECT_TRUE(object); +} + +TEST_F(Test_LoRaMacChannelPlan, set_plan) +{ + lorawan_channelplan_t plan; + memset(&plan, 0, sizeof(plan)); + memset(&LoRaPHY_stub::bool_table, 0, sizeof(LoRaPHY_stub::bool_table)); + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = false; + EXPECT_TRUE(object->set_plan(plan) == LORAWAN_STATUS_SERVICE_UNKNOWN); + + plan.nb_channels = 1; + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + LoRaPHY_stub::uint8_value = 0; + EXPECT_TRUE(object->set_plan(plan) == LORAWAN_STATUS_PARAMETER_INVALID); + + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + LoRaPHY_stub::uint8_value = 10; + LoRaPHY_stub::lorawan_status_value = LORAWAN_STATUS_PARAMETER_INVALID; + loramac_channel_t chan; + memset(&chan, 0, sizeof(chan)); + plan.channels = &chan; + EXPECT_TRUE(object->set_plan(plan) == LORAWAN_STATUS_PARAMETER_INVALID); + + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + plan.nb_channels = 2; + LoRaPHY_stub::lorawan_status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(object->set_plan(plan) == LORAWAN_STATUS_OK); +} + +TEST_F(Test_LoRaMacChannelPlan, get_plan) +{ + lorawan_channelplan_t plan; + channel_params_t params; + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = false; + EXPECT_TRUE(object->get_plan(plan, ¶ms) == LORAWAN_STATUS_SERVICE_UNKNOWN); + + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + LoRaPHY_stub::bool_table[1] = false; + + LoRaPHY_stub::uint8_value = 1; + LoRaPHY_stub::uint16_value = 0xABCD; + EXPECT_TRUE(object->get_plan(plan, ¶ms) == LORAWAN_STATUS_OK); + + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + LoRaPHY_stub::bool_table[1] = true; + LoRaPHY_stub::bool_table[2] = false; + loramac_channel_t ch; + plan.channels = &ch; + EXPECT_TRUE(object->get_plan(plan, ¶ms) == LORAWAN_STATUS_OK); +} + +TEST_F(Test_LoRaMacChannelPlan, remove_plan) +{ + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = false; + EXPECT_TRUE(object->remove_plan() == LORAWAN_STATUS_SERVICE_UNKNOWN); + + LoRaPHY_stub::uint8_value = 4; + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + LoRaPHY_stub::bool_table[1] = true; //first continue + LoRaPHY_stub::bool_table[2] = false; + LoRaPHY_stub::bool_table[3] = false;//second continue + LoRaPHY_stub::bool_table[4] = false; + LoRaPHY_stub::bool_table[5] = true; + LoRaPHY_stub::bool_table[6] = false;//false for remove_single_channel(i) + + EXPECT_TRUE(object->remove_plan() == LORAWAN_STATUS_SERVICE_UNKNOWN); + + LoRaPHY_stub::uint8_value = 3; + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + LoRaPHY_stub::bool_table[1] = false; + LoRaPHY_stub::bool_table[2] = true; + LoRaPHY_stub::bool_table[3] = true; + LoRaPHY_stub::bool_table[4] = true; + LoRaPHY_stub::bool_table[5] = true; + LoRaPHY_stub::bool_table[7] = true; + LoRaPHY_stub::bool_table[8] = true; + LoRaPHY_stub::bool_table[9] = true; + LoRaPHY_stub::bool_table[10] = true; + + EXPECT_TRUE(object->remove_plan() == LORAWAN_STATUS_OK); + +} + +TEST_F(Test_LoRaMacChannelPlan, remove_single_channel) +{ + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = false; + EXPECT_TRUE(object->remove_single_channel(4) == LORAWAN_STATUS_SERVICE_UNKNOWN); + + LoRaPHY_stub::uint8_value = 2; + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + + EXPECT_TRUE(object->remove_single_channel(4) == LORAWAN_STATUS_PARAMETER_INVALID); + + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + LoRaPHY_stub::bool_table[1] = false; + EXPECT_TRUE(object->remove_single_channel(1) == LORAWAN_STATUS_PARAMETER_INVALID); + + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + LoRaPHY_stub::bool_table[1] = true; + EXPECT_TRUE(object->remove_single_channel(1) == LORAWAN_STATUS_OK); +} + diff --git a/UNITTESTS/features/lorawan/loramacchannelplan/unittest.cmake b/UNITTESTS/features/lorawan/loramacchannelplan/unittest.cmake new file mode 100644 index 0000000000..1f15bf09ed --- /dev/null +++ b/UNITTESTS/features/lorawan/loramacchannelplan/unittest.cmake @@ -0,0 +1,39 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaMacChannelPlan") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/mac/LoRaMacChannelPlan.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/mac +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loramacchannelplan/Test_LoRaMacChannelPlan.cpp + stubs/LoRaPHY_stub.cpp +) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_TX_MAX_SIZE=255") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_TX_MAX_SIZE=255") diff --git a/UNITTESTS/features/lorawan/loramaccommand/Test_LoRaMacCommand.cpp b/UNITTESTS/features/lorawan/loramaccommand/Test_LoRaMacCommand.cpp new file mode 100644 index 0000000000..591288d4a8 --- /dev/null +++ b/UNITTESTS/features/lorawan/loramaccommand/Test_LoRaMacCommand.cpp @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaMacCommand.h" + +#include "LoRaPHY_stub.h" + +class my_LoRaPHY : public LoRaPHY { +public: + my_LoRaPHY() + { + }; + + virtual ~my_LoRaPHY() + { + }; +}; + +uint8_t my_cb() +{ + return 1; +} + +class Test_LoRaMacCommand : public testing::Test { +protected: + LoRaMacCommand *object; + + virtual void SetUp() + { + object = new LoRaMacCommand(); + } + + virtual void TearDown() + { + delete object; + } +}; + +TEST_F(Test_LoRaMacCommand, constructor) +{ + EXPECT_TRUE(object); +} + +TEST_F(Test_LoRaMacCommand, get_mac_cmd_length) +{ + object->add_link_check_req(); + EXPECT_TRUE(object->get_mac_cmd_length() == 1); + object->clear_command_buffer(); + EXPECT_TRUE(object->get_mac_cmd_length() == 0); +} + +TEST_F(Test_LoRaMacCommand, parse_mac_commands_to_repeat) +{ + loramac_mlme_confirm_t mlme; + lora_mac_system_params_t params; + my_LoRaPHY phy; + uint8_t buf[20]; + + object->parse_mac_commands_to_repeat(); + + buf[0] = 2; + buf[1] = 16; + buf[2] = 32; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 3, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + buf[0] = 3; + LoRaPHY_stub::uint8_value = 7; + LoRaPHY_stub::linkAdrNbBytesParsed = 5; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 5, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + buf[0] = 4; + buf[1] = 2; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 1, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + buf[0] = 5; + buf[1] = 2; + buf[2] = 2; + buf[3] = 2; + buf[4] = 2; + buf[5] = 2; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 5, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + buf[0] = 6; + object->set_batterylevel_callback(my_cb); + EXPECT_TRUE(object->process_mac_commands(buf, 0, 1, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + buf[0] = 7; + buf[1] = 2; + buf[2] = 2; + buf[3] = 2; + buf[4] = 2; + buf[5] = 2; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 6, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + buf[0] = 8; + buf[1] = 0; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 2, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + buf[0] = 9; + buf[1] = 48; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 2, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + buf[0] = 10; + buf[1] = 2; + buf[1] = 3; + buf[1] = 4; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 4, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + object->parse_mac_commands_to_repeat(); +} + +TEST_F(Test_LoRaMacCommand, clear_repeat_buffer) +{ + object->clear_repeat_buffer(); +} + +TEST_F(Test_LoRaMacCommand, copy_repeat_commands_to_buffer) +{ + loramac_mlme_confirm_t mlme; + lora_mac_system_params_t params; + my_LoRaPHY phy; + uint8_t buf[20]; + + object->clear_command_buffer(); + buf[0] = 5; + buf[1] = 2; + buf[2] = 2; + buf[3] = 2; + buf[4] = 2; + buf[5] = 2; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 5, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + object->parse_mac_commands_to_repeat(); + + object->clear_command_buffer(); + EXPECT_TRUE(object->get_mac_cmd_length() == 0); + + object->copy_repeat_commands_to_buffer(); + + EXPECT_TRUE(object->get_mac_cmd_length() != 0); +} + +TEST_F(Test_LoRaMacCommand, get_repeat_commands_length) +{ + EXPECT_TRUE(object->get_repeat_commands_length() == 0); +} + +TEST_F(Test_LoRaMacCommand, clear_sticky_mac_cmd) +{ + loramac_mlme_confirm_t mlme; + lora_mac_system_params_t params; + my_LoRaPHY phy; + uint8_t buf[20]; + + EXPECT_TRUE(object->has_sticky_mac_cmd() == false); + + object->clear_command_buffer(); + buf[0] = 5; + buf[1] = 2; + buf[2] = 2; + buf[3] = 2; + buf[4] = 2; + buf[5] = 2; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 5, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + EXPECT_TRUE(object->has_sticky_mac_cmd() == true); + + object->clear_sticky_mac_cmd(); + EXPECT_TRUE(object->has_sticky_mac_cmd() == false); +} + +TEST_F(Test_LoRaMacCommand, has_sticky_mac_cmd) +{ + loramac_mlme_confirm_t mlme; + lora_mac_system_params_t params; + my_LoRaPHY phy; + uint8_t buf[20]; + + EXPECT_TRUE(object->has_sticky_mac_cmd() == false); + + object->clear_command_buffer(); + buf[0] = 5; + buf[1] = 2; + buf[2] = 2; + buf[3] = 2; + buf[4] = 2; + buf[5] = 2; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 5, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + EXPECT_TRUE(object->has_sticky_mac_cmd() == true); +} + +TEST_F(Test_LoRaMacCommand, process_mac_commands) +{ + loramac_mlme_confirm_t mlme; + lora_mac_system_params_t params; + my_LoRaPHY phy; + uint8_t buf[20]; + EXPECT_TRUE(object->process_mac_commands(NULL, 0, 0, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + buf[0] = 2; + buf[1] = 16; + buf[2] = 32; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 3, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + buf[0] = 3; + LoRaPHY_stub::uint8_value = 7; + LoRaPHY_stub::linkAdrNbBytesParsed = 5; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 5, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + //Overflow add_link_adr_ans function here + object->clear_command_buffer(); + buf[0] = 3; + for (int i = 0; i < 64; i++) { + EXPECT_TRUE(object->process_mac_commands(buf, 0, 5, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + } + EXPECT_TRUE(object->process_mac_commands(buf, 0, 5, 0, mlme, params, phy) == LORAWAN_STATUS_LENGTH_ERROR); + + object->clear_command_buffer(); + buf[0] = 4; + buf[1] = 2; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 1, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + //Overflow add_duty_cycle_ans() + object->clear_command_buffer(); + for (int i = 0; i < 128; i++) { + EXPECT_TRUE(object->process_mac_commands(buf, 0, 1, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + } + EXPECT_TRUE(object->process_mac_commands(buf, 0, 1, 0, mlme, params, phy) == LORAWAN_STATUS_LENGTH_ERROR); + + object->clear_command_buffer(); + buf[0] = 5; + buf[1] = 2; + buf[2] = 2; + buf[3] = 2; + buf[4] = 2; + buf[5] = 2; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 5, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + //Overflow add_rx_param_setup_ans + object->clear_command_buffer(); + LoRaPHY_stub::uint8_value = 7; + for (int i = 0; i < 64; i++) { + EXPECT_TRUE(object->process_mac_commands(buf, 0, 5, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + } + EXPECT_TRUE(object->process_mac_commands(buf, 0, 5, 0, mlme, params, phy) == LORAWAN_STATUS_LENGTH_ERROR); + + object->clear_command_buffer(); + buf[0] = 6; + object->set_batterylevel_callback(my_cb); + EXPECT_TRUE(object->process_mac_commands(buf, 0, 1, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + //overflow add_dev_status_ans + object->clear_command_buffer(); + for (int i = 0; i < 42; i++) { + EXPECT_TRUE(object->process_mac_commands(buf, 0, 1, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + } + EXPECT_TRUE(object->process_mac_commands(buf, 0, 1, 0, mlme, params, phy) == LORAWAN_STATUS_LENGTH_ERROR); + + object->clear_command_buffer(); + buf[0] = 7; + buf[1] = 2; + buf[2] = 2; + buf[3] = 2; + buf[4] = 2; + buf[5] = 2; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 6, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + //Overflow add_new_channel_ans + object->clear_command_buffer(); + LoRaPHY_stub::uint8_value = 7; + for (int i = 0; i < 64; i++) { + EXPECT_TRUE(object->process_mac_commands(buf, 0, 6, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + } + EXPECT_TRUE(object->process_mac_commands(buf, 0, 6, 0, mlme, params, phy) == LORAWAN_STATUS_LENGTH_ERROR); + + object->clear_command_buffer(); + buf[0] = 8; + buf[1] = 0; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 2, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + //Overflow add_rx_timing_setup_ans + object->clear_command_buffer(); + LoRaPHY_stub::uint8_value = 7; + for (int i = 0; i < 128; i++) { + EXPECT_TRUE(object->process_mac_commands(buf, 0, 2, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + } + EXPECT_TRUE(object->process_mac_commands(buf, 0, 2, 0, mlme, params, phy) == LORAWAN_STATUS_LENGTH_ERROR); + + object->clear_command_buffer(); + buf[0] = 9; + buf[1] = 48; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 2, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + //Overflow add_tx_param_setup_ans + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + object->clear_command_buffer(); + LoRaPHY_stub::uint8_value = 7; + for (int i = 0; i < 128; i++) { + EXPECT_TRUE(object->process_mac_commands(buf, 0, 2, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + LoRaPHY_stub::bool_counter = 0; + } + EXPECT_TRUE(object->process_mac_commands(buf, 0, 2, 0, mlme, params, phy) == LORAWAN_STATUS_LENGTH_ERROR); + + object->clear_command_buffer(); + buf[0] = 10; + buf[1] = 2; + buf[1] = 3; + buf[1] = 4; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 4, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + + //Overflow add_tx_param_setup_ans + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + object->clear_command_buffer(); + LoRaPHY_stub::uint8_value = 7; + for (int i = 0; i < 64; i++) { + EXPECT_TRUE(object->process_mac_commands(buf, 0, 4, 0, mlme, params, phy) == LORAWAN_STATUS_OK); + LoRaPHY_stub::bool_counter = 0; + } + EXPECT_TRUE(object->process_mac_commands(buf, 0, 4, 0, mlme, params, phy) == LORAWAN_STATUS_LENGTH_ERROR); + + object->clear_command_buffer(); + buf[0] = 80; + EXPECT_TRUE(object->process_mac_commands(buf, 0, 1, 0, mlme, params, phy) == LORAWAN_STATUS_UNSUPPORTED); +} + +TEST_F(Test_LoRaMacCommand, add_link_check_req) +{ + object->add_link_check_req(); + EXPECT_TRUE(object->get_mac_commands_buffer()[0] == 2); + EXPECT_TRUE(object->get_mac_cmd_length() == 1); + object->clear_command_buffer(); + EXPECT_TRUE(object->get_mac_cmd_length() == 0); +} + +TEST_F(Test_LoRaMacCommand, set_batterylevel_callback) +{ + object->set_batterylevel_callback(my_cb); +} + diff --git a/UNITTESTS/features/lorawan/loramaccommand/unittest.cmake b/UNITTESTS/features/lorawan/loramaccommand/unittest.cmake new file mode 100644 index 0000000000..1dc3272977 --- /dev/null +++ b/UNITTESTS/features/lorawan/loramaccommand/unittest.cmake @@ -0,0 +1,38 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaMacCommand") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/mac/LoRaMacCommand.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/mac +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loramaccommand/Test_LoRaMacCommand.cpp + stubs/mbed_assert_stub.c + stubs/LoRaPHY_stub.cpp +) + diff --git a/UNITTESTS/features/lorawan/loramaccrypto/Test_LoRaMacCrypto.cpp b/UNITTESTS/features/lorawan/loramaccrypto/Test_LoRaMacCrypto.cpp new file mode 100644 index 0000000000..1c00938238 --- /dev/null +++ b/UNITTESTS/features/lorawan/loramaccrypto/Test_LoRaMacCrypto.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaMacCrypto.h" + +#include "cipher_stub.h" +#include "cmac_stub.h" +#include "aes_stub.h" + +class Test_LoRaMacCrypto : public testing::Test { +protected: + LoRaMacCrypto *object; + + virtual void SetUp() + { + cipher_stub.info_value = NULL; + cipher_stub.int_zero_counter = 0; + cipher_stub.int_value = 0; + cmac_stub.int_zero_counter = 0; + cmac_stub.int_value = 0; + aes_stub.int_zero_counter = 0; + aes_stub.int_value = 0; + object = new LoRaMacCrypto(); + } + + virtual void TearDown() + { + delete object; + } +}; + +TEST_F(Test_LoRaMacCrypto, constructor) +{ + EXPECT_TRUE(object); + LoRaMacCrypto obj; +} + +TEST_F(Test_LoRaMacCrypto, compute_mic) +{ + EXPECT_TRUE(MBEDTLS_ERR_CIPHER_ALLOC_FAILED == object->compute_mic(NULL, 0, NULL, 0, 0, 0, 0, NULL)); + + mbedtls_cipher_info_t info; + cipher_stub.info_value = &info; + cipher_stub.int_zero_counter = 0; + cipher_stub.int_value = -1; + EXPECT_TRUE(-1 == object->compute_mic(NULL, 0, NULL, 0, 0, 0, 0, NULL)); + + cipher_stub.int_value = 0; + cmac_stub.int_zero_counter = 0; + cmac_stub.int_value = -1; + EXPECT_TRUE(-1 == object->compute_mic(NULL, 0, NULL, 0, 0, 0, 0, NULL)); + + cmac_stub.int_zero_counter = 1; + cmac_stub.int_value = -1; + EXPECT_TRUE(-1 == object->compute_mic(NULL, 0, NULL, 0, 0, 0, 0, NULL)); + + cmac_stub.int_zero_counter = 2; + cmac_stub.int_value = -1; + EXPECT_TRUE(-1 == object->compute_mic(NULL, 0, NULL, 0, 0, 0, 0, NULL)); + + cmac_stub.int_zero_counter = 3; + cmac_stub.int_value = -1; + EXPECT_TRUE(-1 == object->compute_mic(NULL, 0, NULL, 0, 0, 0, 0, NULL)); + + uint32_t mic[16]; + cmac_stub.int_zero_counter = 3; + cmac_stub.int_value = 0; + EXPECT_TRUE(0 == object->compute_mic(NULL, 0, NULL, 0, 0, 0, 0, mic)); + +} + +TEST_F(Test_LoRaMacCrypto, encrypt_payload) +{ + aes_stub.int_zero_counter = 0; + aes_stub.int_value = -1; + EXPECT_TRUE(-1 == object->encrypt_payload(NULL, 0, NULL, 0, 0, 0, 0, NULL)); + + aes_stub.int_zero_counter = 1; + aes_stub.int_value = -2; + uint8_t buf[60]; + uint8_t enc[60]; + EXPECT_TRUE(-2 == object->encrypt_payload(buf, 20, NULL, 0, 0, 0, 0, enc)); + + aes_stub.int_zero_counter = 2; + aes_stub.int_value = -3; + EXPECT_TRUE(-3 == object->encrypt_payload(buf, 20, NULL, 0, 0, 0, 0, enc)); + + aes_stub.int_value = 0; + EXPECT_TRUE(0 == object->encrypt_payload(buf, 20, NULL, 0, 0, 0, 0, enc)); + + EXPECT_TRUE(0 == object->encrypt_payload(buf, 60, NULL, 0, 0, 0, 0, enc)); + + aes_stub.int_zero_counter = 0; + EXPECT_TRUE(0 == object->encrypt_payload(NULL, 0, NULL, 0, 0, 0, 0, NULL)); +} + +TEST_F(Test_LoRaMacCrypto, decrypt_payload) +{ + EXPECT_TRUE(0 == object->decrypt_payload(NULL, 0, NULL, 0, 0, 0, 0, NULL)); +} + +TEST_F(Test_LoRaMacCrypto, compute_join_frame_mic) +{ + uint32_t mic[16]; + EXPECT_TRUE(MBEDTLS_ERR_CIPHER_ALLOC_FAILED == object->compute_join_frame_mic(NULL, 0, NULL, 0, NULL)); + mbedtls_cipher_info_t info; + cipher_stub.info_value = &info; + cipher_stub.int_zero_counter = 0; + cipher_stub.int_value = -1; + EXPECT_TRUE(-1 == object->compute_join_frame_mic(NULL, 0, NULL, 0, NULL)); + + cipher_stub.int_value = 0; + cmac_stub.int_zero_counter = 0; + cmac_stub.int_value = -1; + EXPECT_TRUE(-1 == object->compute_join_frame_mic(NULL, 0, NULL, 0, NULL)); + + cmac_stub.int_zero_counter = 1; + cmac_stub.int_value = -1; + EXPECT_TRUE(-1 == object->compute_join_frame_mic(NULL, 0, NULL, 0, NULL)); + + cmac_stub.int_zero_counter = 2; + cmac_stub.int_value = -1; + EXPECT_TRUE(-1 == object->compute_join_frame_mic(NULL, 0, NULL, 0, NULL)); + + cmac_stub.int_zero_counter = 3; + cmac_stub.int_value = 0; + EXPECT_TRUE(0 == object->compute_join_frame_mic(NULL, 0, NULL, 0, mic)); +} + +TEST_F(Test_LoRaMacCrypto, decrypt_join_frame) +{ + aes_stub.int_zero_counter = 0; + aes_stub.int_value = -1; + EXPECT_TRUE(-1 == object->decrypt_join_frame(NULL, 0, NULL, 0, NULL)); + + aes_stub.int_zero_counter = 1; + aes_stub.int_value = -1; + EXPECT_TRUE(-1 == object->decrypt_join_frame(NULL, 0, NULL, 0, NULL)); + + aes_stub.int_value = 0; + uint8_t buf[60]; + uint8_t enc[60]; + EXPECT_TRUE(0 == object->decrypt_join_frame(buf, 60, NULL, 0, enc)); +} + +TEST_F(Test_LoRaMacCrypto, compute_skeys_for_join_frame) +{ + uint8_t nwk_key[16]; + uint8_t app_key[16]; + uint8_t nonce[16]; + + aes_stub.int_zero_counter = 0; + aes_stub.int_value = -1; + EXPECT_TRUE(-1 == object->compute_skeys_for_join_frame(NULL, 0, nonce, 0, nwk_key, app_key)); + + aes_stub.int_zero_counter = 1; + aes_stub.int_value = -2; + EXPECT_TRUE(-2 == object->compute_skeys_for_join_frame(NULL, 0, nonce, 0, nwk_key, app_key)); + + aes_stub.int_zero_counter = 0; + aes_stub.int_value = 0; + EXPECT_TRUE(0 == object->compute_skeys_for_join_frame(NULL, 0, nonce, 0, nwk_key, app_key)); +} diff --git a/UNITTESTS/features/lorawan/loramaccrypto/unittest.cmake b/UNITTESTS/features/lorawan/loramaccrypto/unittest.cmake new file mode 100644 index 0000000000..e41d668906 --- /dev/null +++ b/UNITTESTS/features/lorawan/loramaccrypto/unittest.cmake @@ -0,0 +1,40 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaMacCrypto") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/mac/LoRaMacCrypto.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/mac +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loramaccrypto/Test_LoRaMacCrypto.cpp + stubs/cipher_stub.c + stubs/aes_stub.c + stubs/cmac_stub.c + +) + diff --git a/UNITTESTS/features/lorawan/loraphy/Test_LoRaPHY.cpp b/UNITTESTS/features/lorawan/loraphy/Test_LoRaPHY.cpp new file mode 100644 index 0000000000..6220649ec5 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphy/Test_LoRaPHY.cpp @@ -0,0 +1,944 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaPHY.h" + +#include "LoRaWANTimer_stub.h" + +class my_LoRaPHY : public LoRaPHY { +public: + my_LoRaPHY() + { + phy_params.adr_ack_delay = 1; + } + + virtual ~my_LoRaPHY() + { + } + + loraphy_params_t &get_phy_params() + { + return phy_params; + } +}; + +class my_radio : public LoRaRadio { +public: + + virtual void init_radio(radio_events_t *events) + { + }; + + virtual void radio_reset() + { + }; + + virtual void sleep(void) + { + }; + + virtual void standby(void) + { + }; + + virtual void set_rx_config(radio_modems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidth_afc, uint16_t preamble_len, + uint16_t symb_timeout, bool fix_len, + uint8_t payload_len, + bool crc_on, bool freq_hop_on, uint8_t hop_period, + bool iq_inverted, bool rx_continuous) + { + }; + + virtual void set_tx_config(radio_modems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preamble_len, + bool fix_len, bool crc_on, bool freq_hop_on, + uint8_t hop_period, bool iq_inverted, uint32_t timeout) + { + }; + + virtual void send(uint8_t *buffer, uint8_t size) + { + }; + + virtual void receive(void) + { + }; + + virtual void set_channel(uint32_t freq) + { + }; + + virtual uint32_t random(void) + { + }; + + virtual uint8_t get_status(void) + { + return uint8_value; + }; + + virtual void set_max_payload_length(radio_modems_t modem, uint8_t max) + { + }; + + virtual void set_public_network(bool enable) + { + }; + + virtual uint32_t time_on_air(radio_modems_t modem, uint8_t pkt_len) + { + }; + + virtual bool perform_carrier_sense(radio_modems_t modem, + uint32_t freq, + int16_t rssi_threshold, + uint32_t max_carrier_sense_time) + { + return bool_value; + }; + + virtual void start_cad(void) + { + }; + + virtual bool check_rf_frequency(uint32_t frequency) + { + return bool_value; + }; + + virtual void set_tx_continuous_wave(uint32_t freq, int8_t power, uint16_t time) + { + }; + + virtual void lock(void) + { + }; + + virtual void unlock(void) + { + }; + + bool bool_value; + uint8_t uint8_value; +}; + +class Test_LoRaPHY : public testing::Test { +protected: + my_LoRaPHY *object; + + virtual void SetUp() + { + object = new my_LoRaPHY(); + memset(&object->get_phy_params(), 0, sizeof(object->get_phy_params())); + } + + virtual void TearDown() + { + delete object; + } +}; + +TEST_F(Test_LoRaPHY, initialize) +{ + object->initialize(NULL); +} + +TEST_F(Test_LoRaPHY, set_radio_instance) +{ + my_radio radio; + object->set_radio_instance(radio); +} + +TEST_F(Test_LoRaPHY, put_radio_to_sleep) +{ + my_radio radio; + object->set_radio_instance(radio); + object->put_radio_to_sleep(); +} + +TEST_F(Test_LoRaPHY, put_radio_to_standby) +{ + my_radio radio; + object->set_radio_instance(radio); + object->put_radio_to_standby(); +} + +TEST_F(Test_LoRaPHY, handle_receive) +{ + my_radio radio; + object->set_radio_instance(radio); + object->handle_receive(); +} + +TEST_F(Test_LoRaPHY, handle_send) +{ + my_radio radio; + object->set_radio_instance(radio); + object->handle_send(NULL, 0); +} + +TEST_F(Test_LoRaPHY, setup_public_network_mode) +{ + my_radio radio; + channel_params_t p; + object->get_phy_params().channels.channel_list = &p; + object->set_radio_instance(radio); + object->setup_public_network_mode(false); +} + +TEST_F(Test_LoRaPHY, get_radio_rng) +{ + my_radio radio; + object->set_radio_instance(radio); + EXPECT_TRUE(0 != object->get_radio_rng()); +} + +TEST_F(Test_LoRaPHY, calculate_backoff) +{ + channel_params_t p[1]; + p[0].band = 0; + p[0].dr_range.fields.min = DR_0; + p[0].dr_range.fields.max = DR_5; + object->get_phy_params().channels.channel_list = p; + band_t b[1]; + b[0].duty_cycle = 0; + b[0].higher_band_freq = 8689000; + b[0].lower_band_freq = 8687000; + b[0].max_tx_pwr = 20; + b[0].last_join_tx_time = 0; + b[0].last_tx_time = 0; + b[0].off_time = 0; + object->get_phy_params().bands.table = b; + object->calculate_backoff(false, false, false, 0, 10, 12); + + object->calculate_backoff(false, true, false, 0, 3600000 + 10, 12); + + object->calculate_backoff(false, false, true, 0, 3600000 + 36000000 + 10, 12); +} + +TEST_F(Test_LoRaPHY, mask_bit_test) +{ + uint16_t buf; + buf = 0x08; + EXPECT_TRUE(!object->mask_bit_test(&buf, 0)); +} + +TEST_F(Test_LoRaPHY, mask_bit_set) +{ + uint16_t buf; + object->mask_bit_set(&buf, 3); +} + +TEST_F(Test_LoRaPHY, mask_bit_clear) +{ + uint16_t buf; + object->mask_bit_clear(&buf, 0); +} + +TEST_F(Test_LoRaPHY, request_new_channel) +{ + band_t b; + object->get_phy_params().bands.size = 1; + b.higher_band_freq = 8689000; + b.lower_band_freq = 8678000; + b.duty_cycle = 0; + b.last_join_tx_time = 0; + b.last_tx_time = 0; + b.max_tx_pwr = 20; + b.off_time = 0; + object->get_phy_params().bands.table = &b; + + channel_params_t p; + //First 3 channels are set to be default + p.band = 0; + p.dr_range.fields.min = DR_0; + p.dr_range.fields.max = DR_5; + p.frequency = 8687000; + p.rx1_frequency = 0; + uint16_t dflt_msk = 0x07; + object->get_phy_params().channels.default_mask = &dflt_msk; + object->get_phy_params().channels.channel_list = &p; + object->get_phy_params().custom_channelplans_supported = true; + + //Default channel, PARAMETER invalid + EXPECT_TRUE(0 == object->request_new_channel(0, &p)); + + //Freq & DR invalid + p.frequency = 12345; + p.dr_range.fields.max = 12; + object->get_phy_params().max_channel_cnt = 16; + object->get_phy_params().min_tx_datarate = DR_0; + object->get_phy_params().max_tx_datarate = DR_5; + // Frequency and DR are invalid - LORAWAN_STATUS_FREQ_AND_DR_INVALID + EXPECT_TRUE(0 == object->request_new_channel(0, &p)); + + //Freq invalid + p.frequency = 12345; + p.dr_range.fields.max = DR_5; + object->get_phy_params().default_channel_cnt = 3; + EXPECT_TRUE(2 == object->request_new_channel(0, &p)); + + //DR invalid + p.frequency = 8687000; + p.dr_range.fields.max = 12; + p.dr_range.fields.min = 1; + EXPECT_TRUE(1 == object->request_new_channel(0, &p)); + + //STATUS_OK + p.dr_range.fields.max = DR_5; + p.dr_range.fields.min = DR_0; + uint16_t ch_msk = 0x08; + object->get_phy_params().channels.mask = &ch_msk; + EXPECT_TRUE(3 == object->request_new_channel(0, &p)); +} + +TEST_F(Test_LoRaPHY, set_last_tx_done) +{ + channel_params_t p[1]; + p[0].band = 0; + object->get_phy_params().channels.channel_list = p; + band_t b[1]; + object->get_phy_params().bands.table = b; + object->set_last_tx_done(0, false, 0); + + object->set_last_tx_done(0, true, 0); +} + +TEST_F(Test_LoRaPHY, restore_default_channels) +{ + channel_params_t p[1]; + p[0].band = 0; + object->get_phy_params().channels.channel_list = p; + uint16_t m, dm; + object->get_phy_params().channels.mask_size = 1; + object->get_phy_params().channels.default_mask = &dm; + object->get_phy_params().channels.mask = &m; + object->restore_default_channels(); +} + +TEST_F(Test_LoRaPHY, apply_cf_list) +{ + uint8_t list[16]; + memset(list, 0, 16); + object->apply_cf_list(list, 0); + + object->get_phy_params().cflist_supported = true; + object->apply_cf_list(list, 0); + + object->get_phy_params().default_channel_cnt = 1; + object->get_phy_params().cflist_channel_cnt = 0; + object->get_phy_params().max_channel_cnt = 3; + + uint16_t def_mask = 0x01; + channel_params_t p[16]; + memset(p, 0, 16); + //one default channel + p[0].band = 0; + p[0].dr_range.fields.min = DR_0; + p[0].dr_range.fields.min = DR_5; + p[0].frequency = 8687000; + + object->get_phy_params().channels.default_mask = &def_mask; + object->get_phy_params().channels.mask = &def_mask; + object->get_phy_params().channels.channel_list = p; + object->apply_cf_list(list, 16); + + list[1] = 15; + object->get_phy_params().cflist_channel_cnt = 1; + object->apply_cf_list(list, 16); +} + +TEST_F(Test_LoRaPHY, get_next_ADR) +{ + int8_t i = 0; + int8_t j = 0; + uint32_t ctr = 0; + object->get_phy_params().min_tx_datarate = 0; + EXPECT_TRUE(!object->get_next_ADR(false, i, j, ctr)); + + i = 1; + object->get_phy_params().adr_ack_limit = 3; + EXPECT_TRUE(!object->get_next_ADR(false, i, j, ctr)); + + object->get_phy_params().adr_ack_limit = 3; + ctr = 4; + object->get_phy_params().max_tx_power = 2; + object->get_phy_params().adr_ack_delay = 1; + EXPECT_TRUE(object->get_next_ADR(true, i, j, ctr)); + + ctr = 5; + object->get_phy_params().adr_ack_delay = 2; + EXPECT_TRUE(!object->get_next_ADR(true, i, j, ctr)); +} + +TEST_F(Test_LoRaPHY, rx_config) +{ + my_radio radio; + object->set_radio_instance(radio); + uint8_t list; + object->get_phy_params().datarates.table = &list; + uint8_t list2; + object->get_phy_params().payloads_with_repeater.table = &list2; + rx_config_params_t p; + memset(&p, 0, sizeof(rx_config_params_t)); + p.datarate = 0; + p.rx_slot = RX_SLOT_WIN_1; + channel_params_t pp[1]; + object->get_phy_params().channels.channel_list = pp; + pp[0].rx1_frequency = 2; + p.channel = 0; + uint8_t tab[8]; + object->get_phy_params().payloads.table = tab; + object->get_phy_params().payloads_with_repeater.table = tab; + EXPECT_TRUE(object->rx_config(&p)); + + p.datarate = DR_7; + p.is_repeater_supported = true; + object->get_phy_params().fsk_supported = true; + EXPECT_TRUE(object->rx_config(&p)); +} + +TEST_F(Test_LoRaPHY, compute_rx_win_params) +{ + uint32_t list[1]; + list[0] = 125000; + object->get_phy_params().bandwidths.table = list; + uint8_t list2[1]; + list2[0] = 12; + object->get_phy_params().datarates.table = &list2; + channel_params_t ch_lst[16]; + memset(ch_lst, 0, sizeof(channel_params_t) * 16); + ch_lst[0].band = 0; + ch_lst[0].dr_range.fields.min = DR_0; + ch_lst[0].dr_range.fields.max = DR_5; + ch_lst[0].frequency = 8687000; + object->get_phy_params().channels.channel_list = ch_lst; + object->get_phy_params().channels.channel_list_size = 16; + rx_config_params_t p; + memset(&p, 0, sizeof(rx_config_params_t)); + p.frequency = 8687000; + object->compute_rx_win_params(0, 0, 0, &p); + + p.datarate = 0; + list[0] = 125000; + object->compute_rx_win_params(0, 0, 0, &p); + + list[0] = 250000; + object->compute_rx_win_params(0, 0, 0, &p); + + list[0] = 500000; + object->get_phy_params().fsk_supported = true; + object->get_phy_params().max_rx_datarate = 0; + object->compute_rx_win_params(0, 0, 0, &p); +} + +TEST_F(Test_LoRaPHY, tx_config) +{ + band_t b; + memset(&b, 0, sizeof(band_t)); + object->get_phy_params().bands.table = &b; + channel_params_t pp; + memset(&pp, 0, sizeof(channel_params_t)); + pp.band = 0; + object->get_phy_params().channels.channel_list = &pp; + uint32_t list[1]; + list[0] = 125000; + object->get_phy_params().bandwidths.table = &list; + uint8_t list2[1]; + list2[0] = 12; + object->get_phy_params().datarates.table = &list2; + my_radio radio; + object->set_radio_instance(radio); + tx_config_params_t p; + memset(&p, 0, sizeof(tx_config_params_t)); + p.channel = 0; + int8_t i = 20; + lorawan_time_t t = 36; + object->tx_config(&p, &i, &t); + + p.datarate = 8; + object->get_phy_params().max_tx_datarate = 8; + object->tx_config(&p, &i, &t); +} + +TEST_F(Test_LoRaPHY, link_ADR_request) +{ + adr_req_params_t p; + memset(&p, 0, sizeof(adr_req_params_t)); + uint8_t b[100]; + memset(b, 0, 100); + p.payload = b; + b[0] = 0x03; + b[1] = 1; + b[2] = 0; + b[3] = 0; + b[4] = 1 << 4; + b[5] = 0x03; + b[6] = 1; + b[7] = 1; + b[8] = 1; + b[9] = 6 << 4; + b[10] = 0x03; + b[11] = 1; + b[12] = 0xff; + b[13] = 0xff; + b[14] = 0; + b[15] = 0; + p.payload_size = 16; + int8_t i = 0, j = 0; + uint8_t k = 0, l = 0; + uint8_t t[5] = {12, 11, 10, 9, 8}; + t[0] = 0; + object->get_phy_params().datarates.size = 5; + object->get_phy_params().datarates.table = t; + //Test without ADR payload does not make sense here. + + object->get_phy_params().max_channel_cnt = 16; + channel_params_t li[16]; + memset(li, 0, sizeof(channel_params_t) * 16); + object->get_phy_params().channels.channel_list = li; + li[0].frequency = 0; + li[1].frequency = 5; + EXPECT_TRUE(4 == object->link_ADR_request(&p, &i, &j, &k, &l)); + + t[0] = 3; + //verify adr with p.adr_enabled = false + EXPECT_TRUE(0 == object->link_ADR_request(&p, &i, &j, &k, &l)); + + p.current_nb_trans = 0; + EXPECT_TRUE(0 == object->link_ADR_request(&p, &i, &j, &k, &l)); + + p.adr_enabled = true; + li[0].dr_range.value = 0xff; + object->get_phy_params().min_tx_datarate = DR_3; + object->get_phy_params().max_tx_datarate = DR_8; + + //verify adr with status != 0 + EXPECT_TRUE(0 == object->link_ADR_request(&p, &i, &j, &k, &l)); + + object->get_phy_params().max_tx_power = 2; + object->get_phy_params().min_tx_power = 6; + //verify adr with status != 0 + EXPECT_TRUE(4 == object->link_ADR_request(&p, &i, &j, &k, &l)); + + object->get_phy_params().min_tx_datarate = DR_0; + li[0].dr_range.value = 0xf0; + EXPECT_TRUE(6 == object->link_ADR_request(&p, &i, &j, &k, &l)); + + li[1].dr_range.fields.min = DR_0; + li[1].dr_range.fields.max = DR_13; + b[4] = 6 << 4; + p.payload_size = 5; + EXPECT_TRUE(7 == object->link_ADR_request(&p, &i, &j, &k, &l)); + + uint16_t mask[2]; + object->get_phy_params().channels.mask = mask; + object->get_phy_params().channels.mask_size = 2; + EXPECT_TRUE(7 == object->link_ADR_request(&p, &i, &j, &k, &l)); + + li[0].dr_range.value = 0xff; + object->get_phy_params().max_channel_cnt = 0; + EXPECT_TRUE(5 == object->link_ADR_request(&p, &i, &j, &k, &l)); + + b[0] = 0x03; + b[1] = 1; + b[2] = 0; + b[3] = 0; + b[4] = 0; + t[0] = 0; + object->get_phy_params().datarates.size = 1; + object->get_phy_params().datarates.table = t; + //Test without ADR payload does not make sense here. + + object->get_phy_params().max_channel_cnt = 2; + li[0].frequency = 0; + li[1].frequency = 5; + EXPECT_TRUE(4 == object->link_ADR_request(&p, &i, &j, &k, &l)); +} + +TEST_F(Test_LoRaPHY, accept_rx_param_setup_req) +{ + my_radio radio; + radio.bool_value = true; + object->set_radio_instance(radio); + rx_param_setup_req_t req; + req.datarate = DR_0; + req.dr_offset = 0; + req.frequency = 8678000; + band_t band[1]; + memset(band, 0, sizeof(band_t)); + band[0].higher_band_freq = 8688000; + band[0].lower_band_freq = 8666000; + object->get_phy_params().bands.size = 1; + object->get_phy_params().bands.table = band; + EXPECT_TRUE(0x07 == object->accept_rx_param_setup_req(&req)); +} + +TEST_F(Test_LoRaPHY, accept_tx_param_setup_req) +{ + my_radio radio; + object->set_radio_instance(radio); + object->get_phy_params().accept_tx_param_setup_req = true; + EXPECT_TRUE(object->accept_tx_param_setup_req(0, 0)); +} + +TEST_F(Test_LoRaPHY, dl_channel_request) +{ + EXPECT_TRUE(0 == object->dl_channel_request(0, 0)); + + object->get_phy_params().dl_channel_req_supported = true; + object->get_phy_params().bands.size = 1; + band_t t[1]; + memset(t, 0, sizeof(band_t)); + t[0].higher_band_freq = 8688000; + t[0].lower_band_freq = 8668000; + object->get_phy_params().bands.size = 1; + object->get_phy_params().bands.table = t; + channel_params_t p[16]; + memset(p, 0, sizeof(channel_params_t) * 16); + object->get_phy_params().channels.channel_list_size = 16; + object->get_phy_params().channels.channel_list = p; + + p[0].frequency = 0; + EXPECT_TRUE(0 == object->dl_channel_request(0, 1)); + + t[0].higher_band_freq = 19; + t[0].lower_band_freq = 0; + p[0].frequency = 1; + EXPECT_TRUE(3 == object->dl_channel_request(0, 1)); +} + +TEST_F(Test_LoRaPHY, get_alternate_DR) +{ + EXPECT_TRUE(0 == object->get_alternate_DR(0)); + + object->get_phy_params().default_max_datarate = 5; + object->get_phy_params().min_tx_datarate = 4; + EXPECT_TRUE(5 == object->get_alternate_DR(1)); + + object->get_phy_params().default_max_datarate = 6; + object->get_phy_params().min_tx_datarate = 4; + EXPECT_TRUE(5 == object->get_alternate_DR(2)); +} + +TEST_F(Test_LoRaPHY, set_next_channel) +{ + channel_selection_params_t p; + memset(&p, 0, sizeof(channel_selection_params_t)); + band_t band[1]; + memset(band, 0, sizeof(band_t)); + band[0].higher_band_freq = 8687000; + object->get_phy_params().bands.size = 1; + object->get_phy_params().bands.table = band; + uint8_t ch = 5; + lorawan_time_t t1 = 16; + lorawan_time_t t2 = 32; + p.aggregate_timeoff = 10000; + EXPECT_TRUE(LORAWAN_STATUS_DUTYCYCLE_RESTRICTED == object->set_next_channel(&p, &ch, &t1, &t2)); + + uint16_t list[129]; + memset(list, 0, sizeof(list)); + list[4] = 1; + list[128] = 1; + object->get_phy_params().channels.mask = list; + object->get_phy_params().channels.default_mask = list; + object->get_phy_params().channels.mask_size = 1; + p.aggregate_timeoff = 10000; + EXPECT_TRUE(LORAWAN_STATUS_DUTYCYCLE_RESTRICTED == object->set_next_channel(&p, &ch, &t1, &t2)); + + LoRaWANTimer_stub::time_value = 20000; + EXPECT_TRUE(LORAWAN_STATUS_NO_CHANNEL_FOUND == object->set_next_channel(&p, &ch, &t1, &t2)); + + p.joined = false; + p.dc_enabled = false; + band_t b[4]; + ch = 5; + t1 = 16; + t2 = 32; + memset(b, 0, sizeof(band_t) * 4); + object->get_phy_params().bands.size = 2; + object->get_phy_params().bands.table = &b; + b[0].off_time = 0; + b[1].off_time = 9999999; + memset(list, 0, 129); + list[4] = 0; + object->get_phy_params().channels.mask = list; + object->get_phy_params().channels.default_mask = list; + object->get_phy_params().channels.mask_size = 128; + p.current_datarate = DR_1; + object->get_phy_params().max_channel_cnt = 4; + EXPECT_TRUE(LORAWAN_STATUS_NO_CHANNEL_FOUND == object->set_next_channel(&p, &ch, &t1, &t2)); + + p.dc_enabled = true; + EXPECT_TRUE(LORAWAN_STATUS_NO_CHANNEL_FOUND == object->set_next_channel(&p, &ch, &t1, &t2)); + + list[4] = 1; + p.joined = true; + p.dc_enabled = false; + channel_params_t l[4]; + l[0].dr_range.value = 0xff; + l[1].dr_range.value = 0xff; + l[2].dr_range.value = 0xf0; + l[3].dr_range.value = 0xf0; + l[2].band = 2; + l[3].band = 3; + object->get_phy_params().channels.channel_list = l; + list[0] = 0xFF; + b[2].off_time = 9999999; + b[3].off_time = 0; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_next_channel(&p, &ch, &t1, &t2)); + + b[0].off_time = 10000; + LoRaWANTimer_stub::time_value = 2000; + p.aggregate_timeoff = 1000; + p.dc_enabled = true; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_next_channel(&p, &ch, &t1, &t2)); +} + +TEST_F(Test_LoRaPHY, add_channel) +{ + uint16_t list[16]; + object->get_phy_params().channels.mask = list; + object->get_phy_params().channels.default_mask = list; + channel_params_t p; + p.band = 0; + p.frequency = 0; + EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->add_channel(&p, 0)); + + object->get_phy_params().custom_channelplans_supported = true; + object->get_phy_params().max_channel_cnt = 2; + object->get_phy_params().min_tx_datarate = 0; + object->get_phy_params().max_tx_datarate = 13; + p.dr_range.fields.min = 6; + p.dr_range.fields.max = 1; + EXPECT_TRUE(LORAWAN_STATUS_FREQ_AND_DR_INVALID == object->add_channel(&p, 0)); +} + +TEST_F(Test_LoRaPHY, remove_channel) +{ + channel_params_t pp; + pp.band = 0; + object->get_phy_params().channels.channel_list = &pp; + uint16_t list[16]; + list[0] = 1; + object->get_phy_params().channels.mask = list; + object->get_phy_params().channels.default_mask = list; + EXPECT_TRUE(false == object->remove_channel(0)); + + list[0] = 0; + EXPECT_TRUE(false == object->remove_channel(0)); + + object->get_phy_params().channels.mask_size = 1; + object->get_phy_params().max_channel_cnt = 0; + EXPECT_TRUE(false == object->remove_channel(0)); + + object->get_phy_params().max_channel_cnt = 1; + EXPECT_TRUE(true == object->remove_channel(0)); +} + +TEST_F(Test_LoRaPHY, set_tx_cont_mode) +{ + channel_params_t pp; + pp.band = 0; + object->get_phy_params().channels.channel_list = &pp; + band_t b; + b.max_tx_pwr = 10; + object->get_phy_params().bands.table = &b; + my_radio radio; + object->set_radio_instance(radio); + + cw_mode_params_t p; + p.max_eirp = 0; + p.channel = 0; + p.tx_power = -1; + p.datarate = 0; + p.antenna_gain = 1; + object->set_tx_cont_mode(&p); + + p.max_eirp = 1; + p.antenna_gain = 1; + object->set_tx_cont_mode(&p, 1); +} + +TEST_F(Test_LoRaPHY, apply_DR_offset) +{ + EXPECT_TRUE(0 == object->apply_DR_offset(0, 0)); + + object->get_phy_params().min_tx_datarate = 1; + EXPECT_TRUE(1 == object->apply_DR_offset(0, 2)); +} + +TEST_F(Test_LoRaPHY, reset_to_default_values) +{ + loramac_protocol_params p; + object->reset_to_default_values(&p); + + object->reset_to_default_values(&p, true); +} + +TEST_F(Test_LoRaPHY, get_next_lower_tx_datarate) +{ + EXPECT_TRUE(DR_0 == object->get_next_lower_tx_datarate(DR_2)); + + object->get_phy_params().ul_dwell_time_setting = 1; + object->get_phy_params().dwell_limit_datarate = DR_1; + EXPECT_TRUE(DR_1 == object->get_next_lower_tx_datarate(DR_2)); +} + +TEST_F(Test_LoRaPHY, get_minimum_rx_datarate) +{ + EXPECT_TRUE(DR_0 == object->get_minimum_rx_datarate()); + + object->get_phy_params().dl_dwell_time_setting = 1; + object->get_phy_params().dwell_limit_datarate = DR_1; + EXPECT_TRUE(DR_1 == object->get_minimum_rx_datarate()); +} + +TEST_F(Test_LoRaPHY, get_minimum_tx_datarate) +{ + EXPECT_TRUE(DR_0 == object->get_minimum_tx_datarate()); + + object->get_phy_params().ul_dwell_time_setting = 1; + object->get_phy_params().dwell_limit_datarate = DR_1; + EXPECT_TRUE(DR_1 == object->get_minimum_tx_datarate()); +} + +TEST_F(Test_LoRaPHY, get_default_tx_datarate) +{ + EXPECT_TRUE(0 == object->get_default_tx_datarate()); +} + +TEST_F(Test_LoRaPHY, get_default_max_tx_datarate) +{ + EXPECT_TRUE(DR_0 == object->get_default_max_tx_datarate()); +} + +TEST_F(Test_LoRaPHY, get_default_tx_power) +{ + EXPECT_TRUE(0 == object->get_default_tx_power()); +} + +TEST_F(Test_LoRaPHY, get_max_payload) +{ + uint8_t list = 8; + object->get_phy_params().payloads.table = &list; + object->get_phy_params().payloads_with_repeater.table = &list; + EXPECT_TRUE(8 == object->get_max_payload(0)); + + EXPECT_TRUE(8 == object->get_max_payload(0, true)); +} + +TEST_F(Test_LoRaPHY, get_maximum_frame_counter_gap) +{ + EXPECT_TRUE(0 == object->get_maximum_frame_counter_gap()); +} + +TEST_F(Test_LoRaPHY, get_ack_timeout) +{ + EXPECT_TRUE(0 == object->get_ack_timeout()); +} + +TEST_F(Test_LoRaPHY, get_default_rx2_frequency) +{ + EXPECT_TRUE(0 == object->get_default_rx2_frequency()); +} + +TEST_F(Test_LoRaPHY, get_default_rx2_datarate) +{ + EXPECT_TRUE(0 == object->get_default_rx2_datarate()); +} + +TEST_F(Test_LoRaPHY, get_channel_mask) +{ + EXPECT_TRUE(0 == object->get_channel_mask()); + EXPECT_TRUE(0 == object->get_channel_mask(true)); +} + +TEST_F(Test_LoRaPHY, get_max_nb_channels) +{ + EXPECT_TRUE(0 == object->get_max_nb_channels()); +} + +TEST_F(Test_LoRaPHY, get_phy_channels) +{ + EXPECT_TRUE(0 == object->get_phy_channels()); +} + +TEST_F(Test_LoRaPHY, is_custom_channel_plan_supported) +{ + EXPECT_TRUE(false == object->is_custom_channel_plan_supported()); +} + +TEST_F(Test_LoRaPHY, verify_rx_datarate) +{ + EXPECT_TRUE(false == object->verify_rx_datarate(0)); + + object->get_phy_params().datarates.size = 1; + uint8_t t[1]; + t[0] = 2; + object->get_phy_params().datarates.table = t; + object->get_phy_params().dl_dwell_time_setting = 0; + + EXPECT_TRUE(true == object->verify_rx_datarate(0)); + + object->get_phy_params().dl_dwell_time_setting = 1; + object->get_phy_params().min_rx_datarate = 0; + + EXPECT_TRUE(true == object->verify_rx_datarate(0)); +} + +TEST_F(Test_LoRaPHY, verify_tx_datarate) +{ + EXPECT_TRUE(false == object->verify_tx_datarate(0)); + + object->get_phy_params().datarates.size = 1; + uint8_t t[1]; + t[0] = 2; + object->get_phy_params().datarates.table = t; + object->get_phy_params().ul_dwell_time_setting = 0; + EXPECT_TRUE(true == object->verify_tx_datarate(0)); + + object->get_phy_params().ul_dwell_time_setting = 1; + EXPECT_TRUE(true == object->verify_tx_datarate(0)); + + object->get_phy_params().ul_dwell_time_setting = 1; + EXPECT_TRUE(true == object->verify_tx_datarate(0, true)); +} + +TEST_F(Test_LoRaPHY, verify_tx_power) +{ + EXPECT_TRUE(true == object->verify_tx_power(0)); +} + +TEST_F(Test_LoRaPHY, verify_duty_cycle) +{ + EXPECT_TRUE(true == object->verify_duty_cycle(false)); + + EXPECT_TRUE(false == object->verify_duty_cycle(true)); +} + +TEST_F(Test_LoRaPHY, verify_nb_join_trials) +{ + EXPECT_TRUE(false == object->verify_nb_join_trials(0)); + EXPECT_TRUE(true == object->verify_nb_join_trials(100)); +} + + diff --git a/UNITTESTS/features/lorawan/loraphy/unittest.cmake b/UNITTESTS/features/lorawan/loraphy/unittest.cmake new file mode 100644 index 0000000000..c1abde4e46 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphy/unittest.cmake @@ -0,0 +1,41 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaPHY") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/phy/LoRaPHY.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/phy +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loraphy/Test_LoRaPHY.cpp + stubs/LoRaWANTimer_stub.cpp + stubs/mbed_assert_stub.c +) + + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 -DMBED_CONF_LORA_DUTY_CYCLE_ON_JOIN=true") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 -DMBED_CONF_LORA_DUTY_CYCLE_ON_JOIN=true") diff --git a/UNITTESTS/features/lorawan/loraphyas923/Test_LoRaPHYAS923.cpp b/UNITTESTS/features/lorawan/loraphyas923/Test_LoRaPHYAS923.cpp new file mode 100644 index 0000000000..47e9b76212 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphyas923/Test_LoRaPHYAS923.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaPHYAS923.h" + +#include "LoRaPHY_stub.h" + +class my_radio : public LoRaRadio { +public: + + virtual void init_radio(radio_events_t *events) + { + }; + + virtual void radio_reset() + { + }; + + virtual void sleep(void) + { + }; + + virtual void standby(void) + { + }; + + virtual void set_rx_config(radio_modems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidth_afc, uint16_t preamble_len, + uint16_t symb_timeout, bool fix_len, + uint8_t payload_len, + bool crc_on, bool freq_hop_on, uint8_t hop_period, + bool iq_inverted, bool rx_continuous) + { + }; + + virtual void set_tx_config(radio_modems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preamble_len, + bool fix_len, bool crc_on, bool freq_hop_on, + uint8_t hop_period, bool iq_inverted, uint32_t timeout) + { + }; + + virtual void send(uint8_t *buffer, uint8_t size) + { + }; + + virtual void receive(void) + { + }; + + virtual void set_channel(uint32_t freq) + { + }; + + virtual uint32_t random(void) + { + }; + + virtual uint8_t get_status(void) + { + return uint8_value; + }; + + virtual void set_max_payload_length(radio_modems_t modem, uint8_t max) + { + }; + + virtual void set_public_network(bool enable) + { + }; + + virtual uint32_t time_on_air(radio_modems_t modem, uint8_t pkt_len) + { + }; + + virtual bool perform_carrier_sense(radio_modems_t modem, + uint32_t freq, + int16_t rssi_threshold, + uint32_t max_carrier_sense_time) + { + return bool_value; + }; + + virtual void start_cad(void) + { + }; + + virtual bool check_rf_frequency(uint32_t frequency) + { + return bool_value; + }; + + virtual void set_tx_continuous_wave(uint32_t freq, int8_t power, uint16_t time) + { + }; + + virtual void lock(void) + { + }; + + virtual void unlock(void) + { + }; + + bool bool_value; + uint8_t uint8_value; +}; + +class Test_LoRaPHYAS923 : public testing::Test { +protected: + LoRaPHYAS923 *object; + my_radio radio; + + virtual void SetUp() + { + LoRaPHY_stub::radio = &radio; + object = new LoRaPHYAS923(); + } + + virtual void TearDown() + { + LoRaPHY_stub::radio = NULL; + delete object; + } +}; + +TEST_F(Test_LoRaPHYAS923, constructor) +{ + EXPECT_TRUE(object); +} + +TEST_F(Test_LoRaPHYAS923, get_alternate_DR) +{ + EXPECT_TRUE(2 == object->get_alternate_DR(1)); +} + +TEST_F(Test_LoRaPHYAS923, set_next_channel) +{ + channel_selection_params_t next_channel; + lorawan_time_t backoff_time = 0; + lorawan_time_t time = 0; + uint8_t ch = 1; + + next_channel.aggregate_timeoff = 0; + LoRaPHY_stub::uint8_value = 0; + EXPECT_TRUE(LORAWAN_STATUS_NO_CHANNEL_FOUND == object->set_next_channel(&next_channel, &ch, &backoff_time, &time)); + + next_channel.aggregate_timeoff = 1; + radio.bool_value = false; + EXPECT_TRUE(LORAWAN_STATUS_DUTYCYCLE_RESTRICTED == object->set_next_channel(&next_channel, &ch, &backoff_time, &time)); + + next_channel.aggregate_timeoff = 0; + LoRaPHY_stub::uint8_value = 1; + EXPECT_TRUE(LORAWAN_STATUS_NO_FREE_CHANNEL_FOUND == object->set_next_channel(&next_channel, &ch, &backoff_time, &time)); + + radio.bool_value = true; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_next_channel(&next_channel, &ch, &backoff_time, &time)); +} + +TEST_F(Test_LoRaPHYAS923, apply_DR_offset) +{ + //0, 1, 2, 3, 4, 5, -1, -2 + for (int i = 0; i < 8; i++) { + uint8_t val = i > 5 ? 5 : 2; + EXPECT_TRUE(object->apply_DR_offset(0, i)); + } +} + diff --git a/UNITTESTS/features/lorawan/loraphyas923/unittest.cmake b/UNITTESTS/features/lorawan/loraphyas923/unittest.cmake new file mode 100644 index 0000000000..b4648ab904 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphyas923/unittest.cmake @@ -0,0 +1,40 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaPHYAS923") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/phy/LoRaPHYAS923.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/phy +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loraphyas923/Test_LoRaPHYAS923.cpp + stubs/LoRaPHY_stub.cpp + stubs/LoRaWANTimer_stub.cpp + stubs/mbed_assert_stub.c + +) + diff --git a/UNITTESTS/features/lorawan/loraphyau915/Test_LoRaPHYAU915.cpp b/UNITTESTS/features/lorawan/loraphyau915/Test_LoRaPHYAU915.cpp new file mode 100644 index 0000000000..11a27e9d20 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphyau915/Test_LoRaPHYAU915.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaPHYAU915.h" + +#include "LoRaPHY_stub.h" + +class my_radio : public LoRaRadio { +public: + + virtual void init_radio(radio_events_t *events) + { + }; + + virtual void radio_reset() + { + }; + + virtual void sleep(void) + { + }; + + virtual void standby(void) + { + }; + + virtual void set_rx_config(radio_modems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidth_afc, uint16_t preamble_len, + uint16_t symb_timeout, bool fix_len, + uint8_t payload_len, + bool crc_on, bool freq_hop_on, uint8_t hop_period, + bool iq_inverted, bool rx_continuous) + { + }; + + virtual void set_tx_config(radio_modems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preamble_len, + bool fix_len, bool crc_on, bool freq_hop_on, + uint8_t hop_period, bool iq_inverted, uint32_t timeout) + { + }; + + virtual void send(uint8_t *buffer, uint8_t size) + { + }; + + virtual void receive(void) + { + }; + + virtual void set_channel(uint32_t freq) + { + }; + + virtual uint32_t random(void) + { + }; + + virtual uint8_t get_status(void) + { + return uint8_value; + }; + + virtual void set_max_payload_length(radio_modems_t modem, uint8_t max) + { + }; + + virtual void set_public_network(bool enable) + { + }; + + virtual uint32_t time_on_air(radio_modems_t modem, uint8_t pkt_len) + { + }; + + virtual bool perform_carrier_sense(radio_modems_t modem, + uint32_t freq, + int16_t rssi_threshold, + uint32_t max_carrier_sense_time) + { + return bool_value; + }; + + virtual void start_cad(void) + { + }; + + virtual bool check_rf_frequency(uint32_t frequency) + { + return bool_value; + }; + + virtual void set_tx_continuous_wave(uint32_t freq, int8_t power, uint16_t time) + { + }; + + virtual void lock(void) + { + }; + + virtual void unlock(void) + { + }; + + bool bool_value; + uint8_t uint8_value; +}; + +class Test_LoRaPHYAU915 : public testing::Test { +protected: + LoRaPHYAU915 *object; + my_radio radio; + + virtual void SetUp() + { + LoRaPHY_stub::radio = &radio; + object = new LoRaPHYAU915(); + } + + virtual void TearDown() + { + LoRaPHY_stub::radio = NULL; + delete object; + } +}; + +TEST_F(Test_LoRaPHYAU915, constructor) +{ + EXPECT_TRUE(object); +} + +TEST_F(Test_LoRaPHYAU915, rx_config) +{ + rx_config_params_t p; + memset(&p, 0, sizeof(p)); + + radio.uint8_value = 1; + EXPECT_TRUE(!object->rx_config(&p)); + + radio.uint8_value = 0; + p.is_repeater_supported = true; + EXPECT_TRUE(object->rx_config(&p)); + + p.is_repeater_supported = false; + EXPECT_TRUE(object->rx_config(&p)); +} + +TEST_F(Test_LoRaPHYAU915, tx_config) +{ + tx_config_params_t p; + memset(&p, 0, sizeof(p)); + int8_t tx = 0; + lorawan_time_t time; + p.tx_power = 9; + EXPECT_TRUE(object->tx_config(&p, &tx, &time)); +} + +TEST_F(Test_LoRaPHYAU915, link_ADR_request) +{ + adr_req_params_t params; + memset(¶ms, 0, sizeof(params)); + int8_t dr_out = 0; + int8_t tx_power_out = 0; + uint8_t nb_rep_out = 0; + uint8_t nb_bytes_parsed = 0; + + LoRaPHY_stub::uint8_value = 1; + LoRaPHY_stub::ch_mask_value = 6; + LoRaPHY_stub::adr_parse_count = 2; + EXPECT_TRUE(1 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); + + LoRaPHY_stub::adr_parse_count = 2; + LoRaPHY_stub::ch_mask_value = 7; + EXPECT_TRUE(1 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); + + LoRaPHY_stub::adr_parse_count = 2; + LoRaPHY_stub::ch_mask_value = 5; + LoRaPHY_stub::uint8_value = 6; + EXPECT_TRUE(6 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); + + LoRaPHY_stub::adr_parse_count = 2; + LoRaPHY_stub::ch_mask_value = 66; + LoRaPHY_stub::uint8_value = 7; + EXPECT_TRUE(7 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); +} + +TEST_F(Test_LoRaPHYAU915, accept_rx_param_setup_req) +{ + rx_param_setup_req_t p; + memset(&p, 0, sizeof(p)); + radio.bool_value = false; + EXPECT_TRUE(0 == object->accept_rx_param_setup_req(&p)); + + radio.bool_value = true; + p.frequency = 923300000 - 1; + EXPECT_TRUE(0 == object->accept_rx_param_setup_req(&p)); + + radio.bool_value = true; + p.frequency = 927500000 + 1; + p.datarate = 6; + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + EXPECT_TRUE(2 == object->accept_rx_param_setup_req(&p)); + + radio.bool_value = true; + p.frequency = 923300000 + 600000; + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + LoRaPHY_stub::bool_table[1] = true; + EXPECT_TRUE(7 == object->accept_rx_param_setup_req(&p)); +} + +TEST_F(Test_LoRaPHYAU915, get_alternate_DR) +{ + EXPECT_TRUE(0 == object->get_alternate_DR(0)); + + EXPECT_TRUE(6 == object->get_alternate_DR(1)); +} + +TEST_F(Test_LoRaPHYAU915, set_next_channel) +{ + channel_selection_params_t params; + uint8_t channel; + lorawan_time_t time; + lorawan_time_t timeoff; + + params.current_datarate = 6; + params.aggregate_timeoff = 0; + LoRaPHY_stub::uint8_value = 0; + EXPECT_TRUE(LORAWAN_STATUS_NO_CHANNEL_FOUND == object->set_next_channel(¶ms, &channel, &time, &timeoff)); + + radio.bool_value = false; + params.aggregate_timeoff = 1; + EXPECT_TRUE(LORAWAN_STATUS_DUTYCYCLE_RESTRICTED == object->set_next_channel(¶ms, &channel, &time, &timeoff)); + + params.aggregate_timeoff = 0; + LoRaPHY_stub::uint8_value = 1; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_next_channel(¶ms, &channel, &time, &timeoff)); +} + +TEST_F(Test_LoRaPHYAU915, apply_DR_offset) +{ +// { DR_8, DR_8, DR_8, DR_8, DR_8, DR_8 }, // DR_0 +// { DR_9, DR_8, DR_8, DR_8, DR_8, DR_8 }, // DR_1 +// { DR_10, DR_9, DR_8, DR_8, DR_8, DR_8 }, // DR_2 +// { DR_11, DR_10, DR_9, DR_8, DR_8, DR_8 }, // DR_3 +// { DR_12, DR_11, DR_10, DR_9, DR_8, DR_8 }, // DR_4 +// { DR_13, DR_12, DR_11, DR_10, DR_9, DR_8 }, // DR_5 +// { DR_13, DR_13, DR_12, DR_11, DR_10, DR_9 }, // DR_6 + + for (int i = 0; i < 7; i++) { + for (int j = 0; j < 6; j++) { + uint8_t val = 8 + i; + val -= j; + if (val > 13) { + val = 13; + } + if (val < 8) { + val = 8; + } + EXPECT_TRUE(val == object->apply_DR_offset(i, j)); + } + } +} diff --git a/UNITTESTS/features/lorawan/loraphyau915/unittest.cmake b/UNITTESTS/features/lorawan/loraphyau915/unittest.cmake new file mode 100644 index 0000000000..abc6c4752c --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphyau915/unittest.cmake @@ -0,0 +1,44 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaPHYAU915") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/phy/LoRaPHYAU915.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/phy +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loraphyau915/Test_LoRaPHYAU915.cpp + stubs/LoRaPHY_stub.cpp + stubs/LoRaWANTimer_stub.cpp + stubs/mbed_assert_stub.c + +) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_FSB_MASK=\"{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}\"") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_FSB_MASK=\"{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}\"") + + diff --git a/UNITTESTS/features/lorawan/loraphycn470/Test_LoRaPHYCN470.cpp b/UNITTESTS/features/lorawan/loraphycn470/Test_LoRaPHYCN470.cpp new file mode 100644 index 0000000000..abeefd52d6 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphycn470/Test_LoRaPHYCN470.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaPHYCN470.h" + +#include "LoRaPHY_stub.h" + +class my_radio : public LoRaRadio { +public: + + virtual void init_radio(radio_events_t *events) + { + }; + + virtual void radio_reset() + { + }; + + virtual void sleep(void) + { + }; + + virtual void standby(void) + { + }; + + virtual void set_rx_config(radio_modems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidth_afc, uint16_t preamble_len, + uint16_t symb_timeout, bool fix_len, + uint8_t payload_len, + bool crc_on, bool freq_hop_on, uint8_t hop_period, + bool iq_inverted, bool rx_continuous) + { + }; + + virtual void set_tx_config(radio_modems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preamble_len, + bool fix_len, bool crc_on, bool freq_hop_on, + uint8_t hop_period, bool iq_inverted, uint32_t timeout) + { + }; + + virtual void send(uint8_t *buffer, uint8_t size) + { + }; + + virtual void receive(void) + { + }; + + virtual void set_channel(uint32_t freq) + { + }; + + virtual uint32_t random(void) + { + }; + + virtual uint8_t get_status(void) + { + return uint8_value; + }; + + virtual void set_max_payload_length(radio_modems_t modem, uint8_t max) + { + }; + + virtual void set_public_network(bool enable) + { + }; + + virtual uint32_t time_on_air(radio_modems_t modem, uint8_t pkt_len) + { + }; + + virtual bool perform_carrier_sense(radio_modems_t modem, + uint32_t freq, + int16_t rssi_threshold, + uint32_t max_carrier_sense_time) + { + return bool_value; + }; + + virtual void start_cad(void) + { + }; + + virtual bool check_rf_frequency(uint32_t frequency) + { + return bool_value; + }; + + virtual void set_tx_continuous_wave(uint32_t freq, int8_t power, uint16_t time) + { + }; + + virtual void lock(void) + { + }; + + virtual void unlock(void) + { + }; + + bool bool_value; + uint8_t uint8_value; +}; + +class Test_LoRaPHYCN470 : public testing::Test { +protected: + LoRaPHYCN470 *object; + my_radio radio; + + virtual void SetUp() + { + + LoRaPHY_stub::radio = &radio; + object = new LoRaPHYCN470(); + } + + virtual void TearDown() + { + + LoRaPHY_stub::radio = NULL; + delete object; + } +}; + +TEST_F(Test_LoRaPHYCN470, constructor) +{ + EXPECT_TRUE(object); +} + +TEST_F(Test_LoRaPHYCN470, set_next_channel) +{ + channel_selection_params_t params; + + memset(¶ms, 0, sizeof(params)); + uint8_t channel = 0; + lorawan_time_t time = 0; + lorawan_time_t timeoff = 0; + + params.current_datarate = 4; + params.aggregate_timeoff = 0; + LoRaPHY_stub::uint8_value = 0; + EXPECT_TRUE(LORAWAN_STATUS_NO_CHANNEL_FOUND == object->set_next_channel(¶ms, &channel, &time, &timeoff)); + + radio.bool_value = false; + params.aggregate_timeoff = 1; + EXPECT_TRUE(LORAWAN_STATUS_DUTYCYCLE_RESTRICTED == object->set_next_channel(¶ms, &channel, &time, &timeoff)); + + params.aggregate_timeoff = 0; + LoRaPHY_stub::uint8_value = 1; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_next_channel(¶ms, &channel, &time, &timeoff)); +} + +TEST_F(Test_LoRaPHYCN470, rx_config) +{ + rx_config_params_t p; + memset(&p, 0, sizeof(p)); + + radio.uint8_value = 1; + EXPECT_TRUE(!object->rx_config(&p)); + + radio.uint8_value = 0; + p.is_repeater_supported = true; + EXPECT_TRUE(object->rx_config(&p)); + + p.is_repeater_supported = false; + EXPECT_TRUE(object->rx_config(&p)); +} + +TEST_F(Test_LoRaPHYCN470, tx_config) +{ + tx_config_params_t p; + memset(&p, 0, sizeof(p)); + int8_t tx = 0; + lorawan_time_t time = 0; + p.tx_power = 9; + EXPECT_TRUE(object->tx_config(&p, &tx, &time)); +} + +TEST_F(Test_LoRaPHYCN470, link_ADR_request) +{ + adr_req_params_t params; + memset(¶ms, 0, sizeof(params)); + int8_t dr_out = 0; + int8_t tx_power_out = 0; + uint8_t nb_rep_out = 0; + uint8_t nb_bytes_parsed = 0; + + LoRaPHY_stub::uint8_value = 1; + LoRaPHY_stub::ch_mask_value = 6; + LoRaPHY_stub::adr_parse_count = 2; + EXPECT_TRUE(1 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); + + LoRaPHY_stub::adr_parse_count = 2; + LoRaPHY_stub::ch_mask_value = 7; + EXPECT_TRUE(1 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); + + LoRaPHY_stub::adr_parse_count = 2; + LoRaPHY_stub::ch_mask_value = 5; + LoRaPHY_stub::uint8_value = 6; + EXPECT_TRUE(6 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); + + LoRaPHY_stub::adr_parse_count = 2; + LoRaPHY_stub::ch_mask_value = 66; + LoRaPHY_stub::uint8_value = 7; + EXPECT_TRUE(7 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); +} + +TEST_F(Test_LoRaPHYCN470, accept_rx_param_setup_req) +{ + rx_param_setup_req_t p; + memset(&p, 0, sizeof(p)); + radio.bool_value = false; + EXPECT_TRUE(0 == object->accept_rx_param_setup_req(&p)); + + radio.bool_value = true; + p.frequency = 923300000 - 1; + EXPECT_TRUE(0 == object->accept_rx_param_setup_req(&p)); + + radio.bool_value = true; + p.frequency = 927500000 + 1; + p.datarate = 6; + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + EXPECT_TRUE(2 == object->accept_rx_param_setup_req(&p)); +} + + diff --git a/UNITTESTS/features/lorawan/loraphycn470/unittest.cmake b/UNITTESTS/features/lorawan/loraphycn470/unittest.cmake new file mode 100644 index 0000000000..6c6746f189 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphycn470/unittest.cmake @@ -0,0 +1,40 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaPHYCN470") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/phy/LoRaPHYCN470.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/phy +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loraphycn470/Test_LoRaPHYCN470.cpp + stubs/LoRaPHY_stub.cpp + stubs/LoRaWANTimer_stub.cpp + stubs/mbed_assert_stub.c + +) + diff --git a/UNITTESTS/features/lorawan/loraphycn779/Test_LoRaPHYCN779.cpp b/UNITTESTS/features/lorawan/loraphycn779/Test_LoRaPHYCN779.cpp new file mode 100644 index 0000000000..0d729b4c87 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphycn779/Test_LoRaPHYCN779.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaPHYCN779.h" + +class Test_LoRaPHYCN779 : public testing::Test { +protected: + LoRaPHYCN779 *object; + + virtual void SetUp() + { + object = new LoRaPHYCN779(); + } + + virtual void TearDown() + { + delete object; + } +}; + +TEST_F(Test_LoRaPHYCN779, constructor) +{ + EXPECT_TRUE(object); +} + diff --git a/UNITTESTS/features/lorawan/loraphycn779/unittest.cmake b/UNITTESTS/features/lorawan/loraphycn779/unittest.cmake new file mode 100644 index 0000000000..d0ccd7fece --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphycn779/unittest.cmake @@ -0,0 +1,42 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaPHYCN779") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/phy/LoRaPHYCN779.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/phy +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loraphycn779/Test_LoRaPHYCN779.cpp + stubs/LoRaPHY_stub.cpp + stubs/mbed_assert_stub.c + +) + + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_FSB_MASK_CHINA=\"{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}\"") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_FSB_MASK_CHINA=\"{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}\"") diff --git a/UNITTESTS/features/lorawan/loraphyeu433/Test_LoRaPHYEU433.cpp b/UNITTESTS/features/lorawan/loraphyeu433/Test_LoRaPHYEU433.cpp new file mode 100644 index 0000000000..1981943a63 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphyeu433/Test_LoRaPHYEU433.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaPHYEU433.h" + +class Test_LoRaPHYEU433 : public testing::Test { +protected: + LoRaPHYEU433 *object; + + virtual void SetUp() + { + object = new LoRaPHYEU433(); + } + + virtual void TearDown() + { + delete object; + } +}; + +TEST_F(Test_LoRaPHYEU433, constructor) +{ + EXPECT_TRUE(object); +} + diff --git a/UNITTESTS/features/lorawan/loraphyeu433/unittest.cmake b/UNITTESTS/features/lorawan/loraphyeu433/unittest.cmake new file mode 100644 index 0000000000..5966a3ee60 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphyeu433/unittest.cmake @@ -0,0 +1,39 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaPHYEU433") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/phy/LoRaPHYEU433.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/phy +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loraphyeu433/Test_LoRaPHYEU433.cpp + stubs/LoRaPHY_stub.cpp + stubs/mbed_assert_stub.c + +) + diff --git a/UNITTESTS/features/lorawan/loraphyeu868/Test_LoRaPHYEU868.cpp b/UNITTESTS/features/lorawan/loraphyeu868/Test_LoRaPHYEU868.cpp new file mode 100644 index 0000000000..f216c12016 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphyeu868/Test_LoRaPHYEU868.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaPHYEU868.h" + +class Test_LoRaPHYEU868 : public testing::Test { +protected: + LoRaPHYEU868 *object; + + virtual void SetUp() + { + object = new LoRaPHYEU868(); + } + + virtual void TearDown() + { + delete object; + } +}; + +TEST_F(Test_LoRaPHYEU868, constructor) +{ + EXPECT_TRUE(object); +} + diff --git a/UNITTESTS/features/lorawan/loraphyeu868/unittest.cmake b/UNITTESTS/features/lorawan/loraphyeu868/unittest.cmake new file mode 100644 index 0000000000..1398a52257 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphyeu868/unittest.cmake @@ -0,0 +1,39 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaPHYEU868") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/phy/LoRaPHYEU868.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/phy +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loraphyeu868/Test_LoRaPHYEU868.cpp + stubs/LoRaPHY_stub.cpp + stubs/mbed_assert_stub.c + +) + diff --git a/UNITTESTS/features/lorawan/loraphyin865/Test_LoRaPHYIN865.cpp b/UNITTESTS/features/lorawan/loraphyin865/Test_LoRaPHYIN865.cpp new file mode 100644 index 0000000000..ecb12115f4 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphyin865/Test_LoRaPHYIN865.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaPHYIN865.h" + +class Test_LoRaPHYIN865 : public testing::Test { +protected: + LoRaPHYIN865 *object; + + virtual void SetUp() + { + object = new LoRaPHYIN865(); + } + + virtual void TearDown() + { + delete object; + } +}; + +TEST_F(Test_LoRaPHYIN865, constructor) +{ + EXPECT_TRUE(object); +} + +TEST_F(Test_LoRaPHYIN865, apply_DR_offset) +{ + EXPECT_TRUE(0 == object->apply_DR_offset(0, 0)); +} + + + diff --git a/UNITTESTS/features/lorawan/loraphyin865/unittest.cmake b/UNITTESTS/features/lorawan/loraphyin865/unittest.cmake new file mode 100644 index 0000000000..2fa34a6f73 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphyin865/unittest.cmake @@ -0,0 +1,39 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaPHYIN865") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/phy/LoRaPHYIN865.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/phy +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loraphyin865/Test_LoRaPHYIN865.cpp + stubs/LoRaPHY_stub.cpp + stubs/mbed_assert_stub.c + +) + diff --git a/UNITTESTS/features/lorawan/loraphykr920/Test_LoRaPHYKR920.cpp b/UNITTESTS/features/lorawan/loraphykr920/Test_LoRaPHYKR920.cpp new file mode 100644 index 0000000000..5a170a1f29 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphykr920/Test_LoRaPHYKR920.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaPHYKR920.h" +#include "LoRaPHY_stub.h" +#include "LoRaRadio.h" + +class my_radio : public LoRaRadio { +public: + + virtual void init_radio(radio_events_t *events) + { + }; + + virtual void radio_reset() + { + }; + + virtual void sleep(void) + { + }; + + virtual void standby(void) + { + }; + + virtual void set_rx_config(radio_modems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidth_afc, uint16_t preamble_len, + uint16_t symb_timeout, bool fix_len, + uint8_t payload_len, + bool crc_on, bool freq_hop_on, uint8_t hop_period, + bool iq_inverted, bool rx_continuous) + { + }; + + virtual void set_tx_config(radio_modems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preamble_len, + bool fix_len, bool crc_on, bool freq_hop_on, + uint8_t hop_period, bool iq_inverted, uint32_t timeout) + { + }; + + virtual void send(uint8_t *buffer, uint8_t size) + { + }; + + virtual void receive(void) + { + }; + + virtual void set_channel(uint32_t freq) + { + }; + + virtual uint32_t random(void) + { + }; + + virtual uint8_t get_status(void) + { + }; + + virtual void set_max_payload_length(radio_modems_t modem, uint8_t max) + { + }; + + virtual void set_public_network(bool enable) + { + }; + + virtual uint32_t time_on_air(radio_modems_t modem, uint8_t pkt_len) + { + }; + + virtual bool perform_carrier_sense(radio_modems_t modem, + uint32_t freq, + int16_t rssi_threshold, + uint32_t max_carrier_sense_time) + { + return bool_value; + }; + + virtual void start_cad(void) + { + }; + + virtual bool check_rf_frequency(uint32_t frequency) + { + return bool_value; + }; + + virtual void set_tx_continuous_wave(uint32_t freq, int8_t power, uint16_t time) + { + }; + + virtual void lock(void) + { + }; + + virtual void unlock(void) + { + }; + + bool bool_value; +}; + +class Test_LoRaPHYKR920 : public testing::Test { +protected: + LoRaPHYKR920 *object; + my_radio radio; + + virtual void SetUp() + { + LoRaPHY_stub::radio = &radio; + object = new LoRaPHYKR920(); + } + + virtual void TearDown() + { + LoRaPHY_stub::radio = NULL; + delete object; + } +}; + +TEST_F(Test_LoRaPHYKR920, constructor) +{ + EXPECT_TRUE(object); +} + +TEST_F(Test_LoRaPHYKR920, verify_frequency_for_band) +{ + radio.bool_value = false; + EXPECT_TRUE(false == object->verify_frequency_for_band(0, 0)); + + radio.bool_value = true; + EXPECT_TRUE(false == object->verify_frequency_for_band(0, 0)); + + EXPECT_TRUE(true == object->verify_frequency_for_band(921100000, 0)); +} + +TEST_F(Test_LoRaPHYKR920, tx_config) +{ + tx_config_params_t tx_config; + memset(&tx_config, 0, sizeof(tx_config)); + int8_t tx_power = 0; + lorawan_time_t time = 0; + + tx_config.tx_power = 9; + EXPECT_TRUE(true == object->tx_config(&tx_config, &tx_power, &time)); +} + +TEST_F(Test_LoRaPHYKR920, set_next_channel) +{ + channel_selection_params_t next_channel; + memset(&next_channel, 0, sizeof(next_channel)); + lorawan_time_t backoff_time = 0; + lorawan_time_t time = 0; + uint8_t ch = 1; + + next_channel.aggregate_timeoff = 0; + LoRaPHY_stub::uint8_value = 0; + EXPECT_TRUE(LORAWAN_STATUS_NO_CHANNEL_FOUND == object->set_next_channel(&next_channel, &ch, &backoff_time, &time)); + + next_channel.aggregate_timeoff = 1; + radio.bool_value = false; + EXPECT_TRUE(LORAWAN_STATUS_DUTYCYCLE_RESTRICTED == object->set_next_channel(&next_channel, &ch, &backoff_time, &time)); + + next_channel.aggregate_timeoff = 0; + LoRaPHY_stub::uint8_value = 1; + EXPECT_TRUE(LORAWAN_STATUS_NO_FREE_CHANNEL_FOUND == object->set_next_channel(&next_channel, &ch, &backoff_time, &time)); + + radio.bool_value = true; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_next_channel(&next_channel, &ch, &backoff_time, &time)); +} + +TEST_F(Test_LoRaPHYKR920, set_tx_cont_mode) +{ + cw_mode_params_t params; + memset(¶ms, 0, sizeof(params)); + params.tx_power = 9; + object->set_tx_cont_mode(¶ms, 0); +} + diff --git a/UNITTESTS/features/lorawan/loraphykr920/unittest.cmake b/UNITTESTS/features/lorawan/loraphykr920/unittest.cmake new file mode 100644 index 0000000000..cc32c13f02 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphykr920/unittest.cmake @@ -0,0 +1,40 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaPHYKR920") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/phy/LoRaPHYKR920.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/phy +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loraphykr920/Test_LoRaPHYKR920.cpp + stubs/LoRaPHY_stub.cpp + stubs/LoRaWANTimer_stub.cpp + stubs/mbed_assert_stub.c + +) + diff --git a/UNITTESTS/features/lorawan/loraphyus915/Test_LoRaPHYUS915.cpp b/UNITTESTS/features/lorawan/loraphyus915/Test_LoRaPHYUS915.cpp new file mode 100644 index 0000000000..b3d921bac9 --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphyus915/Test_LoRaPHYUS915.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaPHYUS915.h" +#include "LoRaPHY_stub.h" + +class my_radio : public LoRaRadio { +public: + + virtual void init_radio(radio_events_t *events) + { + }; + + virtual void radio_reset() + { + }; + + virtual void sleep(void) + { + }; + + virtual void standby(void) + { + }; + + virtual void set_rx_config(radio_modems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidth_afc, uint16_t preamble_len, + uint16_t symb_timeout, bool fix_len, + uint8_t payload_len, + bool crc_on, bool freq_hop_on, uint8_t hop_period, + bool iq_inverted, bool rx_continuous) + { + }; + + virtual void set_tx_config(radio_modems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preamble_len, + bool fix_len, bool crc_on, bool freq_hop_on, + uint8_t hop_period, bool iq_inverted, uint32_t timeout) + { + }; + + virtual void send(uint8_t *buffer, uint8_t size) + { + }; + + virtual void receive(void) + { + }; + + virtual void set_channel(uint32_t freq) + { + }; + + virtual uint32_t random(void) + { + }; + + virtual uint8_t get_status(void) + { + return uint8_value; + }; + + virtual void set_max_payload_length(radio_modems_t modem, uint8_t max) + { + }; + + virtual void set_public_network(bool enable) + { + }; + + virtual uint32_t time_on_air(radio_modems_t modem, uint8_t pkt_len) + { + }; + + virtual bool perform_carrier_sense(radio_modems_t modem, + uint32_t freq, + int16_t rssi_threshold, + uint32_t max_carrier_sense_time) + { + return bool_value; + }; + + virtual void start_cad(void) + { + }; + + virtual bool check_rf_frequency(uint32_t frequency) + { + return bool_value; + }; + + virtual void set_tx_continuous_wave(uint32_t freq, int8_t power, uint16_t time) + { + }; + + virtual void lock(void) + { + }; + + virtual void unlock(void) + { + }; + + bool bool_value; + uint8_t uint8_value; +}; + +class Test_LoRaPHYUS915 : public testing::Test { +protected: + LoRaPHYUS915 *object; + my_radio radio; + + virtual void SetUp() + { + LoRaPHY_stub::radio = &radio; + object = new LoRaPHYUS915(); + } + + virtual void TearDown() + { + LoRaPHY_stub::radio = NULL; + delete object; + } +}; + +TEST_F(Test_LoRaPHYUS915, constructor) +{ + EXPECT_TRUE(object); +} + +TEST_F(Test_LoRaPHYUS915, restore_default_channels) +{ + object->restore_default_channels(); +} + +TEST_F(Test_LoRaPHYUS915, rx_config) +{ + rx_config_params_t p; + memset(&p, 0, sizeof(p)); + + radio.uint8_value = 1; + EXPECT_TRUE(!object->rx_config(&p)); + + radio.uint8_value = 0; + p.is_repeater_supported = true; + EXPECT_TRUE(object->rx_config(&p)); + + p.is_repeater_supported = false; + EXPECT_TRUE(object->rx_config(&p)); +} + +TEST_F(Test_LoRaPHYUS915, tx_config) +{ + tx_config_params_t p; + memset(&p, 0, sizeof(p)); + int8_t tx = 0; + lorawan_time_t time = 0; + EXPECT_TRUE(object->tx_config(&p, &tx, &time)); +} + +TEST_F(Test_LoRaPHYUS915, link_ADR_request) +{ + adr_req_params_t params; + memset(¶ms, 0, sizeof(params)); + int8_t dr_out = 0; + int8_t tx_power_out = 0; + uint8_t nb_rep_out = 0; + uint8_t nb_bytes_parsed = 0; + + EXPECT_TRUE(0 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); + + LoRaPHY_stub::uint8_value = 1; + LoRaPHY_stub::ch_mask_value = 6; + LoRaPHY_stub::adr_parse_count = 2; + EXPECT_TRUE(1 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); + + LoRaPHY_stub::adr_parse_count = 2; + LoRaPHY_stub::ch_mask_value = 7; + EXPECT_TRUE(1 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); + + LoRaPHY_stub::adr_parse_count = 2; + LoRaPHY_stub::ch_mask_value = 5; + LoRaPHY_stub::uint8_value = 6; + EXPECT_TRUE(6 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); + + LoRaPHY_stub::adr_parse_count = 2; + LoRaPHY_stub::ch_mask_value = 66; + LoRaPHY_stub::uint8_value = 7; + EXPECT_TRUE(7 == object->link_ADR_request(¶ms, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed)); +} + +TEST_F(Test_LoRaPHYUS915, accept_rx_param_setup_req) +{ + rx_param_setup_req_t p; + memset(&p, 0, sizeof(p)); + radio.bool_value = false; + EXPECT_TRUE(0 == object->accept_rx_param_setup_req(&p)); + + radio.bool_value = true; + p.frequency = 923300000 - 1; + EXPECT_TRUE(0 == object->accept_rx_param_setup_req(&p)); + + radio.bool_value = true; + p.frequency = 927500000 + 1; + p.datarate = 6; + LoRaPHY_stub::bool_counter = 0; + LoRaPHY_stub::bool_table[0] = true; + EXPECT_TRUE(2 == object->accept_rx_param_setup_req(&p)); +} + +TEST_F(Test_LoRaPHYUS915, get_alternate_DR) +{ + EXPECT_TRUE(0 == object->get_alternate_DR(0)); + + EXPECT_TRUE(4 == object->get_alternate_DR(1)); +} + +TEST_F(Test_LoRaPHYUS915, set_next_channel) +{ + channel_selection_params_t params; + memset(¶ms, 0, sizeof(params)); + uint8_t channel = 0; + lorawan_time_t time = 0; + lorawan_time_t timeoff = 0; + + params.current_datarate = 4; + params.aggregate_timeoff = 0; + LoRaPHY_stub::uint8_value = 0; + EXPECT_TRUE(LORAWAN_STATUS_NO_CHANNEL_FOUND == object->set_next_channel(¶ms, &channel, &time, &timeoff)); + + radio.bool_value = false; + params.aggregate_timeoff = 1; + EXPECT_TRUE(LORAWAN_STATUS_DUTYCYCLE_RESTRICTED == object->set_next_channel(¶ms, &channel, &time, &timeoff)); + + params.aggregate_timeoff = 0; + LoRaPHY_stub::uint8_value = 1; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_next_channel(¶ms, &channel, &time, &timeoff)); +} + +TEST_F(Test_LoRaPHYUS915, apply_DR_offset) +{ + //10, 9, 8, 8 + //11, 10, 9, 8 + //12, 11, 10, 9 + //13, 12, 11, 10 + //13, 13, 12, 11 + + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 4; j++) { + uint8_t val = 10 + i; + val -= j; + if (val > 13) { + val = 13; + } + if (val < 8) { + val = 8; + } + EXPECT_TRUE(val == object->apply_DR_offset(i, j)); + } + } +} + +TEST_F(Test_LoRaPHYUS915, set_tx_cont_mode) +{ + cw_mode_params_t p; + memset(&p, 0, sizeof(p)); + object->set_tx_cont_mode(&p, 0); + + p.datarate = 4; + object->set_tx_cont_mode(&p, 0); +} diff --git a/UNITTESTS/features/lorawan/loraphyus915/unittest.cmake b/UNITTESTS/features/lorawan/loraphyus915/unittest.cmake new file mode 100644 index 0000000000..f181da5e3f --- /dev/null +++ b/UNITTESTS/features/lorawan/loraphyus915/unittest.cmake @@ -0,0 +1,42 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaPHYUS915") + +# Source files +set(unittest-sources + ../features/lorawan/lorastack/phy/LoRaPHYUS915.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/lorastack/phy +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/loraphyus915/Test_LoRaPHYUS915.cpp + stubs/LoRaPHY_stub.cpp + stubs/LoRaWANTimer_stub.cpp + stubs/mbed_assert_stub.c + +) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_FSB_MASK=\"{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}\"") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_FSB_MASK=\"{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}\"") diff --git a/UNITTESTS/features/lorawan/lorawaninterface/Test_LoRaWANInterface.cpp b/UNITTESTS/features/lorawan/lorawaninterface/Test_LoRaWANInterface.cpp new file mode 100644 index 0000000000..f4506a815c --- /dev/null +++ b/UNITTESTS/features/lorawan/lorawaninterface/Test_LoRaWANInterface.cpp @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaWANInterface.h" + +class my_radio : public LoRaRadio { +public: + + virtual void init_radio(radio_events_t *events) + { + }; + + virtual void radio_reset() + { + }; + + virtual void sleep(void) + { + }; + + virtual void standby(void) + { + }; + + virtual void set_rx_config(radio_modems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidth_afc, uint16_t preamble_len, + uint16_t symb_timeout, bool fix_len, + uint8_t payload_len, + bool crc_on, bool freq_hop_on, uint8_t hop_period, + bool iq_inverted, bool rx_continuous) + { + + }; + + virtual void set_tx_config(radio_modems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preamble_len, + bool fix_len, bool crc_on, bool freq_hop_on, + uint8_t hop_period, bool iq_inverted, uint32_t timeout) + { + }; + + virtual void send(uint8_t *buffer, uint8_t size) + { + }; + + virtual void receive(void) + { + }; + + virtual void set_channel(uint32_t freq) + { + }; + + virtual uint32_t random(void) + { + }; + + virtual uint8_t get_status(void) + { + }; + + virtual void set_max_payload_length(radio_modems_t modem, uint8_t max) + { + }; + + virtual void set_public_network(bool enable) + { + }; + + virtual uint32_t time_on_air(radio_modems_t modem, uint8_t pkt_len) + { + }; + + virtual bool perform_carrier_sense(radio_modems_t modem, + uint32_t freq, + int16_t rssi_threshold, + uint32_t max_carrier_sense_time) + { + }; + + virtual void start_cad(void) + { + }; + + virtual bool check_rf_frequency(uint32_t frequency) + { + }; + + virtual void set_tx_continuous_wave(uint32_t freq, int8_t power, uint16_t time) + { + }; + + virtual void lock(void) + { + }; + + virtual void unlock(void) + { + }; +}; + +class my_LoRaPHY : public LoRaPHY { +public: + my_LoRaPHY() + { + }; + + virtual ~my_LoRaPHY() + { + }; +}; + +class Test_LoRaWANInterface : public testing::Test { +protected: + LoRaWANInterface *object; + my_radio radio; + + virtual void SetUp() + { + object = new LoRaWANInterface(radio); + } + + virtual void TearDown() + { + delete object; + } +}; + +TEST_F(Test_LoRaWANInterface, constructor) +{ + EXPECT_TRUE(object); + + my_radio radio; + my_LoRaPHY phy; + LoRaWANInterface object(radio, phy); +} + +TEST_F(Test_LoRaWANInterface, initialize) +{ + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize(NULL)); +} + +TEST_F(Test_LoRaWANInterface, connect) +{ + EXPECT_TRUE(LORAWAN_STATUS_OK == object->connect()); + + lorawan_connect_t conn; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->connect(conn)); +} + +TEST_F(Test_LoRaWANInterface, disconnect) +{ + EXPECT_TRUE(LORAWAN_STATUS_OK == object->disconnect()); +} + +TEST_F(Test_LoRaWANInterface, add_link_check_request) +{ + EXPECT_TRUE(LORAWAN_STATUS_OK == object->add_link_check_request()); +} + +TEST_F(Test_LoRaWANInterface, remove_link_check_request) +{ + object->remove_link_check_request(); +} + +TEST_F(Test_LoRaWANInterface, set_datarate) +{ + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_datarate(1)); +} + +TEST_F(Test_LoRaWANInterface, enable_adaptive_datarate) +{ + EXPECT_TRUE(LORAWAN_STATUS_OK == object->enable_adaptive_datarate()); +} + +TEST_F(Test_LoRaWANInterface, disable_adaptive_datarate) +{ + object->disable_adaptive_datarate(); +} + +TEST_F(Test_LoRaWANInterface, set_confirmed_msg_retries) +{ + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_confirmed_msg_retries(1)); +} + +TEST_F(Test_LoRaWANInterface, set_channel_plan) +{ + lorawan_channelplan_t plan; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_channel_plan(plan)); +} + +TEST_F(Test_LoRaWANInterface, get_channel_plan) +{ + lorawan_channelplan_t plan; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->get_channel_plan(plan)); +} + +TEST_F(Test_LoRaWANInterface, remove_channel_plan) +{ + EXPECT_TRUE(LORAWAN_STATUS_OK == object->remove_channel_plan()); +} + +TEST_F(Test_LoRaWANInterface, remove_channel) +{ + EXPECT_TRUE(LORAWAN_STATUS_OK == object->remove_channel(1)); +} + +TEST_F(Test_LoRaWANInterface, send) +{ + EXPECT_TRUE(0 == object->send(1, NULL, 0, 0)); +} + +TEST_F(Test_LoRaWANInterface, receive) +{ + EXPECT_TRUE(0 == object->receive(1, NULL, 0, 0)); + + uint8_t port; + int flags; + EXPECT_TRUE(0 == object->receive(NULL, 0, port, flags)); +} + +TEST_F(Test_LoRaWANInterface, add_app_callbacks) +{ + lorawan_app_callbacks_t cbs; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->add_app_callbacks(&cbs)); +} + +TEST_F(Test_LoRaWANInterface, set_device_class) +{ + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_device_class(CLASS_A)); +} + +TEST_F(Test_LoRaWANInterface, get_tx_metadata) +{ + lorawan_tx_metadata data; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->get_tx_metadata(data)); +} + +TEST_F(Test_LoRaWANInterface, get_rx_metadata) +{ + lorawan_rx_metadata data; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->get_rx_metadata(data)); +} + +TEST_F(Test_LoRaWANInterface, get_backoff_metadata) +{ + int i; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->get_backoff_metadata(i)); +} + +TEST_F(Test_LoRaWANInterface, cancel_sending) +{ + EXPECT_TRUE(LORAWAN_STATUS_OK == object->cancel_sending()); +} + diff --git a/UNITTESTS/features/lorawan/lorawaninterface/unittest.cmake b/UNITTESTS/features/lorawan/lorawaninterface/unittest.cmake new file mode 100644 index 0000000000..9e123a1c5e --- /dev/null +++ b/UNITTESTS/features/lorawan/lorawaninterface/unittest.cmake @@ -0,0 +1,51 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaWANInterface") + +# Source files +set(unittest-sources + ../features/lorawan/LoRaWANInterface.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/lorawaninterface/Test_LoRaWANInterface.cpp + stubs/LoRaPHY_stub.cpp + stubs/LoRaWANStack_stub.cpp + stubs/LoRaMac_stub.cpp + stubs/mbed_assert_stub.c + stubs/LoRaMacCrypto_stub.cpp + stubs/LoRaMacChannelPlan_stub.cpp + stubs/LoRaWANTimer_stub.cpp + stubs/LoRaMacCommand_stub.cpp + stubs/LoRaPHYEU868_stub.cpp +) + +# defines +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_PHY=\"EU868\"") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_PHY=\"EU868\"") + + + diff --git a/UNITTESTS/features/lorawan/lorawanstack/Test_LoRaWANStack.cpp b/UNITTESTS/features/lorawan/lorawanstack/Test_LoRaWANStack.cpp new file mode 100644 index 0000000000..15a2942001 --- /dev/null +++ b/UNITTESTS/features/lorawan/lorawanstack/Test_LoRaWANStack.cpp @@ -0,0 +1,927 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaWANStack.h" +#include "EventQueue.h" + +#include "LoRaPHY_stub.h" +#include "LoRaMac_stub.h" +#include "equeue_stub.h" +#include "lorawan_data_structures.h" + +static uint8_t batt_level = 0; + +using namespace events; + +class my_LoRaPHY : public LoRaPHY { +public: + my_LoRaPHY() + { + }; + + virtual ~my_LoRaPHY() + { + }; +}; + +uint8_t my_cb() +{ + return 1; +} + +class my_radio : public LoRaRadio { +public: + radio_events_t *_ev; + + virtual void init_radio(radio_events_t *events) + { + _ev = events; + }; + + virtual void radio_reset() + { + }; + + virtual void sleep(void) + { + }; + + virtual void standby(void) + { + }; + + virtual void set_rx_config(radio_modems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidth_afc, uint16_t preamble_len, + uint16_t symb_timeout, bool fix_len, + uint8_t payload_len, + bool crc_on, bool freq_hop_on, uint8_t hop_period, + bool iq_inverted, bool rx_continuous) + { + }; + + virtual void set_tx_config(radio_modems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preamble_len, + bool fix_len, bool crc_on, bool freq_hop_on, + uint8_t hop_period, bool iq_inverted, uint32_t timeout) + { + }; + + virtual void send(uint8_t *buffer, uint8_t size) + { + }; + + virtual void receive(void) + { + }; + + virtual void set_channel(uint32_t freq) + { + }; + + virtual uint32_t random(void) + { + }; + + virtual uint8_t get_status(void) + { + return uint8_value; + }; + + virtual void set_max_payload_length(radio_modems_t modem, uint8_t max) + { + }; + + virtual void set_public_network(bool enable) + { + }; + + virtual uint32_t time_on_air(radio_modems_t modem, uint8_t pkt_len) + { + }; + + virtual bool perform_carrier_sense(radio_modems_t modem, + uint32_t freq, + int16_t rssi_threshold, + uint32_t max_carrier_sense_time) + { + return bool_value; + }; + + virtual void start_cad(void) + { + }; + + virtual bool check_rf_frequency(uint32_t frequency) + { + return bool_value; + }; + + virtual void set_tx_continuous_wave(uint32_t freq, int8_t power, uint16_t time) + { + }; + + virtual void lock(void) + { + }; + + virtual void unlock(void) + { + }; + + bool bool_value; + uint8_t uint8_value; +}; + + + +class Test_LoRaWANStack : public testing::Test { +protected: + LoRaWANStack *object; + + virtual void SetUp() + { + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + object = new LoRaWANStack(); + } + + virtual void TearDown() + { + delete object; + } +}; + +TEST_F(Test_LoRaWANStack, constructor) +{ + EXPECT_TRUE(object); +} + +TEST_F(Test_LoRaWANStack, bind_phy_and_radio_driver) +{ + my_radio radio; + my_LoRaPHY phy; + object->bind_phy_and_radio_driver(radio, phy); +} + +TEST_F(Test_LoRaWANStack, initialize_mac_layer) +{ + EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->initialize_mac_layer(NULL)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + //Visit callback + if (LoRaMac_stub::_scheduling_failure_handler) { + LoRaMac_stub::_scheduling_failure_handler.call(); + } +} + +void events_cb(lorawan_event_t ev) +{ + +} + +void lc_resp(uint8_t a, uint8_t b) +{ + +} + +uint8_t batt_lvl() +{ + return batt_level; +} + +TEST_F(Test_LoRaWANStack, set_lora_callbacks) +{ + lorawan_app_callbacks_t cb; + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->set_lora_callbacks(&cb)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->set_lora_callbacks(NULL)); + + cb.events = NULL; + EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->set_lora_callbacks(&cb)); + + cb.events = events_cb; + cb.link_check_resp = lc_resp; + cb.battery_level = batt_lvl; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_lora_callbacks(&cb)); +} + +TEST_F(Test_LoRaWANStack, connect) +{ + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->connect()); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_BUSY; + EXPECT_TRUE(LORAWAN_STATUS_BUSY == object->connect()); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->connect()); + + //_ctrl_flags & CONN_IN_PROGRESS_FLAG + EXPECT_TRUE(LORAWAN_STATUS_BUSY == object->connect()); + + my_radio radio; + my_LoRaPHY phy; + object->bind_phy_and_radio_driver(radio, phy); + + struct equeue_event ptr; + equeue_stub.void_ptr = &ptr; + equeue_stub.call_cb_immediately = true; + loramac_mcps_confirm_t conf; + LoRaMac_stub::mcps_conf_ptr = &conf; + radio._ev->tx_done(); + + loramac_mcps_indication_t ind; + LoRaMac_stub::mcps_ind_ptr = &ind; + + loramac_mlme_confirm_t mlme; + LoRaMac_stub::mlme_conf_ptr = &mlme; + mlme.pending = true; + mlme.req_type = MLME_JOIN; + mlme.status = LORAMAC_EVENT_INFO_STATUS_OK; + LoRaMac_stub::bool_value = false; + radio._ev->rx_done(NULL, 0, 0, 0); + + //_ctrl_flags & CONNECTED_FLAG + EXPECT_TRUE(LORAWAN_STATUS_ALREADY_CONNECTED == object->connect()); + + //Visit rx_interrupt_handler's first if + radio._ev->rx_done(NULL, 65535, 0, 0); +} + +TEST_F(Test_LoRaWANStack, connect_args) +{ + lorawan_connect_t conn; + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->connect(conn)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + conn.connect_type = lorawan_connect_type_t(8); + EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->connect(conn)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_BUSY; + conn.connect_type = LORAWAN_CONNECTION_OTAA; + EXPECT_TRUE(LORAWAN_STATUS_BUSY == object->connect(conn)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->connect(conn)); + + //_ctrl_flags & CONN_IN_PROGRESS_FLAG + EXPECT_TRUE(LORAWAN_STATUS_BUSY == object->connect(conn)); + + object->shutdown(); + conn.connect_type = LORAWAN_CONNECTION_ABP; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->connect(conn)); + + //_ctrl_flags & CONNECTED_FLAG + EXPECT_TRUE(LORAWAN_STATUS_ALREADY_CONNECTED == object->connect(conn)); +} + +TEST_F(Test_LoRaWANStack, add_channels) +{ + lorawan_channelplan_t plan; + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->add_channels(plan)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->add_channels(plan)); +} + +TEST_F(Test_LoRaWANStack, remove_a_channel) +{ + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->remove_a_channel(1)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->remove_a_channel(1)); +} + +TEST_F(Test_LoRaWANStack, drop_channel_list) +{ + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->drop_channel_list()); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->drop_channel_list()); +} + +TEST_F(Test_LoRaWANStack, get_enabled_channels) +{ + lorawan_channelplan_t plan; + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->get_enabled_channels(plan)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->get_enabled_channels(plan)); +} + +TEST_F(Test_LoRaWANStack, set_confirmed_msg_retry) +{ + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->set_confirmed_msg_retry(1)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->set_confirmed_msg_retry(255)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_confirmed_msg_retry(1)); +} + +TEST_F(Test_LoRaWANStack, set_channel_data_rate) +{ + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->set_channel_data_rate(4)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_channel_data_rate(4)); +} + +TEST_F(Test_LoRaWANStack, enable_adaptive_datarate) +{ + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->enable_adaptive_datarate(false)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->enable_adaptive_datarate(false)); +} + +TEST_F(Test_LoRaWANStack, handle_tx) +{ + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->handle_tx(0, NULL, 0, 0, true, false)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->handle_tx(0, NULL, 0, 0, false, false)); + + lorawan_app_callbacks_t cb; + cb.events = events_cb; + cb.link_check_resp = lc_resp; + cb.battery_level = batt_lvl; + struct equeue_event ptr; + equeue_stub.void_ptr = &ptr; + equeue_stub.call_cb_immediately = true; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_lora_callbacks(&cb)); + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_link_check_request()); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_NO_ACTIVE_SESSIONS == object->handle_tx(0, NULL, 0, 0, true, false)); + + lorawan_connect_t conn; + conn.connect_type = LORAWAN_CONNECTION_ABP; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->connect(conn)); + + LoRaMac_stub::bool_value = false; + EXPECT_TRUE(LORAWAN_STATUS_NO_NETWORK_JOINED == object->handle_tx(0, NULL, 0, 0, true, false)); + + LoRaMac_stub::bool_value = true; + EXPECT_TRUE(LORAWAN_STATUS_WOULD_BLOCK == object->handle_tx(0, NULL, 0, 0, true, false)); + + LoRaMac_stub::bool_false_counter = 1; + LoRaMac_stub::bool_value = true; + //set_application_port fails + EXPECT_TRUE(LORAWAN_STATUS_PORT_INVALID == object->handle_tx(0, NULL, 0, 0, true, false)); + + LoRaMac_stub::bool_false_counter = 1; + LoRaMac_stub::bool_value = true; + //Wrong flags -> LORAWAN_STATUS_PARAMETER_INVALID + EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->handle_tx(1, NULL, 0, 0x04, true, false)); + + LoRaMac_stub::bool_false_counter = 1; + //Actual sending + EXPECT_TRUE(LORAWAN_STATUS_OK == object->handle_tx(1, NULL, 0, 0x08, true, false)); + +} + +TEST_F(Test_LoRaWANStack, handle_rx) +{ + uint8_t port; + int flags; + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->handle_rx(NULL, 0, port, flags, false)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_NO_ACTIVE_SESSIONS == object->handle_rx(NULL, 0, port, flags, false)); + + struct equeue_event ptr; + equeue_stub.void_ptr = &ptr; + equeue_stub.call_cb_immediately = true; + + lorawan_connect_t conn; + conn.connect_type = LORAWAN_CONNECTION_ABP; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->connect(conn)); + EXPECT_TRUE(LORAWAN_STATUS_WOULD_BLOCK == object->handle_rx(NULL, 0, port, flags, false)); + + //Prepare ready for receive state + lorawan_app_callbacks_t cb; + cb.events = events_cb; + cb.link_check_resp = lc_resp; + cb.battery_level = batt_lvl; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_lora_callbacks(&cb)); + + my_radio radio; + my_LoRaPHY phy; + object->bind_phy_and_radio_driver(radio, phy); + + loramac_mcps_confirm_t conf; + conf.status = LORAMAC_EVENT_INFO_STATUS_OK; + LoRaMac_stub::mcps_conf_ptr = &conf; + radio._ev->tx_done(); + + loramac_mcps_indication_t ind; + ind.status = LORAMAC_EVENT_INFO_STATUS_OK; + LoRaMac_stub::mcps_ind_ptr = &ind; + + loramac_mlme_confirm_t mlme; + LoRaMac_stub::mlme_conf_ptr = &mlme; + mlme.pending = false; + mlme.req_type = MLME_JOIN; + mlme.status = LORAMAC_EVENT_INFO_STATUS_OK; + LoRaMac_stub::bool_value = true; + conf.req_type = MCPS_PROPRIETARY; + + ind.pending = true; + LoRaMac_stub::dev_class_value = CLASS_A; + + loramac_mlme_indication_t mlme_ind; + mlme_ind.pending = false; + LoRaMac_stub::mlme_ind_ptr = &mlme_ind; + + uint8_t ind_buf[150]; + for (int i = 0; i < 110; i++) { + ind_buf[i] = i; + } + ind.buffer = ind_buf; + ind.buffer_size = 150; + ind.type = MCPS_UNCONFIRMED; + radio._ev->rx_done(NULL, 0, 0, 0); + + //data == NULL || LENGTH == 0 (2 cases) + EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->handle_rx(NULL, 0, port, flags, false)); + uint8_t data[50]; + EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->handle_rx(data, 0, port, flags, false)); + + //validate_params returns Would block + port = 43; + EXPECT_TRUE(LORAWAN_STATUS_WOULD_BLOCK == object->handle_rx(data, 50, port, flags, true)); + + ind.type = MCPS_CONFIRMED; + radio._ev->rx_done(NULL, 0, 0, 0); + EXPECT_TRUE(LORAWAN_STATUS_WOULD_BLOCK == object->handle_rx(data, 50, port, flags, true)); + //Call again to visit send_automatic_uplink_message error case + LoRaMac_stub::bool_true_counter = 1; + ind.type = MCPS_CONFIRMED; + ind.status = LORAMAC_EVENT_INFO_STATUS_ERROR; + LoRaMac_stub::bool_value = false; + radio._ev->rx_done(NULL, 0, 0, 0); + + ind.status = LORAMAC_EVENT_INFO_STATUS_OK; + + LoRaMac_stub::bool_value = true; + //convert_to_msg_flag cases + ind.fpending_status = true; + ind.type = MCPS_PROPRIETARY; + radio._ev->rx_done(NULL, 0, 0, 0); + EXPECT_TRUE(LORAWAN_STATUS_WOULD_BLOCK == object->handle_rx(data, 50, port, flags, true)); + + ind.type = MCPS_MULTICAST; + radio._ev->rx_done(NULL, 0, 0, 0); + EXPECT_TRUE(LORAWAN_STATUS_WOULD_BLOCK == object->handle_rx(data, 50, port, flags, true)); + + ind.type = MCPS_UNCONFIRMED; + radio._ev->rx_done(NULL, 0, 0, 0); + + //read not complete + EXPECT_TRUE(50 == object->handle_rx(data, 50, port, flags, false)); + EXPECT_EQ(10, data[10]); + + EXPECT_TRUE(50 == object->handle_rx(data, 50, port, flags, false)); + EXPECT_EQ(60, data[10]); + + //read complete + EXPECT_TRUE(50 == object->handle_rx(data, 50, port, flags, false)); + EXPECT_EQ(100, data[0]); + + //read can fit the buffer + for (int i = 0; i < 110; i++) { + ind_buf[i] = i; + } + ind.buffer = ind_buf; + ind.buffer_size = 50; + ind.type = mcps_type_t(66); + radio._ev->rx_done(NULL, 0, 0, 0); + EXPECT_TRUE(50 == object->handle_rx(data, 50, port, flags, false)); + EXPECT_EQ(10, data[10]); +} + +TEST_F(Test_LoRaWANStack, set_link_check_request) +{ + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->set_link_check_request()); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->set_link_check_request()); + + lorawan_app_callbacks_t cb; + cb.events = events_cb; + cb.link_check_resp = lc_resp; + cb.battery_level = batt_lvl; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_lora_callbacks(&cb)); + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_link_check_request()); +} + +TEST_F(Test_LoRaWANStack, remove_link_check_request) +{ + object->remove_link_check_request(); +} + +TEST_F(Test_LoRaWANStack, shutdown) +{ + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->shutdown()); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + EXPECT_TRUE(LORAWAN_STATUS_DEVICE_OFF == object->shutdown()); +} + +TEST_F(Test_LoRaWANStack, set_device_class) +{ + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->set_device_class(CLASS_A)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_UNSUPPORTED == object->set_device_class(CLASS_B)); + + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_device_class(CLASS_A)); +} + +TEST_F(Test_LoRaWANStack, acquire_tx_metadata) +{ + lorawan_tx_metadata data; + memset(&data, 0, sizeof(data)); + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->acquire_tx_metadata(data)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + // stale = true; + EXPECT_TRUE(LORAWAN_STATUS_METADATA_NOT_AVAILABLE == object->acquire_tx_metadata(data)); + + // stale = false; + my_radio radio; + my_LoRaPHY phy; + object->bind_phy_and_radio_driver(radio, phy); + + struct equeue_event ptr; + equeue_stub.void_ptr = &ptr; + equeue_stub.call_cb_immediately = true; + loramac_mcps_confirm_t conf; + memset(&conf, 0, sizeof(conf)); + conf.status = LORAMAC_EVENT_INFO_STATUS_OK; + LoRaMac_stub::mcps_conf_ptr = &conf; + radio._ev->tx_done(); + + LoRaMac_stub::slot_value = RX_SLOT_WIN_2; + radio._ev->rx_timeout(); + + EXPECT_TRUE(LORAWAN_STATUS_OK == object->acquire_tx_metadata(data)); +} + +TEST_F(Test_LoRaWANStack, acquire_rx_metadata) +{ + lorawan_rx_metadata data; + memset(&data, 0, sizeof(data)); + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->acquire_rx_metadata(data)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + // stale = true; + EXPECT_TRUE(LORAWAN_STATUS_METADATA_NOT_AVAILABLE == object->acquire_rx_metadata(data)); + + // stale = false; + my_radio radio; + my_LoRaPHY phy; + object->bind_phy_and_radio_driver(radio, phy); + + struct equeue_event ptr; + equeue_stub.void_ptr = &ptr; + equeue_stub.call_cb_immediately = true; + loramac_mcps_confirm_t conf; + memset(&conf, 0, sizeof(conf)); + conf.status = LORAMAC_EVENT_INFO_STATUS_OK; + LoRaMac_stub::mcps_conf_ptr = &conf; + radio._ev->tx_done(); + + loramac_mcps_indication_t ind; + memset(&ind, 0, sizeof(ind)); + ind.status = LORAMAC_EVENT_INFO_STATUS_OK; + LoRaMac_stub::mcps_ind_ptr = &ind; + + loramac_mlme_confirm_t mlme; + mlme.status = LORAMAC_EVENT_INFO_STATUS_OK; + LoRaMac_stub::mlme_conf_ptr = &mlme; + mlme.pending = true; + mlme.req_type = MLME_JOIN; + + //Visit mlme_confirm_handler here also + mlme.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL; + LoRaMac_stub::bool_value = false; + radio._ev->rx_done(NULL, 0, 0, 0); + + mlme.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT; + radio._ev->rx_done(NULL, 0, 0, 0); + + mlme.status = LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT; + LoRaMac_stub::slot_value = RX_SLOT_WIN_2; + radio._ev->rx_done(NULL, 0, 0, 0); + + lorawan_app_callbacks_t cb; + cb.events = events_cb; + cb.link_check_resp = lc_resp; + cb.battery_level = batt_lvl; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_lora_callbacks(&cb)); + mlme.req_type = MLME_LINK_CHECK; + mlme.status = LORAMAC_EVENT_INFO_STATUS_OK; + LoRaMac_stub::bool_true_counter = true; + radio._ev->rx_done(NULL, 0, 0, 0); + + EXPECT_TRUE(LORAWAN_STATUS_OK == object->acquire_rx_metadata(data)); +} + +TEST_F(Test_LoRaWANStack, acquire_backoff_metadata) +{ + int b; + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->acquire_backoff_metadata(b)); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::int_value = 2; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->acquire_backoff_metadata(b)); + + LoRaMac_stub::int_value = 0; + EXPECT_TRUE(LORAWAN_STATUS_METADATA_NOT_AVAILABLE == object->acquire_backoff_metadata(b)); +} + +TEST_F(Test_LoRaWANStack, stop_sending) +{ + EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->stop_sending()); + + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + LoRaMac_stub::status_value = LORAWAN_STATUS_BUSY; + EXPECT_TRUE(LORAWAN_STATUS_BUSY == object->stop_sending()); + + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->stop_sending()); +} + +TEST_F(Test_LoRaWANStack, lock) +{ + object->lock(); +} + +TEST_F(Test_LoRaWANStack, unlock) +{ + object->unlock(); +} + +TEST_F(Test_LoRaWANStack, interrupt_functions) +{ + lorawan_connect_t conn; + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + my_radio radio; + my_LoRaPHY phy; + object->bind_phy_and_radio_driver(radio, phy); + + struct equeue_event ptr; + equeue_stub.void_ptr = &ptr; + equeue_stub.call_cb_immediately = true; + loramac_mcps_confirm_t conf; + LoRaMac_stub::mcps_conf_ptr = &conf; + radio._ev->tx_done(); + + loramac_mcps_indication_t ind; + LoRaMac_stub::mcps_ind_ptr = &ind; + + loramac_mlme_confirm_t mlme; + LoRaMac_stub::mlme_conf_ptr = &mlme; + mlme.pending = true; + mlme.req_type = MLME_JOIN; + mlme.status = LORAMAC_EVENT_INFO_STATUS_OK; + LoRaMac_stub::bool_value = false; + radio._ev->rx_done(NULL, 0, 0, 0); + + radio._ev->rx_done(NULL, 0, 0, 0); + + radio._ev->rx_error(); + LoRaMac_stub::slot_value = RX_SLOT_WIN_2; + radio._ev->rx_error(); + + conf.req_type = MCPS_UNCONFIRMED; + LoRaMac_stub::bool_value = true; + radio._ev->rx_error(); + + conf.req_type = MCPS_CONFIRMED; + radio._ev->rx_error(); + + LoRaMac_stub::bool_value = false; + + LoRaMac_stub::slot_value = RX_SLOT_WIN_1; + radio._ev->rx_timeout(); + + radio._ev->tx_timeout(); + + object->shutdown(); + conn.connect_type = LORAWAN_CONNECTION_OTAA; + object->connect(conn); + LoRaMac_stub::status_value = LORAWAN_STATUS_OK; + object->connect(conn); + radio._ev->tx_timeout(); +} + +TEST_F(Test_LoRaWANStack, process_transmission) +{ + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + lorawan_app_callbacks_t cb; + cb.events = events_cb; + cb.link_check_resp = lc_resp; + cb.battery_level = batt_lvl; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_lora_callbacks(&cb)); + + my_radio radio; + my_LoRaPHY phy; + object->bind_phy_and_radio_driver(radio, phy); + + object->connect(); + + struct equeue_event ptr; + equeue_stub.void_ptr = &ptr; + equeue_stub.call_cb_immediately = true; + loramac_mcps_confirm_t conf; + LoRaMac_stub::mcps_conf_ptr = &conf; + radio._ev->tx_done(); + + loramac_mcps_indication_t ind; + LoRaMac_stub::mcps_ind_ptr = &ind; + + loramac_mlme_confirm_t mlme; + LoRaMac_stub::mlme_conf_ptr = &mlme; + mlme.pending = true; + mlme.req_type = MLME_JOIN; + mlme.status = LORAMAC_EVENT_INFO_STATUS_OK; + LoRaMac_stub::bool_value = false; + radio._ev->rx_done(NULL, 0, 0, 0); + + LoRaMac_stub::bool_value = true; + conf.req_type = MCPS_PROPRIETARY; + LoRaMac_stub::bool_false_counter = 1; + LoRaMac_stub::dev_class_value = CLASS_A; + object->handle_tx(1, NULL, 0, MSG_UNCONFIRMED_FLAG, true, false); + radio._ev->tx_done(); + + LoRaMac_stub::bool_false_counter = 1; + LoRaMac_stub::dev_class_value = CLASS_A; + object->handle_tx(1, NULL, 0, MSG_UNCONFIRMED_FLAG, true, false); + radio._ev->tx_done(); + + LoRaMac_stub::bool_false_counter = 1; + LoRaMac_stub::dev_class_value = CLASS_C; + object->handle_tx(1, NULL, 0, MSG_UNCONFIRMED_FLAG, true, false); + radio._ev->tx_done(); + + LoRaMac_stub::bool_false_counter = 1; + conf.req_type = MCPS_CONFIRMED; + object->handle_tx(1, NULL, 0, MSG_UNCONFIRMED_FLAG, true, false); + radio._ev->tx_done(); +} + +TEST_F(Test_LoRaWANStack, process_reception) +{ + EventQueue queue; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue)); + + //Prepare ready for receive state + lorawan_app_callbacks_t cb; + cb.events = events_cb; + cb.link_check_resp = lc_resp; + cb.battery_level = batt_lvl; + EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_lora_callbacks(&cb)); + + my_radio radio; + my_LoRaPHY phy; + object->bind_phy_and_radio_driver(radio, phy); + + struct equeue_event ptr; + equeue_stub.void_ptr = &ptr; + equeue_stub.call_cb_immediately = true; + loramac_mcps_confirm_t conf; + memset(&conf, 0, sizeof(&conf)); + LoRaMac_stub::mcps_conf_ptr = &conf; + radio._ev->tx_done(); + + loramac_mcps_indication_t ind; + memset(&ind, 0, sizeof(ind)); + LoRaMac_stub::mcps_ind_ptr = &ind; + + loramac_mlme_confirm_t mlme; + LoRaMac_stub::mlme_conf_ptr = &mlme; + mlme.pending = false; + mlme.req_type = MLME_JOIN; + mlme.status = LORAMAC_EVENT_INFO_STATUS_OK; + LoRaMac_stub::bool_value = true; + conf.req_type = MCPS_PROPRIETARY; + + ind.pending = true; + LoRaMac_stub::dev_class_value = CLASS_C; + + loramac_mlme_indication_t mlme_ind; + mlme_ind.pending = false; + LoRaMac_stub::mlme_ind_ptr = &mlme_ind; + + uint8_t ind_buf[150]; + for (int i = 0; i < 110; i++) { + ind_buf[i] = i; + } + ind.buffer = ind_buf; + ind.buffer_size = 150; + + //_loramac.get_mcps_confirmation()->req_type == MCPS_CONFIRMED + conf.req_type = MCPS_CONFIRMED; + conf.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT; + radio._ev->rx_done(NULL, 0, 0, 0); + + ind.is_ack_recvd = false; + LoRaMac_stub::bool_true_counter = 1; + LoRaMac_stub::bool_value = false; + LoRaMac_stub::slot_value = RX_SLOT_WIN_2; + conf.status = LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR; + radio._ev->rx_done(NULL, 0, 0, 0); + + conf.req_type = MCPS_UNCONFIRMED; + LoRaMac_stub::dev_class_value = CLASS_A; + LoRaMac_stub::bool_true_counter++; + mlme_ind.pending = true; + mlme_ind.indication_type = MLME_SCHEDULE_UPLINK; + conf.status = LORAMAC_EVENT_INFO_STATUS_ERROR; + radio._ev->rx_done(NULL, 0, 0, 0); + + ind.is_ack_recvd = true; + conf.req_type = MCPS_CONFIRMED; + conf.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT; + radio._ev->rx_done(NULL, 0, 0, 0); +} + diff --git a/UNITTESTS/features/lorawan/lorawanstack/unittest.cmake b/UNITTESTS/features/lorawan/lorawanstack/unittest.cmake new file mode 100644 index 0000000000..8c97d36268 --- /dev/null +++ b/UNITTESTS/features/lorawan/lorawanstack/unittest.cmake @@ -0,0 +1,56 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaWANStack") + +# Source files +set(unittest-sources + ../features/lorawan/LoRaWANStack.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/lorawanstack/Test_LoRaWANStack.cpp + stubs/LoRaPHY_stub.cpp + stubs/LoRaMac_stub.cpp + stubs/mbed_assert_stub.c + stubs/LoRaMacCrypto_stub.cpp + stubs/LoRaMacChannelPlan_stub.cpp + stubs/LoRaWANTimer_stub.cpp + stubs/LoRaMacCommand_stub.cpp + stubs/EventQueue_stub.cpp + stubs/equeue_stub.c + +) + +# defines +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_OVER_THE_AIR_ACTIVATION=true -DMBED_CONF_LORA_DEVICE_EUI=\"{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}\"") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_OVER_THE_AIR_ACTIVATION=true -DMBED_CONF_LORA_DEVICE_EUI=\"{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}\"") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE=true") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE=true") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_APPLICATION_EUI=\"{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}\" -DMBED_CONF_LORA_APPLICATION_KEY=\"{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}\"") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_APPLICATION_EUI=\"{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}\" -DMBED_CONF_LORA_APPLICATION_KEY=\"{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}\"") + diff --git a/UNITTESTS/features/lorawan/lorawantimer/Test_LoRaWANTimer.cpp b/UNITTESTS/features/lorawan/lorawantimer/Test_LoRaWANTimer.cpp new file mode 100644 index 0000000000..3389de828b --- /dev/null +++ b/UNITTESTS/features/lorawan/lorawantimer/Test_LoRaWANTimer.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "LoRaWANTimer.h" + +using namespace events; + +class Test_LoRaWANTimer : public testing::Test { +protected: + LoRaWANTimeHandler *object; + EventQueue *queue; + + virtual void SetUp() + { + queue = new EventQueue(3, NULL); + object = new LoRaWANTimeHandler(); + object->activate_timer_subsystem(queue); + } + + virtual void TearDown() + { + delete object; + delete queue; + } +}; + +TEST_F(Test_LoRaWANTimer, constructor) +{ + EXPECT_TRUE(object); +} + +TEST_F(Test_LoRaWANTimer, get_current_time) +{ + lorawan_time_t tt = object->get_current_time(); + EXPECT_TRUE(0 == tt); +} + +TEST_F(Test_LoRaWANTimer, get_elapsed_time) +{ + lorawan_time_t tt = object->get_elapsed_time(0); + EXPECT_TRUE(0 == tt); +} + +void my_callback() +{ +} + +TEST_F(Test_LoRaWANTimer, init) +{ + timer_event_t ev; + memset(&ev, 0, sizeof(ev)); + object->init(ev, my_callback); +} + +TEST_F(Test_LoRaWANTimer, start) +{ + timer_event_t ev; + memset(&ev, 0, sizeof(ev)); + object->start(ev, 10); +} + +TEST_F(Test_LoRaWANTimer, stop) +{ + timer_event_t ev; + memset(&ev, 0, sizeof(ev)); + ev.timer_id = 4; + object->stop(ev); + EXPECT_TRUE(ev.timer_id == 0); +} + + + diff --git a/UNITTESTS/features/lorawan/lorawantimer/unittest.cmake b/UNITTESTS/features/lorawan/lorawantimer/unittest.cmake new file mode 100644 index 0000000000..48764961fc --- /dev/null +++ b/UNITTESTS/features/lorawan/lorawantimer/unittest.cmake @@ -0,0 +1,39 @@ +#[[ + * Copyright (c) 2018, 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. +]] + +# Unit test suite name +set(TEST_SUITE_NAME "lorawan_LoRaWANTimer") + +# Source files +set(unittest-sources + ../features/lorawan/system/LoRaWANTimer.cpp +) + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + target_h + ../features/lorawan/system +) + +# Test & stub files +set(unittest-test-sources + features/lorawan/lorawantimer/Test_LoRaWANTimer.cpp + stubs/EventQueue_stub.cpp + stubs/mbed_assert_stub.c + stubs/equeue_stub.c +) + diff --git a/UNITTESTS/features/netsocket/EthernetInterface/test_EthernetInterface.cpp b/UNITTESTS/features/netsocket/EthernetInterface/test_EthernetInterface.cpp new file mode 100644 index 0000000000..603b1ef3e4 --- /dev/null +++ b/UNITTESTS/features/netsocket/EthernetInterface/test_EthernetInterface.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "features/netsocket/EthernetInterface.h" +#include + +class MockEMAC : public EMAC { +public: + MOCK_METHOD0(power_up, bool()); + MOCK_METHOD0(power_down, void()); + MOCK_CONST_METHOD0(get_mtu_size, uint32_t()); + MOCK_CONST_METHOD0(get_align_preference, uint32_t()); + MOCK_CONST_METHOD2(get_ifname, void(char *name, uint8_t size)); + MOCK_CONST_METHOD0(get_hwaddr_size, uint8_t()); + MOCK_CONST_METHOD1(get_hwaddr, bool(uint8_t *addr)); + MOCK_METHOD1(set_hwaddr, void(const uint8_t *)); + MOCK_METHOD1(link_out, bool(emac_mem_buf_t *buf)); + MOCK_METHOD1(set_link_input_cb, void(emac_link_input_cb_t input_cb)); + MOCK_METHOD1(set_link_state_cb, void(emac_link_state_change_cb_t state_cb)); + MOCK_METHOD1(add_multicast_group, void(const uint8_t *address)); + MOCK_METHOD1(remove_multicast_group, void(const uint8_t *address)); + MOCK_METHOD1(set_all_multicast, void(bool all)); + MOCK_METHOD1(set_memory_manager, void(EMACMemoryManager &mem_mngr)); + + static MockEMAC &get_instance() + { + static MockEMAC emacMock1; + return emacMock1; + } +}; + +MBED_WEAK EMAC &EMAC::get_default_instance() +{ + return MockEMAC::get_instance(); +} + +class EmacNetworkStackMock : public OnboardNetworkStack { +public: + MOCK_METHOD3(gethostbyname, nsapi_error_t(const char *host, SocketAddress *address, nsapi_version_t version)); + MOCK_METHOD1(add_dns_server, nsapi_error_t(const SocketAddress &address)); + MOCK_METHOD2(call_in, nsapi_error_t(int delay, mbed::Callback func)); + MOCK_METHOD2(socket_open, nsapi_error_t(nsapi_socket_t *handle, nsapi_protocol_t proto)); + MOCK_METHOD1(socket_close, nsapi_error_t(nsapi_socket_t handle)); + MOCK_METHOD2(socket_bind, nsapi_error_t(nsapi_socket_t handle, const SocketAddress &address)); + MOCK_METHOD2(socket_listen, nsapi_error_t(nsapi_socket_t handle, int backlog)); + MOCK_METHOD2(socket_connect, nsapi_error_t(nsapi_socket_t handle, const SocketAddress &address)); + MOCK_METHOD3(socket_accept, nsapi_error_t(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address)); + MOCK_METHOD3(socket_send, nsapi_error_t(nsapi_socket_t handle, const void *data, nsapi_size_t size)); + MOCK_METHOD3(socket_recv, nsapi_error_t(nsapi_socket_t handle, void *data, nsapi_size_t size)); + MOCK_METHOD4(socket_sendto, nsapi_error_t(nsapi_socket_t handle, const SocketAddress &address, const void *data, nsapi_size_t size)); + MOCK_METHOD4(socket_recvfrom, nsapi_error_t(nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size)); + MOCK_METHOD5(setsockopt, nsapi_error_t(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen)); + MOCK_METHOD5(getsockopt, nsapi_error_t(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned *optlen)); + MOCK_METHOD3(socket_attach, void(nsapi_socket_t handle, void (*callback)(void *), void *data)); + MOCK_METHOD3(add_ethernet_interface, nsapi_error_t(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out)); + + static EmacNetworkStackMock &get_instance() + { + static EmacNetworkStackMock stackMock1; + return stackMock1; + } + + class InterfaceMock : public OnboardNetworkStack::Interface { + public: + + static InterfaceMock &get_instance() + { + static InterfaceMock test_interface; + return test_interface; + } + MOCK_METHOD6(bringup, nsapi_error_t(bool dhcp, const char *ip, + const char *netmask, const char *gw, + nsapi_ip_stack_t stack, + bool blocking + )); + MOCK_METHOD0(bringdown, nsapi_error_t()); + MOCK_METHOD1(attach, void(mbed::Callback status_cb)); + MOCK_CONST_METHOD0(get_connection_status, nsapi_connection_status_t()); + MOCK_METHOD2(get_mac_address, char *(char *buf, nsapi_size_t buflen)); + MOCK_METHOD2(get_ip_address, char *(char *buf, nsapi_size_t buflen)); + MOCK_METHOD2(get_netmask, char *(char *buf, nsapi_size_t buflen)); + MOCK_METHOD2(get_gateway, char *(char *buf, nsapi_size_t buflen)); + }; +}; + +OnboardNetworkStack &OnboardNetworkStack::get_default_instance() +{ + return EmacNetworkStackMock::get_instance(); +} + +// Implementaion in in NetworkInterfaceDefaults.cpp +MBED_WEAK EthInterface *EthInterface::get_default_instance() +{ + return get_target_default_instance(); +} + +using ::testing::_; +using ::testing::Return; +using ::testing::ReturnArg; +using ::testing::SaveArg; +using ::testing::SaveArgPointee; +using ::testing::SetArrayArgument; +using ::testing::SetArgPointee; +using ::testing::SetArgReferee; + +class TestEthernetInterface: public testing::Test { +protected: + EthernetInterface *iface; + EmacNetworkStackMock *stackMock; + MockEMAC *emacMock; + EmacNetworkStackMock::InterfaceMock *netStackIface; + virtual void SetUp() + { + stackMock = &EmacNetworkStackMock::get_instance(); + emacMock = &MockEMAC::get_instance(); + netStackIface = &EmacNetworkStackMock::InterfaceMock::get_instance(); + iface = new EthernetInterface(MockEMAC::get_instance(), EmacNetworkStackMock::get_instance()); + } + + virtual void TearDown() + { + // Do not delete the mocks pointers, as they point to statically allocated singletons. + delete iface; + } + + /* Enclose the heavily-used connection procedure to improve code redability */ + void doConnect(bool dhcp = true, bool blocking = true) + { + EXPECT_CALL(*stackMock, add_ethernet_interface(testing::Ref(*emacMock), true, _)) + .Times(1) + .WillOnce(DoAll(SetArgPointee<2>(netStackIface), Return(NSAPI_ERROR_OK))); + EXPECT_CALL(*netStackIface, attach(_)) + .Times(1) + .RetiresOnSaturation();; + EXPECT_CALL(*netStackIface, bringup(dhcp, NULL, NULL, NULL, DEFAULT_STACK, blocking)) + .Times(1) + .WillOnce(Return(NSAPI_ERROR_OK)); + EXPECT_EQ(NSAPI_ERROR_OK, iface->connect()); + } + + static void cb(nsapi_event_t ev, intptr_t ptr) + { + + } +}; + +TEST_F(TestEthernetInterface, constructor_default) +{ + EXPECT_TRUE(iface); +} + +TEST_F(TestEthernetInterface, constructor_getter) +{ + EthInterface *eth = EthInterface::get_default_instance(); +} + + + +TEST_F(TestEthernetInterface, connect) +{ + doConnect(); +} + +TEST_F(TestEthernetInterface, connect_failure) +{ + EXPECT_CALL(*stackMock, add_ethernet_interface(testing::Ref(*emacMock), true, _)) + .Times(1) + .WillOnce(DoAll(SetArgPointee<2>(netStackIface), Return(NSAPI_ERROR_NO_MEMORY))); + EXPECT_EQ(NSAPI_ERROR_NO_MEMORY, iface->connect()); +} + +TEST_F(TestEthernetInterface, disconnect_without_connecting) +{ + EXPECT_EQ(NSAPI_ERROR_NO_CONNECTION, iface->disconnect()); +} + +TEST_F(TestEthernetInterface, disconnect) +{ + doConnect(); + + EXPECT_CALL(*netStackIface, bringdown()) + .Times(1) + .WillOnce(Return(NSAPI_ERROR_OK)); + EXPECT_EQ(NSAPI_ERROR_OK, iface->disconnect()); +} + +TEST_F(TestEthernetInterface, set_network) +{ + char ipAddress[NSAPI_IPv4_SIZE] = "127.0.0.1"; + char netmask[NSAPI_IPv4_SIZE] = "255.255.0.0"; + char gateway[NSAPI_IPv4_SIZE] = "127.0.0.2"; + + const char *ipAddressArg; + const char *netmaskArg; + const char *gatewayArg; + + EXPECT_EQ(0, iface->get_ip_address()); + EXPECT_EQ(0, iface->get_netmask()); + EXPECT_EQ(0, iface->get_gateway()); + + // Set the network data + EXPECT_EQ(NSAPI_ERROR_OK, iface->set_network(ipAddress, netmask, gateway)); + + // Now the bringup should have different arguments. We can't use doConnect method. + EXPECT_CALL(*stackMock, add_ethernet_interface(testing::Ref(*emacMock), true, _)) + .Times(1) + .WillOnce(DoAll(SetArgPointee<2>(netStackIface), Return(NSAPI_ERROR_OK))); + EXPECT_CALL(*netStackIface, attach(_)) + .Times(1) + .RetiresOnSaturation(); + // Do not put the expected char * arguments, as they are pointers and would not match + EXPECT_CALL(*netStackIface, bringup(false, _, _, _, DEFAULT_STACK, true)) + .Times(1) + .WillOnce(DoAll(SaveArg<1>(&ipAddressArg), + SaveArg<2>(&netmaskArg), + SaveArg<3>(&gatewayArg), + Return(NSAPI_ERROR_OK))); + EXPECT_EQ(NSAPI_ERROR_OK, iface->connect()); + // Check the contents of the stored pointer arguments. + EXPECT_TRUE(0 == strcmp(ipAddress, ipAddressArg)); + EXPECT_TRUE(0 == strcmp(netmask, netmaskArg)); + EXPECT_TRUE(0 == strcmp(gateway, gatewayArg)); + + // Testing the getters makes sense now. + EXPECT_CALL(*netStackIface, get_ip_address(_, _)) + .Times(1) + .WillOnce(DoAll(SetArgPointee<0>(*ipAddress), Return(ipAddress))); + EXPECT_EQ(std::string(ipAddress), std::string(iface->get_ip_address())); + + EXPECT_CALL(*netStackIface, get_netmask(_, _)) + .Times(1) + .WillOnce(DoAll(SetArgPointee<0>(*netmask), Return(netmask))); + EXPECT_EQ(std::string(netmask), std::string(iface->get_netmask())); + + EXPECT_CALL(*netStackIface, get_gateway(_, _)) + .Times(1) + .WillOnce(DoAll(SetArgPointee<0>(*gateway), Return(gateway))); + EXPECT_EQ(std::string(gateway), std::string(iface->get_gateway())); +} + +TEST_F(TestEthernetInterface, get_connection_status) +{ + EXPECT_EQ(NSAPI_STATUS_DISCONNECTED, iface->get_connection_status()); + + doConnect(); + + EXPECT_CALL(*netStackIface, get_connection_status()) + .Times(1) + .WillOnce(Return(NSAPI_STATUS_LOCAL_UP)); + EXPECT_EQ(NSAPI_STATUS_LOCAL_UP, iface->get_connection_status()); +} + +TEST_F(TestEthernetInterface, attach) +{ + doConnect(); + EXPECT_CALL(*netStackIface, attach(_)) // TODO: check that the correct function is passed. + .Times(1); + iface->attach(cb); +} + +TEST_F(TestEthernetInterface, set_dhcp) +{ + EXPECT_EQ(NSAPI_ERROR_OK, iface->set_dhcp(false)); + doConnect(false, true); +} + +TEST_F(TestEthernetInterface, set_blocking) +{ + EXPECT_EQ(NSAPI_ERROR_OK, iface->set_blocking(false)); + doConnect(true, false); +} diff --git a/UNITTESTS/features/netsocket/EthernetInterface/unittest.cmake b/UNITTESTS/features/netsocket/EthernetInterface/unittest.cmake new file mode 100644 index 0000000000..78a9f1f943 --- /dev/null +++ b/UNITTESTS/features/netsocket/EthernetInterface/unittest.cmake @@ -0,0 +1,36 @@ + +#################### +# UNIT TESTS +#################### + +# Unit test suite name +set(TEST_SUITE_NAME "features_netsocket_EthernetInterface") + +# Source files +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/netsocket/EthernetInterface.cpp + ../features/netsocket/EMACInterface.cpp + ../features/netsocket/NetworkInterface.cpp + ../features/netsocket/NetworkStack.cpp + ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c + ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c +) + +# Test files +set(unittest-test-sources + features/netsocket/EthernetInterface/test_EthernetInterface.cpp + stubs/Mutex_stub.cpp + stubs/mbed_assert_stub.c + stubs/equeue_stub.c + stubs/EventQueue_stub.cpp + stubs/mbed_shared_queues_stub.cpp + stubs/nsapi_dns_stub.cpp + stubs/EventFlags_stub.cpp + stubs/stoip4_stub.c + stubs/ip4tos_stub.c + stubs/NetworkStack_stub.cpp +) diff --git a/UNITTESTS/features/netsocket/InternetSocket/test_InternetSocket.cpp b/UNITTESTS/features/netsocket/InternetSocket/test_InternetSocket.cpp index 3b499fef42..61a78dcfc6 100644 --- a/UNITTESTS/features/netsocket/InternetSocket/test_InternetSocket.cpp +++ b/UNITTESTS/features/netsocket/InternetSocket/test_InternetSocket.cpp @@ -58,12 +58,30 @@ public: } // Testing functions - void add_reader (void) { _readers++;} - void rem_reader (void) { _readers--;} - void add_writer (void) { _writers++;} - void rem_writer (void) { _writers--;} - void add_pending (void) { _pending++;} - void rem_pending (void) { _pending--;} + void add_reader(void) + { + _readers++; + } + void rem_reader(void) + { + _readers--; + } + void add_writer(void) + { + _writers++; + } + void rem_writer(void) + { + _writers--; + } + void add_pending(void) + { + _pending++; + } + void rem_pending(void) + { + _pending--; + } protected: virtual nsapi_protocol_t get_proto() @@ -133,7 +151,7 @@ TEST_F(TestInternetSocket, close) TEST_F(TestInternetSocket, close_no_open) { stack.return_value = NSAPI_ERROR_OK; - EXPECT_EQ(socket->close(), NSAPI_ERROR_OK); + EXPECT_EQ(socket->close(), NSAPI_ERROR_NO_SOCKET); } TEST_F(TestInternetSocket, close_during_read) @@ -204,6 +222,7 @@ TEST_F(TestInternetSocket, getsockopt) TEST_F(TestInternetSocket, sigio) { callback_is_called = false; + socket->open((NetworkStack *)&stack); socket->sigio(mbed::callback(my_callback)); socket->close(); // Trigger event; EXPECT_EQ(callback_is_called, true); diff --git a/UNITTESTS/features/netsocket/InternetSocket/unittest.cmake b/UNITTESTS/features/netsocket/InternetSocket/unittest.cmake index 3d4297e530..f2f89e1136 100644 --- a/UNITTESTS/features/netsocket/InternetSocket/unittest.cmake +++ b/UNITTESTS/features/netsocket/InternetSocket/unittest.cmake @@ -8,7 +8,10 @@ set(unittest-sources ../features/netsocket/NetworkStack.cpp ../features/netsocket/InternetSocket.cpp ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c ) set(unittest-test-sources diff --git a/UNITTESTS/features/netsocket/NetworkInterface/unittest.cmake b/UNITTESTS/features/netsocket/NetworkInterface/unittest.cmake index 37ea5dc0bf..336e9b106f 100644 --- a/UNITTESTS/features/netsocket/NetworkInterface/unittest.cmake +++ b/UNITTESTS/features/netsocket/NetworkInterface/unittest.cmake @@ -9,7 +9,10 @@ set(unittest-sources ../features/netsocket/NetworkStack.cpp ../features/netsocket/NetworkInterface.cpp ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c ) # Test files diff --git a/UNITTESTS/features/netsocket/NetworkStack/test_NetworkStack.cpp b/UNITTESTS/features/netsocket/NetworkStack/test_NetworkStack.cpp index 2b18f2b466..236b0745dc 100644 --- a/UNITTESTS/features/netsocket/NetworkStack/test_NetworkStack.cpp +++ b/UNITTESTS/features/netsocket/NetworkStack/test_NetworkStack.cpp @@ -21,6 +21,8 @@ #include "events/EventQueue.h" #include +#include "equeue_stub.h" + // Control nsapi stub return value. See stubs/nsapi_dns_stub.cpp extern nsapi_error_t nsapi_stub_return_value; @@ -70,27 +72,27 @@ class NetworkStackChild : public NetworkStack { return NSAPI_ERROR_OK; } virtual nsapi_error_t socket_accept(nsapi_socket_t server, - nsapi_socket_t *handle, SocketAddress *address = 0) + nsapi_socket_t *handle, SocketAddress *address = 0) { return NSAPI_ERROR_OK; } virtual nsapi_size_or_error_t socket_send(nsapi_socket_t handle, - const void *data, nsapi_size_t size) + const void *data, nsapi_size_t size) { return NSAPI_ERROR_OK; } virtual nsapi_size_or_error_t socket_recv(nsapi_socket_t handle, - void *data, nsapi_size_t size) + void *data, nsapi_size_t size) { return NSAPI_ERROR_OK; } virtual nsapi_size_or_error_t socket_sendto(nsapi_socket_t handle, const SocketAddress &address, - const void *data, nsapi_size_t size) + const void *data, nsapi_size_t size) { return NSAPI_ERROR_OK; } virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, - void *buffer, nsapi_size_t size) + void *buffer, nsapi_size_t size) { return NSAPI_ERROR_OK; } @@ -123,8 +125,7 @@ protected: virtual void TearDown() { delete stack; - if (mbed::mbed_shared_queue_stub) - { + if (mbed::mbed_shared_queue_stub) { delete mbed::mbed_shared_queue_stub; mbed::mbed_shared_queue_stub = 0; } @@ -143,7 +144,7 @@ TEST_F(TestNetworkStack, constructor) TEST_F(TestNetworkStack, get_ip_address_default) { - EXPECT_EQ(stack->NetworkStack::get_ip_address(), (char*)NULL); + EXPECT_EQ(stack->NetworkStack::get_ip_address(), (char *)NULL); } /* gethostbyname */ @@ -186,6 +187,9 @@ TEST_F(TestNetworkStack, gethostbyname_async_delay) SocketAddress a; stack->ip_address = std::string("127.0.0.1"); SetUpQueue(); + struct equeue_event ptr; + equeue_stub.void_ptr = &ptr; + equeue_stub.call_cb_immediately = true; EXPECT_EQ(stack->gethostbyname_async("localhost", mbed::callback(my_callback), NSAPI_UNSPEC), NSAPI_ERROR_DNS_FAILURE); EXPECT_EQ(callin_callback(1, mbed::callback(noarg_callback)), NSAPI_ERROR_OK); EXPECT_TRUE(noarg_callback_is_called); @@ -197,6 +201,9 @@ TEST_F(TestNetworkStack, gethostbyname_async) SocketAddress a; stack->ip_address = std::string("127.0.0.1"); SetUpQueue(); + struct equeue_event ptr; + equeue_stub.void_ptr = &ptr; + equeue_stub.call_cb_immediately = true; EXPECT_EQ(stack->gethostbyname_async("localhost", mbed::callback(my_callback), NSAPI_UNSPEC), NSAPI_ERROR_DNS_FAILURE); EXPECT_EQ(callin_callback(0, mbed::callback(noarg_callback)), NSAPI_ERROR_OK); EXPECT_TRUE(noarg_callback_is_called); @@ -223,11 +230,11 @@ TEST_F(TestNetworkStack, gethostbyname_async_empty_host) TEST_F(TestNetworkStack, getstackopt) { - EXPECT_EQ(stack->getstackopt(0,0,0,0), NSAPI_ERROR_UNSUPPORTED); + EXPECT_EQ(stack->getstackopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED); } TEST_F(TestNetworkStack, setstackopt) { - EXPECT_EQ(stack->setstackopt(0,0,0,0), NSAPI_ERROR_UNSUPPORTED); + EXPECT_EQ(stack->setstackopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED); } diff --git a/UNITTESTS/features/netsocket/NetworkStack/unittest.cmake b/UNITTESTS/features/netsocket/NetworkStack/unittest.cmake index f17d68852e..91ea42d5a2 100644 --- a/UNITTESTS/features/netsocket/NetworkStack/unittest.cmake +++ b/UNITTESTS/features/netsocket/NetworkStack/unittest.cmake @@ -12,7 +12,10 @@ set(unittest-sources ../features/netsocket/NetworkStack.cpp ../features/netsocket/NetworkInterface.cpp ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c ) # Test files diff --git a/UNITTESTS/features/netsocket/SocketAddress/test_SocketAddress.cpp b/UNITTESTS/features/netsocket/SocketAddress/test_SocketAddress.cpp new file mode 100644 index 0000000000..d9abf4f656 --- /dev/null +++ b/UNITTESTS/features/netsocket/SocketAddress/test_SocketAddress.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "features/netsocket/SocketAddress.h" +#include + +class TestSocketAddress: public testing::Test { +protected: + SocketAddress *address; + virtual void SetUp() + { + address = new SocketAddress; + } + + virtual void TearDown() + { + delete address; + } + void isEqual(SocketAddress addr1, SocketAddress addr2) + { + EXPECT_EQ(std::string(addr1.get_ip_address()), std::string(addr2.get_ip_address())); + EXPECT_EQ(addr1.get_addr().version, addr2.get_addr().version); + EXPECT_TRUE(0 == memcmp(addr1.get_addr().bytes, addr2.get_addr().bytes, NSAPI_IPv4_BYTES)); + EXPECT_TRUE(0 == memcmp(addr1.get_ip_bytes(), addr2.get_ip_bytes(), NSAPI_IP_BYTES)); + EXPECT_EQ(addr1.get_ip_version(), addr2.get_ip_version()); + EXPECT_EQ(addr1.get_port(), addr2.get_port()); + } +}; + +TEST_F(TestSocketAddress, constructor_default) +{ + EXPECT_TRUE(address); + EXPECT_EQ(NULL, address->get_ip_address()); + EXPECT_EQ(0, address->get_port()); + EXPECT_EQ(NSAPI_UNSPEC, address->get_ip_version()); +} + +TEST_F(TestSocketAddress, constructor_address_ip4) +{ + SocketAddress addr("127.0.0.1", 80); + EXPECT_EQ(std::string("127.0.0.1"), std::string(addr.get_ip_address())); + EXPECT_EQ(80, addr.get_port()); + EXPECT_EQ(NSAPI_IPv4, addr.get_ip_version()); +} + +TEST_F(TestSocketAddress, constructor_address_ip6) +{ + SocketAddress addr("1234:5678:9abc:def0:1234:5678::def0", 80); + EXPECT_EQ(80, addr.get_port()); + EXPECT_EQ(NSAPI_IPv6, addr.get_ip_version()); + // Note that a missing zero is added between two neighbouring colons + EXPECT_EQ(std::string("1234:5678:9abc:def0:1234:5678:0:def0"), std::string(addr.get_ip_address())); +} + +TEST_F(TestSocketAddress, constructor_address_ip6_invalid) +{ + SocketAddress addr("zzzz:yyyy:xxxx:def0:1234:5678:9abc:def0", 80); + EXPECT_EQ(80, addr.get_port()); + EXPECT_EQ(NSAPI_UNSPEC, addr.get_ip_version()); + EXPECT_EQ(NULL, addr.get_ip_address()); +} + +TEST_F(TestSocketAddress, constructor_address_bytes_ip4) +{ + uint8_t addrBytes[NSAPI_IP_BYTES] = {127, 0, 0, 2}; + + SocketAddress addr(addrBytes, NSAPI_IPv4, 80); + EXPECT_EQ(std::string("127.0.0.2"), std::string(addr.get_ip_address())); + EXPECT_EQ(80, addr.get_port()); + EXPECT_EQ(NSAPI_IPv4, addr.get_ip_version()); + EXPECT_TRUE(0 == memcmp(addrBytes, static_cast(addr.get_ip_bytes()), sizeof(addrBytes))); +} + +TEST_F(TestSocketAddress, constructor_address_bytes_ip6) +{ + uint8_t addrBytes[NSAPI_IP_BYTES] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + + SocketAddress addr(addrBytes, NSAPI_IPv6, 80); + // the leading zeroes are removed + EXPECT_EQ(std::string("1:203:405:607:809:a0b:c0d:e0f"), std::string(addr.get_ip_address())); + EXPECT_EQ(80, addr.get_port()); + EXPECT_EQ(NSAPI_IPv6, addr.get_ip_version()); + EXPECT_TRUE(0 == memcmp(addrBytes, static_cast(addr.get_ip_bytes()), NSAPI_IP_BYTES)); +} + +TEST_F(TestSocketAddress, constructor_copy) +{ + SocketAddress addr(*address); + EXPECT_EQ(address->get_ip_address(), addr.get_ip_address()); + EXPECT_EQ(address->get_port(), addr.get_port()); + EXPECT_EQ(address->get_ip_version(), addr.get_ip_version()); +} + +TEST_F(TestSocketAddress, assignment_and_equality_operator_ip4) +{ + SocketAddress addr; + address->set_ip_address("127.0.0.2"); + address->set_port(81); + // First verify assignment operator (including return value) using equality operator. + EXPECT_EQ((addr = *address), *address); + // Then check inequality operator + EXPECT_FALSE(addr != *address); + // Now proceed to check that the equality operator really works. + isEqual(addr, *address); +} + +TEST_F(TestSocketAddress, assignment_and_equality_operator_ip6) +{ + SocketAddress addr; + address->set_ip_address("0:0:0:0:0:ffff:7f00:1"); + address->set_port(81); + // First verify assignment operator (including return value) using equality operator. + EXPECT_EQ((addr = *address), *address); + // Then check inequality operator + EXPECT_FALSE(addr != *address); + // Now proceed to check that the equality operator really works. + isEqual(addr, *address); +} + +TEST_F(TestSocketAddress, equality_null_check) +{ + address->set_ip_address("127.0.0.2"); + EXPECT_NE(*address, static_cast(NULL)); +} + +TEST_F(TestSocketAddress, equality_wrong_version) +{ + SocketAddress addr4("127.0.0.1", 80); + SocketAddress addr6("0:0:0:0:0:ffff:7f00:1", 80); // This is converted 127.0.0.1 + EXPECT_NE(addr4, addr6); // But they should still be inequal. +} + +TEST_F(TestSocketAddress, bool_operator_false) +{ + EXPECT_FALSE(*address ? true : false); +} + +TEST_F(TestSocketAddress, bool_operator_ip4_true) +{ + SocketAddress addr("127.0.0.1", 80); + EXPECT_TRUE(addr ? true : false); +} + +TEST_F(TestSocketAddress, bool_operator_ip6_true) +{ + SocketAddress addr("1234:5678:9abc:def0:1234:5678:9abc:def0", 80); + EXPECT_TRUE(addr ? true : false); +} + + + diff --git a/UNITTESTS/features/netsocket/SocketAddress/unittest.cmake b/UNITTESTS/features/netsocket/SocketAddress/unittest.cmake new file mode 100644 index 0000000000..6c4171c23f --- /dev/null +++ b/UNITTESTS/features/netsocket/SocketAddress/unittest.cmake @@ -0,0 +1,22 @@ + +#################### +# UNIT TESTS +#################### + +# Unit test suite name +set(TEST_SUITE_NAME "features_netsocket_SocketAddress") + +# Source files +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c + ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c +) + +# Test files +set(unittest-test-sources + features/netsocket/SocketAddress/test_SocketAddress.cpp +) diff --git a/UNITTESTS/features/netsocket/TCPServer/test_TCPServer.cpp b/UNITTESTS/features/netsocket/TCPServer/test_TCPServer.cpp index c2cf9532fb..d866ea0ab0 100644 --- a/UNITTESTS/features/netsocket/TCPServer/test_TCPServer.cpp +++ b/UNITTESTS/features/netsocket/TCPServer/test_TCPServer.cpp @@ -54,7 +54,7 @@ TEST_F(TestTCPServer, constructor) TEST_F(TestTCPServer, constructor_parameters) { - TCPServer serverParam = TCPServer(dynamic_cast(&stack)); + TCPServer serverParam = TCPServer(dynamic_cast(&stack)); const SocketAddress a("127.0.0.1", 1024); EXPECT_EQ(serverParam.connect(a), NSAPI_ERROR_OK); } diff --git a/UNITTESTS/features/netsocket/TCPServer/unittest.cmake b/UNITTESTS/features/netsocket/TCPServer/unittest.cmake index d0b1e031b1..942d3aade0 100644 --- a/UNITTESTS/features/netsocket/TCPServer/unittest.cmake +++ b/UNITTESTS/features/netsocket/TCPServer/unittest.cmake @@ -13,7 +13,10 @@ set(unittest-sources ../features/netsocket/TCPSocket.cpp ../features/netsocket/TCPServer.cpp ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c ) set(unittest-test-sources diff --git a/UNITTESTS/features/netsocket/TCPSocket/test_TCPSocket.cpp b/UNITTESTS/features/netsocket/TCPSocket/test_TCPSocket.cpp index 16022ca525..abd7cc41eb 100644 --- a/UNITTESTS/features/netsocket/TCPSocket/test_TCPSocket.cpp +++ b/UNITTESTS/features/netsocket/TCPSocket/test_TCPSocket.cpp @@ -62,7 +62,7 @@ TEST_F(TestTCPSocket, constructor) TEST_F(TestTCPSocket, constructor_parameters) { - TCPSocket socketParam = TCPSocket(dynamic_cast(&stack)); + TCPSocket socketParam = TCPSocket(dynamic_cast(&stack)); const SocketAddress a("127.0.0.1", 1024); EXPECT_EQ(socketParam.connect(a), NSAPI_ERROR_OK); } @@ -200,7 +200,7 @@ TEST_F(TestTCPSocket, recv_all_data) TEST_F(TestTCPSocket, recv_less_than_expected) { socket->open((NetworkStack *)&stack); - unsigned int lessThanDataSize = dataSize -1; + unsigned int lessThanDataSize = dataSize - 1; stack.return_values.push_back(lessThanDataSize); EXPECT_EQ(socket->recv(dataBuf, dataSize), lessThanDataSize); } @@ -262,7 +262,7 @@ TEST_F(TestTCPSocket, accept_no_open) { nsapi_error_t error; stack.return_value = NSAPI_ERROR_OK; - EXPECT_EQ(socket->accept(&error), static_cast(NULL)); + EXPECT_EQ(socket->accept(&error), static_cast(NULL)); EXPECT_EQ(error, NSAPI_ERROR_NO_SOCKET); } @@ -271,7 +271,7 @@ TEST_F(TestTCPSocket, accept) nsapi_error_t error; stack.return_value = NSAPI_ERROR_OK; socket->open((NetworkStack *)&stack); - EXPECT_NE(socket->accept(&error), static_cast(NULL)); + EXPECT_NE(socket->accept(&error), static_cast(NULL)); EXPECT_EQ(error, NSAPI_ERROR_OK); } @@ -282,6 +282,6 @@ TEST_F(TestTCPSocket, accept_would_block) stack.return_value = NSAPI_ERROR_WOULD_BLOCK; eventFlagsStubNextRetval.push_back(0); eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop - EXPECT_EQ(socket->accept(&error), static_cast(NULL)); + EXPECT_EQ(socket->accept(&error), static_cast(NULL)); EXPECT_EQ(error, NSAPI_ERROR_WOULD_BLOCK); } diff --git a/UNITTESTS/features/netsocket/TCPSocket/unittest.cmake b/UNITTESTS/features/netsocket/TCPSocket/unittest.cmake index 58367cfede..474a2b158e 100644 --- a/UNITTESTS/features/netsocket/TCPSocket/unittest.cmake +++ b/UNITTESTS/features/netsocket/TCPSocket/unittest.cmake @@ -9,7 +9,10 @@ set(unittest-sources ../features/netsocket/InternetSocket.cpp ../features/netsocket/TCPSocket.cpp ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c ) set(unittest-test-sources diff --git a/UNITTESTS/features/netsocket/UDPSocket/test_UDPSocket.cpp b/UNITTESTS/features/netsocket/UDPSocket/test_UDPSocket.cpp index d631cc7573..f746d010fc 100644 --- a/UNITTESTS/features/netsocket/UDPSocket/test_UDPSocket.cpp +++ b/UNITTESTS/features/netsocket/UDPSocket/test_UDPSocket.cpp @@ -79,7 +79,7 @@ TEST_F(TestUDPSocket, sendto_addr_port) TEST_F(TestUDPSocket, connect) { stack.return_value = NSAPI_ERROR_OK; - const nsapi_addr_t addr = {NSAPI_IPv4, {127,0,0,1} }; + const nsapi_addr_t addr = {NSAPI_IPv4, {127, 0, 0, 1} }; const SocketAddress a(addr, 1024); socket->open((NetworkStack *)&stack); @@ -93,7 +93,7 @@ TEST_F(TestUDPSocket, connect) TEST_F(TestUDPSocket, sendto_timeout) { - const nsapi_addr_t saddr = {NSAPI_IPv4, {127,0,0,1} }; + const nsapi_addr_t saddr = {NSAPI_IPv4, {127, 0, 0, 1} }; const SocketAddress addr(saddr, 1024); socket->open((NetworkStack *)&stack); @@ -127,8 +127,8 @@ TEST_F(TestUDPSocket, recv) TEST_F(TestUDPSocket, recv_address_filtering) { socket->open((NetworkStack *)&stack); - const nsapi_addr_t addr1 = {NSAPI_IPv4, {127,0,0,1} }; - const nsapi_addr_t addr2 = {NSAPI_IPv4, {127,0,0,2} }; + const nsapi_addr_t addr1 = {NSAPI_IPv4, {127, 0, 0, 1} }; + const nsapi_addr_t addr2 = {NSAPI_IPv4, {127, 0, 0, 2} }; SocketAddress a1(addr1, 1024); SocketAddress a2(addr2, 1024); diff --git a/UNITTESTS/features/netsocket/UDPSocket/unittest.cmake b/UNITTESTS/features/netsocket/UDPSocket/unittest.cmake index b57c38e6f4..82d149e086 100644 --- a/UNITTESTS/features/netsocket/UDPSocket/unittest.cmake +++ b/UNITTESTS/features/netsocket/UDPSocket/unittest.cmake @@ -9,7 +9,10 @@ set(unittest-sources ../features/netsocket/InternetSocket.cpp ../features/netsocket/UDPSocket.cpp ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c ) set(unittest-test-sources diff --git a/UNITTESTS/features/netsocket/WiFiAccessPoint/test_WiFiAccessPoint.cpp b/UNITTESTS/features/netsocket/WiFiAccessPoint/test_WiFiAccessPoint.cpp new file mode 100644 index 0000000000..ef27e5e198 --- /dev/null +++ b/UNITTESTS/features/netsocket/WiFiAccessPoint/test_WiFiAccessPoint.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "gtest/gtest.h" +#include "features/netsocket/WiFiAccessPoint.h" +#include + +class TestWiFiAccessPoint : public testing::Test { +protected: + WiFiAccessPoint *ap; + + virtual void SetUp() + { + ap = new WiFiAccessPoint; + } + + virtual void TearDown() + { + delete ap; + } +}; + +TEST_F(TestWiFiAccessPoint, constructor) +{ + EXPECT_TRUE(ap); +} + +TEST_F(TestWiFiAccessPoint, getters_default) +{ + // ssid and bssid return pointers to uninitialized memory - impossible to set expectations. + EXPECT_EQ(0, ap->get_channel()); + EXPECT_EQ(0, ap->get_rssi()); + EXPECT_EQ(NSAPI_SECURITY_NONE, ap->get_security()); +} + +TEST_F(TestWiFiAccessPoint, set_data) +{ + nsapi_wifi_ap_t testAp = { + "mySSID67890123456789012345678901", + {0xd8, 0xc7, 0xc8, 0xcc, 0x43, 0x24}, + NSAPI_SECURITY_WPA2, + 0x64, + 0x02, + }; + WiFiAccessPoint *ap1 = new WiFiAccessPoint(testAp); + EXPECT_EQ(std::string(testAp.ssid), std::string(ap1->get_ssid())); + EXPECT_TRUE(0 == std::memcmp(testAp.bssid, ap1->get_bssid(), sizeof(testAp.bssid))); + EXPECT_EQ(testAp.channel, ap1->get_channel()); + EXPECT_EQ(testAp.rssi, ap1->get_rssi()); + EXPECT_EQ(testAp.security, ap1->get_security()); +} + diff --git a/UNITTESTS/features/netsocket/WiFiAccessPoint/unittest.cmake b/UNITTESTS/features/netsocket/WiFiAccessPoint/unittest.cmake new file mode 100644 index 0000000000..4b045712c4 --- /dev/null +++ b/UNITTESTS/features/netsocket/WiFiAccessPoint/unittest.cmake @@ -0,0 +1,12 @@ + +#################### +# UNIT TESTS +#################### + +set(unittest-sources + ../features/netsocket/WiFiAccessPoint.cpp +) + +set(unittest-test-sources + features/netsocket/WiFiAccessPoint/test_WiFiAccessPoint.cpp +) diff --git a/UNITTESTS/stubs/ATCmdParser_stub.cpp b/UNITTESTS/stubs/ATCmdParser_stub.cpp index d9157ec848..233dd039dc 100644 --- a/UNITTESTS/stubs/ATCmdParser_stub.cpp +++ b/UNITTESTS/stubs/ATCmdParser_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/ATHandler_stub.cpp b/UNITTESTS/stubs/ATHandler_stub.cpp index 7c65253af3..06e6fbfc09 100644 --- a/UNITTESTS/stubs/ATHandler_stub.cpp +++ b/UNITTESTS/stubs/ATHandler_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,7 +36,7 @@ int ATHandler_stub::timeout = 0; bool ATHandler_stub::default_timeout = 0; bool ATHandler_stub::debug_on = 0; ssize_t ATHandler_stub::ssize_value = 0; -char *ATHandler_stub::read_string_value = NULL; +const char *ATHandler_stub::read_string_value = NULL; size_t ATHandler_stub::size_value = 0; size_t ATHandler_stub::return_given_size = false; bool ATHandler_stub::bool_value = false; @@ -51,7 +51,7 @@ int ATHandler_stub::int_valid_count_table[kRead_int_table_size]; int ATHandler_stub::int_count = kRead_int_table_size; int ATHandler_stub::read_string_index = kRead_string_table_size; -char *ATHandler_stub::read_string_table[kRead_string_table_size]; +const char *ATHandler_stub::read_string_table[kRead_string_table_size]; int ATHandler_stub::resp_stop_success_count = kResp_stop_count_default; ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char *output_delimiter, uint16_t send_delay) : @@ -105,7 +105,7 @@ nsapi_error_t ATHandler::set_urc_handler(const char *urc, mbed::Callback return ATHandler_stub::nsapi_error_value; } -void ATHandler::remove_urc_handler(const char *prefix, mbed::Callback callback) +void ATHandler::remove_urc_handler(const char *prefix) { } @@ -176,7 +176,7 @@ ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag) ATHandler_stub::read_string_index--; if (ATHandler_stub::read_string_index >= 0) { - char *tmp = ATHandler_stub::read_string_table[ATHandler_stub::read_string_index]; + const char *tmp = ATHandler_stub::read_string_table[ATHandler_stub::read_string_index]; ssize_t len = strlen(tmp); memcpy(buf, tmp, len + 1); return len; @@ -283,6 +283,13 @@ void ATHandler::cmd_stop() { } +void ATHandler::cmd_stop_read_resp() +{ + cmd_stop(); + resp_start(); + resp_stop(); +} + device_err_t ATHandler::get_last_device_error() const { return ATHandler_stub::device_err_value; diff --git a/UNITTESTS/stubs/ATHandler_stub.h b/UNITTESTS/stubs/ATHandler_stub.h index 3341aa4ced..c506ccf017 100644 --- a/UNITTESTS/stubs/ATHandler_stub.h +++ b/UNITTESTS/stubs/ATHandler_stub.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,7 +41,7 @@ extern int timeout; extern bool default_timeout; extern bool debug_on; extern ssize_t ssize_value; -extern char *read_string_value; +extern const char *read_string_value; extern size_t size_value; extern size_t return_given_size; extern bool bool_value; @@ -52,7 +52,7 @@ extern mbed::FileHandle_stub *fh_value; extern mbed::device_err_t device_err_value; extern mbed::Callback callback; extern bool call_immediately; -extern char *read_string_table[kRead_string_table_size]; +extern const char *read_string_table[kRead_string_table_size]; extern int read_string_index; extern int int_valid_count_table[kRead_int_table_size]; extern int int_count; diff --git a/UNITTESTS/stubs/AT_CellularBase_stub.cpp b/UNITTESTS/stubs/AT_CellularBase_stub.cpp index e1f8526f5f..179c2e42e1 100644 --- a/UNITTESTS/stubs/AT_CellularBase_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularBase_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/AT_CellularBase_stub.h b/UNITTESTS/stubs/AT_CellularBase_stub.h index f7d117d192..ec32d8eb28 100644 --- a/UNITTESTS/stubs/AT_CellularBase_stub.h +++ b/UNITTESTS/stubs/AT_CellularBase_stub.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/AT_CellularDevice_stub.cpp b/UNITTESTS/stubs/AT_CellularDevice_stub.cpp index 2010018ced..9f6749a8f8 100644 --- a/UNITTESTS/stubs/AT_CellularDevice_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularDevice_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/AT_CellularInformation_stub.cpp b/UNITTESTS/stubs/AT_CellularInformation_stub.cpp index a41b3080d5..ae35f29bde 100644 --- a/UNITTESTS/stubs/AT_CellularInformation_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularInformation_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/AT_CellularMultiplexer_stub.cpp b/UNITTESTS/stubs/AT_CellularMultiplexer_stub.cpp index c397d5fb38..21ea7e9f54 100644 --- a/UNITTESTS/stubs/AT_CellularMultiplexer_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularMultiplexer_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp b/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp index c4ba878439..c976abdf91 100644 --- a/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -111,12 +111,12 @@ nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn) return NSAPI_ERROR_OK; } -nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, RegistrationStatus &status) +nsapi_error_t AT_CellularNetwork::get_registration_params(RegistrationType type, registration_params_t ®_params) { return NSAPI_ERROR_OK; } -nsapi_error_t AT_CellularNetwork::get_cell_id(int &cell_id) +nsapi_error_t AT_CellularNetwork::get_registration_params(registration_params_t ®_params) { return NSAPI_ERROR_OK; } @@ -186,12 +186,6 @@ nsapi_error_t AT_CellularNetwork::set_access_technology(RadioAccessTechnology op return NSAPI_ERROR_OK; } -nsapi_error_t AT_CellularNetwork::get_access_technology(RadioAccessTechnology &rat) -{ - rat = RAT_CATM1; - return NSAPI_ERROR_OK; -} - nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount) { return NSAPI_ERROR_OK; diff --git a/UNITTESTS/stubs/AT_CellularPower_stub.cpp b/UNITTESTS/stubs/AT_CellularPower_stub.cpp index 3459088ce5..56d8a4ca87 100644 --- a/UNITTESTS/stubs/AT_CellularPower_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularPower_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/AT_CellularSIM_stub.cpp b/UNITTESTS/stubs/AT_CellularSIM_stub.cpp index fc4be35b94..afab1012bd 100644 --- a/UNITTESTS/stubs/AT_CellularSIM_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularSIM_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/AT_CellularSMS_stub.cpp b/UNITTESTS/stubs/AT_CellularSMS_stub.cpp index 66456d7295..c43d4b2c82 100644 --- a/UNITTESTS/stubs/AT_CellularSMS_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularSMS_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/AT_CellularStack_stub.cpp b/UNITTESTS/stubs/AT_CellularStack_stub.cpp index 640d8c1b68..a4dd04732c 100644 --- a/UNITTESTS/stubs/AT_CellularStack_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularStack_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/BufferedBlockDevice_stub.cpp b/UNITTESTS/stubs/BufferedBlockDevice_stub.cpp index 9c9fabea1f..ce7e2aba88 100644 --- a/UNITTESTS/stubs/BufferedBlockDevice_stub.cpp +++ b/UNITTESTS/stubs/BufferedBlockDevice_stub.cpp @@ -1,5 +1,6 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018 ARM Limited +/* + * Copyright (c) , 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. diff --git a/UNITTESTS/stubs/CellularDevice_stub.cpp b/UNITTESTS/stubs/CellularDevice_stub.cpp index aba5fc8f04..542d79e8fb 100644 --- a/UNITTESTS/stubs/CellularDevice_stub.cpp +++ b/UNITTESTS/stubs/CellularDevice_stub.cpp @@ -27,7 +27,7 @@ MBED_WEAK CellularDevice *CellularDevice::get_default_instance() } CellularDevice::CellularDevice() : _network_ref_count(0), _sms_ref_count(0), _power_ref_count(0), _sim_ref_count(0), - _info_ref_count(0) + _info_ref_count(0) { } diff --git a/UNITTESTS/stubs/CellularUtil_stub.cpp b/UNITTESTS/stubs/CellularUtil_stub.cpp index d4bcaf4916..7de3907310 100644 --- a/UNITTESTS/stubs/CellularUtil_stub.cpp +++ b/UNITTESTS/stubs/CellularUtil_stub.cpp @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "CellularUtil.h" #include #include diff --git a/UNITTESTS/stubs/ChainingBlockDevice_stub.cpp b/UNITTESTS/stubs/ChainingBlockDevice_stub.cpp index 51134b3553..b31de2eec2 100644 --- a/UNITTESTS/stubs/ChainingBlockDevice_stub.cpp +++ b/UNITTESTS/stubs/ChainingBlockDevice_stub.cpp @@ -1,5 +1,6 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited +/* + * Copyright (c) , 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. @@ -74,7 +75,7 @@ bd_size_t ChainingBlockDevice::get_erase_size() const bd_size_t ChainingBlockDevice::get_erase_size(bd_addr_t addr) const { - return 0; + return 0; } int ChainingBlockDevice::get_erase_value() const diff --git a/UNITTESTS/stubs/EventFlags_stub.cpp b/UNITTESTS/stubs/EventFlags_stub.cpp index 9c20b882f4..39ded93482 100644 --- a/UNITTESTS/stubs/EventFlags_stub.cpp +++ b/UNITTESTS/stubs/EventFlags_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,8 +42,7 @@ uint32_t rtos::EventFlags::wait_all(uint32_t flags, uint32_t timeout, bool clear } uint32_t rtos::EventFlags::wait_any(uint32_t flags, uint32_t timeout, bool clear) { - if (!eventFlagsStubNextRetval.empty()) - { + if (!eventFlagsStubNextRetval.empty()) { uint32_t ret = eventFlagsStubNextRetval.front(); eventFlagsStubNextRetval.pop_front(); return ret; diff --git a/UNITTESTS/stubs/EventQueue_stub.cpp b/UNITTESTS/stubs/EventQueue_stub.cpp index e3436647b7..abbfc8ac21 100644 --- a/UNITTESTS/stubs/EventQueue_stub.cpp +++ b/UNITTESTS/stubs/EventQueue_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,9 +17,13 @@ #include "EventQueue.h" #include "Callback.h" +#include "EventQueue_stub.h" using namespace mbed; +int EventQueue_stub::int_value = 0; +unsigned EventQueue_stub::unsigned_value = 0; + namespace events { EventQueue::EventQueue(unsigned event_size, unsigned char *event_pointer) @@ -40,13 +44,18 @@ void EventQueue::break_dispatch() unsigned EventQueue::tick() { - return 0; + return EventQueue_stub::unsigned_value; } void EventQueue::cancel(int id) { } +int EventQueue::time_left(int id) +{ + return EventQueue_stub::int_value; +} + void EventQueue::background(Callback update) { } diff --git a/UNITTESTS/stubs/EventQueue_stub.h b/UNITTESTS/stubs/EventQueue_stub.h new file mode 100644 index 0000000000..12fb4d51a4 --- /dev/null +++ b/UNITTESTS/stubs/EventQueue_stub.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) , 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. + */ + +#include + +namespace EventQueue_stub { +extern int int_value; +extern unsigned unsigned_value; +} + diff --git a/UNITTESTS/stubs/ExhaustibleBlockDevice_stub.cpp b/UNITTESTS/stubs/ExhaustibleBlockDevice_stub.cpp index 36cdb1cfac..845da43e6d 100644 --- a/UNITTESTS/stubs/ExhaustibleBlockDevice_stub.cpp +++ b/UNITTESTS/stubs/ExhaustibleBlockDevice_stub.cpp @@ -1,5 +1,6 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited +/* + * Copyright (c) , 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. diff --git a/UNITTESTS/stubs/FileHandle_stub.h b/UNITTESTS/stubs/FileHandle_stub.h index ef68572c1e..3f0fb5abdb 100644 --- a/UNITTESTS/stubs/FileHandle_stub.h +++ b/UNITTESTS/stubs/FileHandle_stub.h @@ -14,35 +14,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef __FILE_HANDLE_STUB_H__ #define __FILE_HANDLE_STUB_H__ #include "FileHandle.h" -namespace mbed -{ +namespace mbed { static uint8_t filehandle_stub_short_value_counter = 0; static char *filehandle_stub_table = NULL; static uint8_t filehandle_stub_table_pos = 0; -class FileHandle_stub : public FileHandle -{ - public: +class FileHandle_stub : public FileHandle { +public: ssize_t size_value; - FileHandle_stub() { size_value = 0; } + FileHandle_stub() + { + size_value = 0; + } virtual ssize_t read(void *buffer, size_t size) { - if (filehandle_stub_table) - { + if (filehandle_stub_table) { ssize_t ret = strlen(filehandle_stub_table) - filehandle_stub_table_pos; - if (size < ret) - { + if (size < ret) { ret = size; } - memcpy(buffer, filehandle_stub_table, ret); + memcpy(buffer, filehandle_stub_table + filehandle_stub_table_pos, ret); filehandle_stub_table_pos += ret; return ret; } @@ -51,33 +51,37 @@ class FileHandle_stub : public FileHandle virtual ssize_t write(const void *buffer, size_t size) { - if (size_value > 0) - { + if (size_value > 0) { size_value--; return size; - } - else if (size_value < 0) - { + } else if (size_value < 0) { return -1; } return 0; } - virtual off_t seek(off_t offset, int whence = SEEK_SET) { return 0; } + virtual off_t seek(off_t offset, int whence = SEEK_SET) + { + return 0; + } - virtual int close() {} + virtual int close() + { + } virtual short poll(short events) const { - if (filehandle_stub_short_value_counter) - { + if (filehandle_stub_short_value_counter) { filehandle_stub_short_value_counter--; return short_value; } return 0; } - virtual void sigio(Callback func) { func(); } + virtual void sigio(Callback func) + { + func(); + } short short_value; }; diff --git a/UNITTESTS/stubs/FlashSimBlockDevice_stub.cpp b/UNITTESTS/stubs/FlashSimBlockDevice_stub.cpp index bbc9db57ce..4f0e368981 100644 --- a/UNITTESTS/stubs/FlashSimBlockDevice_stub.cpp +++ b/UNITTESTS/stubs/FlashSimBlockDevice_stub.cpp @@ -1,5 +1,6 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018 ARM Limited +/* + * Copyright (c) , 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. diff --git a/UNITTESTS/stubs/HeapBlockDevice_stub.cpp b/UNITTESTS/stubs/HeapBlockDevice_stub.cpp index afa6e9bbbc..dd39ffc28c 100644 --- a/UNITTESTS/stubs/HeapBlockDevice_stub.cpp +++ b/UNITTESTS/stubs/HeapBlockDevice_stub.cpp @@ -1,5 +1,6 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited +/* + * Copyright (c) , 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. diff --git a/UNITTESTS/stubs/Kernel_stub.cpp b/UNITTESTS/stubs/Kernel_stub.cpp index ecfa1d80af..0050f4481a 100644 --- a/UNITTESTS/stubs/Kernel_stub.cpp +++ b/UNITTESTS/stubs/Kernel_stub.cpp @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "Kernel.h" namespace rtos { diff --git a/UNITTESTS/stubs/LoRaMacChannelPlan_stub.cpp b/UNITTESTS/stubs/LoRaMacChannelPlan_stub.cpp new file mode 100644 index 0000000000..5d84f26359 --- /dev/null +++ b/UNITTESTS/stubs/LoRaMacChannelPlan_stub.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) , 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. + */ + +#include "LoRaMacChannelPlan.h" + +LoRaMacChannelPlan::LoRaMacChannelPlan() : _lora_phy(NULL) +{ +} + +LoRaMacChannelPlan::~LoRaMacChannelPlan() +{ +} + +void LoRaMacChannelPlan::activate_channelplan_subsystem(LoRaPHY *phy) +{ +} + +lorawan_status_t LoRaMacChannelPlan::set_plan(const lorawan_channelplan_t &plan) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaMacChannelPlan::get_plan(lorawan_channelplan_t &plan, + const channel_params_t *channel_list) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaMacChannelPlan::remove_plan() +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaMacChannelPlan::remove_single_channel(uint8_t channel_id) +{ + return LORAWAN_STATUS_OK; +} + diff --git a/UNITTESTS/stubs/LoRaMacCommand_stub.cpp b/UNITTESTS/stubs/LoRaMacCommand_stub.cpp new file mode 100644 index 0000000000..1bed37572e --- /dev/null +++ b/UNITTESTS/stubs/LoRaMacCommand_stub.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) , 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. + */ + +#include "LoRaMacCommand.h" +#include "LoRaMac.h" + +#include "LoRaMacCommand_stub.h" + +lorawan_status_t LoRaMacCommand_stub::status_value = LORAWAN_STATUS_OK; +bool LoRaMacCommand_stub::bool_value = false; +uint8_t LoRaMacCommand_stub::uint8_value = 0; +int32_t LoRaMacCommand_stub::int32_value = 0; + +LoRaMacCommand::LoRaMacCommand() +{ +} + +void LoRaMacCommand::clear_command_buffer() +{ +} + +uint8_t LoRaMacCommand::get_mac_cmd_length() const +{ + return LoRaMacCommand_stub::uint8_value; +} + +uint8_t *LoRaMacCommand::get_mac_commands_buffer() +{ + return &LoRaMacCommand_stub::uint8_value; +} + +void LoRaMacCommand::parse_mac_commands_to_repeat() +{ +} + + +void LoRaMacCommand::clear_repeat_buffer() +{ +} + +void LoRaMacCommand::copy_repeat_commands_to_buffer() +{ +} + +uint8_t LoRaMacCommand::get_repeat_commands_length() const +{ + return LoRaMacCommand_stub::uint8_value; +} + +void LoRaMacCommand::clear_sticky_mac_cmd() +{ +} + +bool LoRaMacCommand::has_sticky_mac_cmd() const +{ + return LoRaMacCommand_stub::bool_value; +} + +lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, uint8_t mac_index, + uint8_t commands_size, uint8_t snr, + loramac_mlme_confirm_t &mlme_conf, + lora_mac_system_params_t &mac_sys_params, + LoRaPHY &lora_phy) +{ + return LoRaMacCommand_stub::status_value; +} + +int32_t LoRaMacCommand::cmd_buffer_remaining() const +{ + return LoRaMacCommand_stub::int32_value; +} + +void LoRaMacCommand::set_batterylevel_callback(mbed::Callback battery_level) +{ +} + +lorawan_status_t LoRaMacCommand::add_link_check_req() +{ + return LoRaMacCommand_stub::status_value; +} + +lorawan_status_t LoRaMacCommand::add_link_adr_ans(uint8_t status) +{ + return LoRaMacCommand_stub::status_value; +} + +lorawan_status_t LoRaMacCommand::add_duty_cycle_ans() +{ + return LoRaMacCommand_stub::status_value; +} + +lorawan_status_t LoRaMacCommand::add_rx_param_setup_ans(uint8_t status) +{ + return LoRaMacCommand_stub::status_value; +} + +lorawan_status_t LoRaMacCommand::add_dev_status_ans(uint8_t battery, uint8_t margin) +{ + return LoRaMacCommand_stub::status_value; +} + +lorawan_status_t LoRaMacCommand::add_new_channel_ans(uint8_t status) +{ + return LoRaMacCommand_stub::status_value; +} + +lorawan_status_t LoRaMacCommand::add_rx_timing_setup_ans() +{ + return LoRaMacCommand_stub::status_value; +} + +lorawan_status_t LoRaMacCommand::add_tx_param_setup_ans() +{ + return LoRaMacCommand_stub::status_value; +} + +lorawan_status_t LoRaMacCommand::add_dl_channel_ans(uint8_t status) +{ + return LoRaMacCommand_stub::status_value; +} diff --git a/UNITTESTS/stubs/LoRaMacCommand_stub.h b/UNITTESTS/stubs/LoRaMacCommand_stub.h new file mode 100644 index 0000000000..2d1678ff7a --- /dev/null +++ b/UNITTESTS/stubs/LoRaMacCommand_stub.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) , 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. + */ + + +#include +#include "lorawan_types.h" + +namespace LoRaMacCommand_stub { +extern lorawan_status_t status_value; +extern bool bool_value; +extern uint8_t uint8_value; +extern int32_t int32_value; +} diff --git a/UNITTESTS/stubs/LoRaMacCrypto_stub.cpp b/UNITTESTS/stubs/LoRaMacCrypto_stub.cpp new file mode 100644 index 0000000000..669e44f64c --- /dev/null +++ b/UNITTESTS/stubs/LoRaMacCrypto_stub.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) , 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. + */ + +#include +#include + +#include "LoRaMacCrypto.h" +#include "system/lorawan_data_structures.h" + +#include "LoRaMacCrypto_stub.h" + +int LoRaMacCrypto_stub::int_table_idx_value = 0; +int LoRaMacCrypto_stub::int_table[20] = {}; + +LoRaMacCrypto::LoRaMacCrypto() +{ +} + +int LoRaMacCrypto::compute_mic(const uint8_t *, uint16_t, const uint8_t *, uint32_t, uint32_t, + uint8_t dir, uint32_t, uint32_t *) +{ + return LoRaMacCrypto_stub::int_table[LoRaMacCrypto_stub::int_table_idx_value++]; +} + +int LoRaMacCrypto::encrypt_payload(const uint8_t *, uint16_t, const uint8_t *, uint32_t, uint32_t, + uint8_t, uint32_t, uint8_t *) +{ + return LoRaMacCrypto_stub::int_table[LoRaMacCrypto_stub::int_table_idx_value++]; +} + +int LoRaMacCrypto::decrypt_payload(const uint8_t *, uint16_t, const uint8_t *, uint32_t, uint32_t, + uint8_t, uint32_t, uint8_t *) +{ + return LoRaMacCrypto_stub::int_table[LoRaMacCrypto_stub::int_table_idx_value++]; +} + +int LoRaMacCrypto::compute_join_frame_mic(const uint8_t *, uint16_t, const uint8_t *, uint32_t, uint32_t *) +{ + return LoRaMacCrypto_stub::int_table[LoRaMacCrypto_stub::int_table_idx_value++]; +} + +int LoRaMacCrypto::decrypt_join_frame(const uint8_t *in, uint16_t size, const uint8_t *, uint32_t, uint8_t *out) +{ + memcpy(out, in, size); + return LoRaMacCrypto_stub::int_table[LoRaMacCrypto_stub::int_table_idx_value++]; +} + +int LoRaMacCrypto::compute_skeys_for_join_frame(const uint8_t *, uint32_t, const uint8_t *, uint16_t, + uint8_t *, uint8_t *) +{ + return LoRaMacCrypto_stub::int_table[LoRaMacCrypto_stub::int_table_idx_value++]; +} diff --git a/UNITTESTS/stubs/LoRaMacCrypto_stub.h b/UNITTESTS/stubs/LoRaMacCrypto_stub.h new file mode 100644 index 0000000000..fb0f24eb1f --- /dev/null +++ b/UNITTESTS/stubs/LoRaMacCrypto_stub.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) , 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. + */ + + +#include + +namespace LoRaMacCrypto_stub { +extern int int_table_idx_value; +extern int int_table[20]; +} diff --git a/UNITTESTS/stubs/LoRaMac_stub.cpp b/UNITTESTS/stubs/LoRaMac_stub.cpp new file mode 100644 index 0000000000..083115d38a --- /dev/null +++ b/UNITTESTS/stubs/LoRaMac_stub.cpp @@ -0,0 +1,466 @@ +/* + * Copyright (c) , 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. + */ + +#include +#include "LoRaMac.h" +#include "LoRaMac_stub.h" + +using namespace events; +using namespace mbed; + +int LoRaMac_stub::bool_false_counter = 0; +int LoRaMac_stub::bool_true_counter = 0; +bool LoRaMac_stub::bool_value = false; +int LoRaMac_stub::int_value = 0; +uint8_t LoRaMac_stub::uint8_value = 1; +rx_slot_t LoRaMac_stub::slot_value = RX_SLOT_WIN_1; +lorawan_status_t LoRaMac_stub::status_value = LORAWAN_STATUS_OK; +loramac_mcps_confirm_t *LoRaMac_stub::mcps_conf_ptr = NULL; +loramac_mcps_indication_t *LoRaMac_stub::mcps_ind_ptr = NULL; +loramac_mlme_confirm_t *LoRaMac_stub::mlme_conf_ptr = NULL; +loramac_mlme_indication_t *LoRaMac_stub::mlme_ind_ptr = NULL; +device_class_t LoRaMac_stub::dev_class_value = CLASS_A; +mbed::Callback LoRaMac_stub::_scheduling_failure_handler = NULL; + +LoRaMac::LoRaMac() + : _lora_time(), + _lora_phy(NULL), + _mac_commands(), + _channel_plan(), + _lora_crypto(), + _ev_queue(NULL), + _mcps_indication(), + _mcps_confirmation(), + _mlme_indication(), + _mlme_confirmation(), + _is_nwk_joined(false), + _continuous_rx2_window_open(false), + _device_class(CLASS_A) +{} + +LoRaMac::~LoRaMac() +{ +} + +const loramac_mcps_confirm_t *LoRaMac::get_mcps_confirmation() const +{ + return LoRaMac_stub::mcps_conf_ptr; +} + +const loramac_mcps_indication_t *LoRaMac::get_mcps_indication() const +{ + return LoRaMac_stub::mcps_ind_ptr; +} + +const loramac_mlme_confirm_t *LoRaMac::get_mlme_confirmation() const +{ + return LoRaMac_stub::mlme_conf_ptr; +} + +const loramac_mlme_indication_t *LoRaMac::get_mlme_indication() const +{ + return LoRaMac_stub::mlme_ind_ptr; +} + +void LoRaMac::post_process_mlme_request() +{ +} + +void LoRaMac::post_process_mcps_req() +{ +} + +void LoRaMac::post_process_mcps_ind() +{ +} + +void LoRaMac::post_process_mlme_ind() +{ +} + +lorawan_time_t LoRaMac::get_current_time(void) +{ +} + +rx_slot_t LoRaMac::get_current_slot(void) +{ + return LoRaMac_stub::slot_value; +} + +void LoRaMac::handle_join_accept_frame(const uint8_t *payload, uint16_t size) +{ +} + +void LoRaMac::check_frame_size(uint16_t size) +{ +} + +bool LoRaMac::message_integrity_check(const uint8_t *const payload, + const uint16_t size, + uint8_t *const ptr_pos, + uint32_t address, + uint32_t *downlink_counter, + const uint8_t *nwk_skey) +{ + if (LoRaMac_stub::bool_false_counter) { + LoRaMac_stub::bool_false_counter--; + return false; + } + if (LoRaMac_stub::bool_true_counter) { + LoRaMac_stub::bool_true_counter--; + return true; + } + + return LoRaMac_stub::bool_value; +} + +void LoRaMac::extract_data_and_mac_commands(const uint8_t *payload, + uint16_t size, + uint8_t fopts_len, + uint8_t *nwk_skey, + uint8_t *app_skey, + uint32_t address, + uint32_t downlink_counter, + int16_t rssi, + int8_t snr) +{ +} + +void LoRaMac::extract_mac_commands_only(const uint8_t *payload, + int8_t snr, + uint8_t fopts_len) +{ +} + +void LoRaMac::handle_data_frame(const uint8_t *const payload, + const uint16_t size, + uint8_t ptr_pos, + uint8_t msg_type, + int16_t rssi, + int8_t snr) +{ +} + +void LoRaMac::set_batterylevel_callback(mbed::Callback battery_level) +{ +} + +void LoRaMac::on_radio_tx_done(lorawan_time_t timestamp) +{ +} + +void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size, + int16_t rssi, int8_t snr) +{ +} + +void LoRaMac::on_radio_tx_timeout(void) +{ +} + +void LoRaMac::on_radio_rx_timeout(bool is_timeout) +{ +} + +bool LoRaMac::continue_joining_process() +{ + if (LoRaMac_stub::bool_false_counter) { + LoRaMac_stub::bool_false_counter--; + return false; + } + if (LoRaMac_stub::bool_true_counter) { + LoRaMac_stub::bool_true_counter--; + return true; + } + return LoRaMac_stub::bool_value; +} + +bool LoRaMac::continue_sending_process() +{ + if (LoRaMac_stub::bool_false_counter) { + LoRaMac_stub::bool_false_counter--; + return false; + } + if (LoRaMac_stub::bool_true_counter) { + LoRaMac_stub::bool_true_counter--; + return true; + } + return LoRaMac_stub::bool_value; +} + +lorawan_status_t LoRaMac::send_join_request() +{ + return LoRaMac_stub::status_value; +} + +lorawan_status_t LoRaMac::handle_retransmission() +{ + return LoRaMac_stub::status_value; +} + +void LoRaMac::on_backoff_timer_expiry(void) +{ +} + +void LoRaMac::open_rx1_window(void) +{ +} + +void LoRaMac::open_rx2_window() +{ +} + +void LoRaMac::on_ack_timeout_timer_event(void) +{ +} + +bool LoRaMac::validate_payload_length(uint16_t length, + int8_t datarate, + uint8_t fopts_len) +{ + if (LoRaMac_stub::bool_false_counter) { + LoRaMac_stub::bool_false_counter--; + return false; + } + if (LoRaMac_stub::bool_true_counter) { + LoRaMac_stub::bool_true_counter--; + return true; + } + return LoRaMac_stub::bool_value; +} + +void LoRaMac::set_mlme_schedule_ul_indication(void) +{ +} + +// This is not actual transmission. It just schedules a message in response +// to MCPS request +lorawan_status_t LoRaMac::send(loramac_mhdr_t *machdr, const uint8_t fport, + const void *fbuffer, uint16_t fbuffer_size) +{ + return LoRaMac_stub::status_value; +} + +int LoRaMac::get_backoff_timer_event_id(void) +{ + return LoRaMac_stub::int_value; +} + +lorawan_status_t LoRaMac::clear_tx_pipe(void) +{ + return LoRaMac_stub::status_value; +} + +lorawan_status_t LoRaMac::schedule_tx() +{ + return LoRaMac_stub::status_value; +} + +void LoRaMac::calculate_backOff(uint8_t channel) +{ +} + +void LoRaMac::reset_mac_parameters(void) +{ +} + +uint8_t LoRaMac::get_default_tx_datarate() +{ + return 0; +} + +void LoRaMac::enable_adaptive_datarate(bool adr_enabled) +{ +} + +lorawan_status_t LoRaMac::set_channel_data_rate(uint8_t data_rate) +{ + return LoRaMac_stub::status_value; +} + +bool LoRaMac::tx_ongoing() +{ + if (LoRaMac_stub::bool_false_counter) { + LoRaMac_stub::bool_false_counter--; + return false; + } + if (LoRaMac_stub::bool_true_counter) { + LoRaMac_stub::bool_true_counter--; + return true; + } + return LoRaMac_stub::bool_value; +} + +void LoRaMac::set_tx_ongoing(bool ongoing) +{ +} + +void LoRaMac::reset_ongoing_tx(bool reset_pending) +{ +} + +int16_t LoRaMac::prepare_ongoing_tx(const uint8_t port, + const uint8_t *const data, + uint16_t length, + uint8_t flags, + uint8_t num_retries) +{ + return 0; +} + +lorawan_status_t LoRaMac::send_ongoing_tx() +{ + return LoRaMac_stub::status_value; +} + +device_class_t LoRaMac::get_device_class() const +{ + return LoRaMac_stub::dev_class_value; +} + +void LoRaMac::set_device_class(const device_class_t &device_class, + mbed::Callbackrx2_would_be_closure_handler) +{ +} + +void LoRaMac::setup_link_check_request() +{ +} + +lorawan_status_t LoRaMac::prepare_join(const lorawan_connect_t *params, bool is_otaa) +{ + return LoRaMac_stub::status_value; +} + +lorawan_status_t LoRaMac::join(bool is_otaa) +{ + return LoRaMac_stub::status_value; +} + +static void memcpy_convert_endianess(uint8_t *dst, + const uint8_t *src, + uint16_t size) +{ +} + +lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr, + loramac_frame_ctrl_t *fctrl, + const uint8_t fport, + const void *fbuffer, + uint16_t fbuffer_size) +{ + return LoRaMac_stub::status_value; +} + +lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel) +{ + return LoRaMac_stub::status_value; +} + +void LoRaMac::reset_mcps_confirmation() +{ +} + +void LoRaMac::reset_mlme_confirmation() +{ +} + +void LoRaMac::reset_mcps_indication() +{ +} + +void LoRaMac::set_tx_continuous_wave(uint8_t channel, int8_t datarate, int8_t tx_power, + float max_eirp, float antenna_gain, uint16_t timeout) +{ +} + +lorawan_status_t LoRaMac::initialize(EventQueue *queue, + mbed::Callbackscheduling_failure_handler) +{ + LoRaMac_stub::_scheduling_failure_handler = scheduling_failure_handler; + return LoRaMac_stub::status_value; +} + +void LoRaMac::disconnect() +{ +} + +uint8_t LoRaMac::get_max_possible_tx_size(uint8_t fopts_len) +{ + return 0; +} + +bool LoRaMac::nwk_joined() +{ + if (LoRaMac_stub::bool_false_counter) { + LoRaMac_stub::bool_false_counter--; + return false; + } + if (LoRaMac_stub::bool_true_counter) { + LoRaMac_stub::bool_true_counter--; + return true; + } + return LoRaMac_stub::bool_value; +} + +void LoRaMac::set_nwk_joined(bool joined) +{ +} + +lorawan_status_t LoRaMac::add_channel_plan(const lorawan_channelplan_t &plan) +{ + return LoRaMac_stub::status_value; +} + +lorawan_status_t LoRaMac::remove_channel_plan() +{ + return LoRaMac_stub::status_value; +} + +lorawan_status_t LoRaMac::get_channel_plan(lorawan_channelplan_t &plan) +{ + return LoRaMac_stub::status_value; +} + +lorawan_status_t LoRaMac::remove_single_channel(uint8_t id) +{ + return LoRaMac_stub::status_value; +} + +lorawan_status_t LoRaMac::multicast_channel_link(multicast_params_t *channel_param) +{ + return LoRaMac_stub::status_value; +} + +lorawan_status_t LoRaMac::multicast_channel_unlink(multicast_params_t *channel_param) +{ + return LoRaMac_stub::status_value; +} + +void LoRaMac::bind_phy(LoRaPHY &phy) +{ +} + +uint8_t LoRaMac::get_QOS_level(void) +{ + return LoRaMac_stub::uint8_value; +} + +uint8_t LoRaMac::get_prev_QOS_level(void) +{ + return LoRaMac_stub::uint8_value; +} diff --git a/UNITTESTS/stubs/LoRaMac_stub.h b/UNITTESTS/stubs/LoRaMac_stub.h new file mode 100644 index 0000000000..dedb261745 --- /dev/null +++ b/UNITTESTS/stubs/LoRaMac_stub.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) , 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. + */ + +#include "stdint.h" +#include "stdbool.h" +#include + +#include "lorawan_types.h" +#include "lorawan_data_structures.h" + +namespace LoRaMac_stub { +extern bool bool_value; +extern int bool_false_counter; +extern int bool_true_counter; +extern int int_value; +extern uint8_t uint8_value; +extern rx_slot_t slot_value; +extern lorawan_status_t status_value; +extern loramac_mcps_confirm_t *mcps_conf_ptr; +extern loramac_mcps_indication_t *mcps_ind_ptr; +extern loramac_mlme_confirm_t *mlme_conf_ptr; +extern loramac_mlme_indication_t *mlme_ind_ptr; +extern device_class_t dev_class_value; +extern mbed::Callback _scheduling_failure_handler; +} diff --git a/UNITTESTS/stubs/LoRaPHYEU868_stub.cpp b/UNITTESTS/stubs/LoRaPHYEU868_stub.cpp new file mode 100644 index 0000000000..a425f30a12 --- /dev/null +++ b/UNITTESTS/stubs/LoRaPHYEU868_stub.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) , 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. + */ + +#include "LoRaPHYEU868.h" +#include "lora_phy_ds.h" + +LoRaPHYEU868::LoRaPHYEU868() +{ +} + +LoRaPHYEU868::~LoRaPHYEU868() +{ +} + diff --git a/UNITTESTS/stubs/LoRaPHY_stub.cpp b/UNITTESTS/stubs/LoRaPHY_stub.cpp new file mode 100644 index 0000000000..56862af5df --- /dev/null +++ b/UNITTESTS/stubs/LoRaPHY_stub.cpp @@ -0,0 +1,414 @@ +/* + * Copyright (c) , 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. + */ + + +#include +#include +#include +#include + +#include "LoRaPHY.h" +#include "LoRaPHY_stub.h" + +LoRaRadio *LoRaPHY_stub::radio = NULL; +uint32_t LoRaPHY_stub::uint32_value = 0; +uint16_t LoRaPHY_stub::uint16_value = 0; +uint8_t LoRaPHY_stub::uint8_value = 0; +int8_t LoRaPHY_stub::int8_value = 0; +int LoRaPHY_stub::int_value = 0; +double LoRaPHY_stub::double_value = 0; +lorawan_status_t LoRaPHY_stub::lorawan_status_value = LORAWAN_STATUS_OK; +channel_params_t *LoRaPHY_stub::channel_params_ptr = NULL; +uint8_t LoRaPHY_stub::bool_counter = 0; +bool LoRaPHY_stub::bool_table[20] = {}; +uint8_t LoRaPHY_stub::linkAdrNbBytesParsed = 0; +uint8_t LoRaPHY_stub::ch_mask_value = 0; +uint8_t LoRaPHY_stub::adr_parse_count = 0; + +LoRaPHY::LoRaPHY() + : _radio(LoRaPHY_stub::radio) +{ +} + +LoRaPHY::~LoRaPHY() +{ +} + +void LoRaPHY::initialize(LoRaWANTimeHandler *lora_time) +{ +} + +bool LoRaPHY::mask_bit_test(const uint16_t *mask, unsigned bit) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +void LoRaPHY::mask_bit_set(uint16_t *mask, unsigned bit) +{ +} + +void LoRaPHY::mask_bit_clear(uint16_t *mask, unsigned bit) +{ +} + +void LoRaPHY::set_radio_instance(LoRaRadio &radio) +{ +} + +void LoRaPHY::put_radio_to_sleep() +{ +} + +void LoRaPHY::put_radio_to_standby() +{ +} + +void LoRaPHY::setup_public_network_mode(bool set) +{ +} + +void LoRaPHY::handle_receive(void) +{ +} + +uint32_t LoRaPHY::get_radio_rng() +{ + return LoRaPHY_stub::uint32_value; +} + +void LoRaPHY::handle_send(uint8_t *buf, uint8_t size) +{ +} + +uint8_t LoRaPHY::request_new_channel(int8_t channel_id, channel_params_t *new_channel) +{ + return LoRaPHY_stub::uint8_value; +} + +int32_t LoRaPHY::get_random(int32_t min, int32_t max) +{ + return LoRaPHY_stub::uint32_value; +} + +bool LoRaPHY::verify_channel_DR(uint16_t *channel_mask, int8_t dr) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +bool LoRaPHY::val_in_range(int8_t value, int8_t min, int8_t max) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +bool LoRaPHY::disable_channel(uint16_t *channel_mask, uint8_t id, + uint8_t max_channels_num) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +uint8_t LoRaPHY::count_bits(uint16_t mask, uint8_t nbBits) +{ + return LoRaPHY_stub::uint8_value; +} + +uint8_t LoRaPHY::num_active_channels(uint16_t *channel_mask, uint8_t start_idx, + uint8_t stop_idx) +{ + return LoRaPHY_stub::uint8_value; +} + +void LoRaPHY::copy_channel_mask(uint16_t *dest_mask, uint16_t *src_mask, uint8_t len) +{ + if ((dest_mask != NULL) && (src_mask != NULL)) { + for (uint8_t i = 0; i < len; i++) { + dest_mask[i] = src_mask[i]; + } + } +} + +void LoRaPHY::set_last_tx_done(uint8_t channel, bool joined, lorawan_time_t last_tx_done_time) +{ +} + +lorawan_time_t LoRaPHY::update_band_timeoff(bool joined, bool duty_cycle, + band_t *bands, uint8_t nb_bands) +{ + return LoRaPHY_stub::uint32_value; +} + +uint8_t LoRaPHY::parse_link_ADR_req(const uint8_t *payload, + link_adr_params_t *params) +{ + params->ch_mask_ctrl = LoRaPHY_stub::ch_mask_value; + + if (LoRaPHY_stub::adr_parse_count) { + return --LoRaPHY_stub::adr_parse_count; + } + + return LoRaPHY_stub::uint8_value; +} + +uint8_t LoRaPHY::verify_link_ADR_req(verify_adr_params_t *verify_params, + int8_t *dr, int8_t *tx_pow, uint8_t *nb_rep) +{ + return LoRaPHY_stub::uint8_value; +} + +void LoRaPHY::get_rx_window_params(double t_symb, uint8_t min_rx_symb, + uint32_t rx_error, uint32_t wakeup_time, + uint32_t *window_timeout, int32_t *window_offset) +{ +} + +int8_t LoRaPHY::compute_tx_power(int8_t tx_power_idx, float max_eirp, + float antenna_gain) +{ + return LoRaPHY_stub::int8_value; +} + + +int8_t LoRaPHY::get_next_lower_dr(int8_t dr, int8_t min_dr) +{ + return LoRaPHY_stub::int8_value; +} + +uint8_t LoRaPHY::get_bandwidth(uint8_t dr) +{ + return LoRaPHY_stub::uint8_value; +} + +uint8_t LoRaPHY::enabled_channel_count(uint8_t datarate, + const uint16_t *channel_mask, + uint8_t *channel_indices, + uint8_t *delayTx) +{ + return LoRaPHY_stub::uint8_value; +} + +bool LoRaPHY::is_datarate_supported(const int8_t datarate) const +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +void LoRaPHY::reset_to_default_values(loramac_protocol_params *params, bool init) +{ +} + +int8_t LoRaPHY::get_next_lower_tx_datarate(int8_t datarate) +{ + return LoRaPHY_stub::int8_value; +} + +uint8_t LoRaPHY::get_minimum_rx_datarate() +{ + return LoRaPHY_stub::uint8_value; +} + +uint8_t LoRaPHY::get_minimum_tx_datarate() +{ + return LoRaPHY_stub::uint8_value; +} + +uint8_t LoRaPHY::get_default_tx_datarate() +{ + return LoRaPHY_stub::uint8_value; +} + +uint8_t LoRaPHY::get_default_max_tx_datarate() +{ + return LoRaPHY_stub::uint8_value; +} + +uint8_t LoRaPHY::get_default_tx_power() +{ + return LoRaPHY_stub::uint8_value; +} + +uint8_t LoRaPHY::get_max_payload(uint8_t datarate, bool use_repeater) +{ + return LoRaPHY_stub::uint8_value; +} + +uint16_t LoRaPHY::get_maximum_frame_counter_gap() +{ + return LoRaPHY_stub::uint16_value; +} + +uint32_t LoRaPHY::get_ack_timeout() +{ + return LoRaPHY_stub::uint32_value; +} + +uint32_t LoRaPHY::get_default_rx2_frequency() +{ + return LoRaPHY_stub::uint32_value; +} + +uint8_t LoRaPHY::get_default_rx2_datarate() +{ + return phy_params.rx_window2_datarate; +} + +uint16_t *LoRaPHY::get_channel_mask(bool get_default) +{ + return &LoRaPHY_stub::uint16_value; +} + +uint8_t LoRaPHY::get_max_nb_channels() +{ + return LoRaPHY_stub::uint8_value; +} + +channel_params_t *LoRaPHY::get_phy_channels() +{ + return LoRaPHY_stub::channel_params_ptr; +} + +bool LoRaPHY::is_custom_channel_plan_supported() +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +void LoRaPHY::restore_default_channels() +{ +} + +bool LoRaPHY::verify_rx_datarate(uint8_t datarate) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +bool LoRaPHY::verify_tx_datarate(uint8_t datarate, bool use_default) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +bool LoRaPHY::verify_tx_power(uint8_t tx_power) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +bool LoRaPHY::verify_duty_cycle(bool cycle) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +bool LoRaPHY::verify_nb_join_trials(uint8_t nb_join_trials) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +void LoRaPHY::apply_cf_list(const uint8_t *payload, uint8_t size) +{ +} + + +bool LoRaPHY::get_next_ADR(bool restore_channel_mask, int8_t &dr_out, + int8_t &tx_power_out, uint32_t &adr_ack_cnt) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +void LoRaPHY::compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols, + uint32_t rx_error, + rx_config_params_t *rx_conf_params) +{ +} + +bool LoRaPHY::rx_config(rx_config_params_t *rx_conf) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +bool LoRaPHY::tx_config(tx_config_params_t *tx_conf, int8_t *tx_power, + lorawan_time_t *tx_toa) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +uint8_t LoRaPHY::link_ADR_request(adr_req_params_t *link_adr_req, + int8_t *dr_out, int8_t *tx_power_out, + uint8_t *nb_rep_out, uint8_t *nb_bytes_processed) +{ + *nb_bytes_processed = LoRaPHY_stub::linkAdrNbBytesParsed; + return LoRaPHY_stub::uint8_value; +} + +uint8_t LoRaPHY::accept_rx_param_setup_req(rx_param_setup_req_t *params) +{ + return LoRaPHY_stub::uint8_value; +} + +bool LoRaPHY::accept_tx_param_setup_req(uint8_t ul_dwell_time, uint8_t dl_dwell_time) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +int LoRaPHY::lookup_band_for_frequency(uint32_t freq) const +{ + return LoRaPHY_stub::int_value; +} + +bool LoRaPHY::verify_frequency_for_band(uint32_t freq, uint8_t band) const +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +uint8_t LoRaPHY::dl_channel_request(uint8_t channel_id, uint32_t rx1_frequency) +{ + return LoRaPHY_stub::uint8_value; +} + +int8_t LoRaPHY::get_alternate_DR(uint8_t nb_trials) +{ + return LoRaPHY_stub::int8_value; +} + +void LoRaPHY::calculate_backoff(bool joined, bool last_tx_was_join_req, bool dc_enabled, uint8_t channel, + lorawan_time_t elapsed_time, lorawan_time_t tx_toa) +{ +} + +lorawan_status_t LoRaPHY::set_next_channel(channel_selection_params_t *params, + uint8_t *channel, lorawan_time_t *time, + lorawan_time_t *aggregate_timeoff) +{ + *time = 100; + return LoRaPHY_stub::lorawan_status_value; +} + +lorawan_status_t LoRaPHY::add_channel(const channel_params_t *new_channel, + uint8_t id) +{ + return LoRaPHY_stub::lorawan_status_value; +} + +bool LoRaPHY::remove_channel(uint8_t channel_id) +{ + return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++]; +} + +void LoRaPHY::set_tx_cont_mode(cw_mode_params_t *params, uint32_t given_frequency) +{ +} + +uint8_t LoRaPHY::apply_DR_offset(int8_t dr, int8_t dr_offset) +{ + return LoRaPHY_stub::uint8_value; +} + + diff --git a/UNITTESTS/stubs/LoRaPHY_stub.h b/UNITTESTS/stubs/LoRaPHY_stub.h new file mode 100644 index 0000000000..d3c8cffdd8 --- /dev/null +++ b/UNITTESTS/stubs/LoRaPHY_stub.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) , 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. + */ + +#include "stdint.h" +#include "stdbool.h" +#include + +#include "lorawan_types.h" + +namespace LoRaPHY_stub { +extern LoRaRadio *radio; +extern uint8_t bool_counter; +extern bool bool_table[20]; +extern uint32_t uint32_value; +extern uint8_t uint8_value; +extern int8_t int8_value; +extern int int_value; +extern double double_value; +extern uint16_t uint16_value; +extern lorawan_status_t lorawan_status_value; +extern channel_params_t *channel_params_ptr; +extern uint8_t linkAdrNbBytesParsed; +extern uint8_t ch_mask_value; +extern uint8_t adr_parse_count; +} diff --git a/UNITTESTS/stubs/LoRaWANStack_stub.cpp b/UNITTESTS/stubs/LoRaWANStack_stub.cpp new file mode 100644 index 0000000000..4423ee5ca8 --- /dev/null +++ b/UNITTESTS/stubs/LoRaWANStack_stub.cpp @@ -0,0 +1,303 @@ +/* + * Copyright (c) , 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. + */ + +#include +#include + +#include "LoRaWANStack.h" + +using namespace mbed; +using namespace events; + +/***************************************************************************** + * Constructor * + ****************************************************************************/ +LoRaWANStack::LoRaWANStack() + : _loramac(), + _device_current_state(DEVICE_STATE_NOT_INITIALIZED), + _lw_session(), + _tx_msg(), + _rx_msg(), + _tx_metadata(), + _rx_metadata(), + _num_retry(1), + _ctrl_flags(0), + _app_port(12), + _link_check_requested(false), + _automatic_uplink_ongoing(false), + _ready_for_rx(true), + _queue(NULL) +{ +} + +void LoRaWANStack::bind_phy_and_radio_driver(LoRaRadio &radio, LoRaPHY &phy) +{ +} + +lorawan_status_t LoRaWANStack::initialize_mac_layer(EventQueue *queue) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::set_lora_callbacks(const lorawan_app_callbacks_t *callbacks) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::connect() +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::connect(const lorawan_connect_t &connect) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::add_channels(const lorawan_channelplan_t &channel_plan) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::remove_a_channel(uint8_t channel_id) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::drop_channel_list() +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::get_enabled_channels(lorawan_channelplan_t &channel_plan) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::set_confirmed_msg_retry(uint8_t count) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::set_channel_data_rate(uint8_t data_rate) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::enable_adaptive_datarate(bool adr_enabled) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::stop_sending(void) +{ + return LORAWAN_STATUS_OK; +} + +int16_t LoRaWANStack::handle_tx(const uint8_t port, const uint8_t *data, + uint16_t length, uint8_t flags, + bool null_allowed, bool allow_port_0) +{ + return 0; +} + +int16_t LoRaWANStack::handle_rx(uint8_t *data, uint16_t length, uint8_t &port, int &flags, bool validate_params) +{ + return 0; +} + +lorawan_status_t LoRaWANStack::set_link_check_request() +{ + return LORAWAN_STATUS_OK; +} + +void LoRaWANStack::remove_link_check_request() +{ +} + +lorawan_status_t LoRaWANStack::shutdown() +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::set_device_class(const device_class_t &device_class) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::acquire_tx_metadata(lorawan_tx_metadata &tx_metadata) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::acquire_rx_metadata(lorawan_rx_metadata &metadata) +{ + return LORAWAN_STATUS_OK; +} + +lorawan_status_t LoRaWANStack::acquire_backoff_metadata(int &backoff) +{ + return LORAWAN_STATUS_OK; +} + +/***************************************************************************** + * Interrupt handlers * + ****************************************************************************/ +void LoRaWANStack::tx_interrupt_handler(void) +{ +} + +void LoRaWANStack::rx_interrupt_handler(const uint8_t *payload, uint16_t size, + int16_t rssi, int8_t snr) +{ +} + +void LoRaWANStack::rx_error_interrupt_handler(void) +{ +} + +void LoRaWANStack::tx_timeout_interrupt_handler(void) +{ +} + +void LoRaWANStack::rx_timeout_interrupt_handler(void) +{ +} + +void LoRaWANStack::process_transmission_timeout() +{ +} + +void LoRaWANStack::process_transmission(void) +{ +} + +void post_process_tx_with_reception(void) +{ + +} + +void post_process_tx_no_reception(void) +{ + +} + +void LoRaWANStack::handle_scheduling_failure(void) +{ +} + +void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size, + int16_t rssi, int8_t snr) +{ +} + +void LoRaWANStack::process_reception_timeout(bool is_timeout) +{ +} + +void LoRaWANStack::make_tx_metadata_available(void) +{ +} + +void LoRaWANStack::make_rx_metadata_available(void) +{ +} + +bool LoRaWANStack::is_port_valid(const uint8_t port, bool allow_port_0) +{ + return true; +} + +lorawan_status_t LoRaWANStack::set_application_port(const uint8_t port, bool allow_port_0) +{ + return LORAWAN_STATUS_OK; +} + +void LoRaWANStack::state_machine_run_to_completion() +{ +} + +void LoRaWANStack::send_event_to_application(const lorawan_event_t event) const +{ +} + +void LoRaWANStack::send_automatic_uplink_message(const uint8_t port) +{ +} + +int LoRaWANStack::convert_to_msg_flag(const mcps_type_t type) +{ + return 0; +} + +lorawan_status_t LoRaWANStack::handle_connect(bool is_otaa) +{ + return LORAWAN_STATUS_OK; +} + +void LoRaWANStack::mlme_indication_handler() +{ +} + +void LoRaWANStack::mlme_confirm_handler() +{ +} + +void LoRaWANStack::mcps_confirm_handler() +{ +} + +void LoRaWANStack::mcps_indication_handler() +{ +} + +lorawan_status_t LoRaWANStack::state_controller(device_states_t new_state) +{ + return LORAWAN_STATUS_OK; +} + +void LoRaWANStack::process_shutdown_state(lorawan_status_t &op_status) +{ +} + +void LoRaWANStack::process_status_check_state() +{ +} + +void LoRaWANStack::process_scheduling_state(lorawan_status_t &op_status) +{ +} + +void LoRaWANStack::process_joining_state(lorawan_status_t &op_status) +{ +} + +void LoRaWANStack::process_connected_state() +{ +} + +void LoRaWANStack::process_connecting_state(lorawan_status_t &op_status) +{ +} + +void LoRaWANStack::process_idle_state(lorawan_status_t &op_status) +{ +} + +void LoRaWANStack::process_uninitialized_state(lorawan_status_t &op_status) +{ +} diff --git a/UNITTESTS/stubs/LoRaWANTimer_stub.cpp b/UNITTESTS/stubs/LoRaWANTimer_stub.cpp new file mode 100644 index 0000000000..4cbf21cdd8 --- /dev/null +++ b/UNITTESTS/stubs/LoRaWANTimer_stub.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) , 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. + */ + +#include "mbed_assert.h" +#include "LoRaWANTimer.h" + +#include "LoRaWANTimer_stub.h" + +lorawan_time_t LoRaWANTimer_stub::time_value = 0; +bool LoRaWANTimer_stub::call_cb_immediately = false; + +LoRaWANTimeHandler::LoRaWANTimeHandler() + : _queue(NULL) +{ +} + +LoRaWANTimeHandler::~LoRaWANTimeHandler() +{ +} + +void LoRaWANTimeHandler::activate_timer_subsystem(events::EventQueue *queue) +{ +} + +lorawan_time_t LoRaWANTimeHandler::get_current_time(void) +{ + return LoRaWANTimer_stub::time_value; +} + +lorawan_time_t LoRaWANTimeHandler::get_elapsed_time(lorawan_time_t saved_time) +{ + return LoRaWANTimer_stub::time_value; +} + +void LoRaWANTimeHandler::init(timer_event_t &obj, mbed::Callback callback) +{ + if (callback && LoRaWANTimer_stub::call_cb_immediately) { + callback(); + } + obj.timer_id = 1; +} + +void LoRaWANTimeHandler::start(timer_event_t &obj, const uint32_t timeout) +{ +} + +void LoRaWANTimeHandler::stop(timer_event_t &obj) +{ + obj.timer_id = 0; +} diff --git a/UNITTESTS/stubs/LoRaWANTimer_stub.h b/UNITTESTS/stubs/LoRaWANTimer_stub.h new file mode 100644 index 0000000000..0bc3db7396 --- /dev/null +++ b/UNITTESTS/stubs/LoRaWANTimer_stub.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) , 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. + */ + +#include "LoRaWANTimer.h" + +namespace LoRaWANTimer_stub { +extern lorawan_time_t time_value; +extern bool call_cb_immediately; +} diff --git a/UNITTESTS/stubs/MBRBlockDevice_stub.cpp b/UNITTESTS/stubs/MBRBlockDevice_stub.cpp index 1e12f59cee..449236be6e 100644 --- a/UNITTESTS/stubs/MBRBlockDevice_stub.cpp +++ b/UNITTESTS/stubs/MBRBlockDevice_stub.cpp @@ -1,5 +1,6 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited +/* + * Copyright (c) 2017, 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. @@ -54,8 +55,8 @@ static void tochs(uint32_t lba, uint8_t chs[3]) // Partition after address are turned into absolute // addresses, assumes bd is initialized static int partition_absolute( - BlockDevice *bd, int part, uint8_t type, - bd_size_t offset, bd_size_t size) + BlockDevice *bd, int part, uint8_t type, + bd_size_t offset, bd_size_t size) { return 0; } @@ -66,7 +67,7 @@ int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type, bd_addr_t } int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type, - bd_addr_t start, bd_addr_t stop) + bd_addr_t start, bd_addr_t stop) { return 0; } diff --git a/UNITTESTS/stubs/NetworkInterface_stub.cpp b/UNITTESTS/stubs/NetworkInterface_stub.cpp index 0e8eaa15a9..cfe6bdaa79 100644 --- a/UNITTESTS/stubs/NetworkInterface_stub.cpp +++ b/UNITTESTS/stubs/NetworkInterface_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Arm Limited and affiliates. + * Copyright (c) 2017, Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/NetworkStack_stub.cpp b/UNITTESTS/stubs/NetworkStack_stub.cpp index 372812effb..2d3a451a3c 100644 --- a/UNITTESTS/stubs/NetworkStack_stub.cpp +++ b/UNITTESTS/stubs/NetworkStack_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Arm Limited and affiliates. + * Copyright (c) 2017, Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/NetworkStack_stub.h b/UNITTESTS/stubs/NetworkStack_stub.h index 3a8955a6e0..43eda21ee9 100644 --- a/UNITTESTS/stubs/NetworkStack_stub.h +++ b/UNITTESTS/stubs/NetworkStack_stub.h @@ -47,10 +47,9 @@ public: protected: virtual nsapi_error_t socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto) { - if (return_value == NSAPI_ERROR_OK && return_values.front() == NSAPI_ERROR_OK) - { + if (return_value == NSAPI_ERROR_OK && return_values.front() == NSAPI_ERROR_OK) { // Make sure a non-NULL value is returned if error is not expected - *handle = reinterpret_cast(1234); + *handle = reinterpret_cast(1234); } return return_value; }; @@ -68,8 +67,7 @@ protected: }; virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address) { - if (!return_values.empty()) - { + if (!return_values.empty()) { nsapi_error_t ret = return_values.front(); return_values.pop_front(); return ret; @@ -84,8 +82,7 @@ protected: virtual nsapi_size_or_error_t socket_send(nsapi_socket_t handle, const void *data, nsapi_size_t size) { - if (!return_values.empty()) - { + if (!return_values.empty()) { nsapi_error_t ret = return_values.front(); return_values.pop_front(); return ret; @@ -95,8 +92,7 @@ protected: virtual nsapi_size_or_error_t socket_recv(nsapi_socket_t handle, void *data, nsapi_size_t size) { - if (!return_values.empty()) - { + if (!return_values.empty()) { nsapi_error_t ret = return_values.front(); return_values.pop_front(); return ret; @@ -111,8 +107,7 @@ protected: virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *buffer, nsapi_size_t size) { - if (!return_values.empty()) - { + if (!return_values.empty()) { nsapi_error_t ret = return_values.front(); return_values.pop_front(); return ret; diff --git a/UNITTESTS/stubs/ObservingBlockDevice_stub.cpp b/UNITTESTS/stubs/ObservingBlockDevice_stub.cpp index ffd9450a83..550bf722a3 100644 --- a/UNITTESTS/stubs/ObservingBlockDevice_stub.cpp +++ b/UNITTESTS/stubs/ObservingBlockDevice_stub.cpp @@ -1,23 +1,18 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017-2017 ARM Limited +/* + * Copyright (c) 2017, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: + * 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 * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * 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. */ #include "ObservingBlockDevice.h" diff --git a/UNITTESTS/stubs/ProfilingBlockDevice_stub.cpp b/UNITTESTS/stubs/ProfilingBlockDevice_stub.cpp index df41cb1da5..52a94fa5b1 100644 --- a/UNITTESTS/stubs/ProfilingBlockDevice_stub.cpp +++ b/UNITTESTS/stubs/ProfilingBlockDevice_stub.cpp @@ -1,5 +1,6 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited +/* + * Copyright (c) 2017, 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. diff --git a/UNITTESTS/stubs/ReadOnlyBlockDevice_stub.cpp b/UNITTESTS/stubs/ReadOnlyBlockDevice_stub.cpp index 13e20d934e..17a42915bb 100644 --- a/UNITTESTS/stubs/ReadOnlyBlockDevice_stub.cpp +++ b/UNITTESTS/stubs/ReadOnlyBlockDevice_stub.cpp @@ -1,23 +1,18 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017-2017 ARM Limited +/* + * Copyright (c) , Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: + * 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 * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * 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. */ #include "ReadOnlyBlockDevice.h" diff --git a/UNITTESTS/stubs/SlicingBlockDevice_stub.cpp b/UNITTESTS/stubs/SlicingBlockDevice_stub.cpp index 6b4fbabdcf..d0b75ee194 100644 --- a/UNITTESTS/stubs/SlicingBlockDevice_stub.cpp +++ b/UNITTESTS/stubs/SlicingBlockDevice_stub.cpp @@ -1,5 +1,6 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited +/* + * Copyright (c) , 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. @@ -19,7 +20,7 @@ SlicingBlockDevice::SlicingBlockDevice(BlockDevice *bd, bd_addr_t start, bd_addr_t stop) { - + } int SlicingBlockDevice::init() diff --git a/UNITTESTS/stubs/SocketAddress_stub.cpp b/UNITTESTS/stubs/SocketAddress_stub.cpp index 9ed53f03cf..874e5ce667 100644 --- a/UNITTESTS/stubs/SocketAddress_stub.cpp +++ b/UNITTESTS/stubs/SocketAddress_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/mbed_assert_stub.cpp b/UNITTESTS/stubs/ThisThread_stub.cpp similarity index 87% rename from UNITTESTS/stubs/mbed_assert_stub.cpp rename to UNITTESTS/stubs/ThisThread_stub.cpp index 341881a7f5..28eb18fa8b 100644 --- a/UNITTESTS/stubs/mbed_assert_stub.cpp +++ b/UNITTESTS/stubs/ThisThread_stub.cpp @@ -15,10 +15,12 @@ * limitations under the License. */ -#include "mbed_assert.h" +#include "rtos/ThisThread.h" -void mbed_assert_internal(const char *expr, const char *file, int line) +namespace rtos { + +void ThisThread::sleep_until(uint64_t millisec) { - } +} diff --git a/UNITTESTS/stubs/Timer_stub.h b/UNITTESTS/stubs/Timer_stub.h index 699fdd0c53..a97333fe63 100644 --- a/UNITTESTS/stubs/Timer_stub.h +++ b/UNITTESTS/stubs/Timer_stub.h @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef TIMER_STUB_H #define TIMER_STUB_H diff --git a/UNITTESTS/stubs/aes_stub.c b/UNITTESTS/stubs/aes_stub.c new file mode 100644 index 0000000000..2aa4faeb29 --- /dev/null +++ b/UNITTESTS/stubs/aes_stub.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) , 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. + */ + + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#include "mbedtls/aes.h" + +#include "aes_stub.h" +aes_stub_def aes_stub; + + +void mbedtls_aes_init(mbedtls_aes_context *ctx) +{ +} + +void mbedtls_aes_free(mbedtls_aes_context *ctx) +{ +} + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +void mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx) +{ +} + +void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx) +{ +} +#endif + +#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) +int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} +#endif + +#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) +int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} +#endif + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} + +int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} +#endif + +int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} + +void mbedtls_aes_encrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ +} + +int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} + +void mbedtls_aes_decrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ +} + +int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16]) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} + +int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} + + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} +#endif + +int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} + +int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} + +int mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} + +int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output) +{ + if (aes_stub.int_zero_counter) { + aes_stub.int_zero_counter--; + return 0; + } + return aes_stub.int_value; +} diff --git a/UNITTESTS/stubs/aes_stub.h b/UNITTESTS/stubs/aes_stub.h new file mode 100644 index 0000000000..c361b0a031 --- /dev/null +++ b/UNITTESTS/stubs/aes_stub.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) , 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. + */ + + +#include + +typedef struct { + int int_value; + uint8_t int_zero_counter; +} aes_stub_def; + +extern aes_stub_def aes_stub; diff --git a/UNITTESTS/stubs/cipher_stub.c b/UNITTESTS/stubs/cipher_stub.c new file mode 100644 index 0000000000..d6fc38ff9c --- /dev/null +++ b/UNITTESTS/stubs/cipher_stub.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) , 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. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" +#include "mbedtls/cipher_internal.h" +#include "mbedtls/platform_util.h" + +#include +#include + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#include "cipher_stub.h" + +cipher_stub_def cipher_stub; + +const int *mbedtls_cipher_list(void) +{ + return cipher_stub.int_ptr; +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(const mbedtls_cipher_type_t cipher_type) +{ + return cipher_stub.info_value; +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(const char *cipher_name) +{ + return cipher_stub.info_value; +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode) +{ + return cipher_stub.info_value; +} + +void mbedtls_cipher_init(mbedtls_cipher_context_t *ctx) +{ +} + +void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx) +{ +} + +int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + +int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, const unsigned char *key, + int key_bitlen, const mbedtls_operation_t operation) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + +int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + +int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + +int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + +int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + +int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + +int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + +int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + +int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + +int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + +int mbedtls_cipher_auth_encrypt(mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + +int mbedtls_cipher_auth_decrypt(mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len) +{ + if (cipher_stub.int_zero_counter) { + cipher_stub.int_zero_counter--; + return 0; + } + return cipher_stub.int_value; +} + diff --git a/UNITTESTS/stubs/cipher_stub.h b/UNITTESTS/stubs/cipher_stub.h new file mode 100644 index 0000000000..9a16f04666 --- /dev/null +++ b/UNITTESTS/stubs/cipher_stub.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) , 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. + */ + +#include +#include "mbedtls/cipher.h" + +typedef struct { + mbedtls_cipher_info_t *info_value; + int int_value; + int *int_ptr; + uint8_t int_zero_counter; +} cipher_stub_def; + +extern cipher_stub_def cipher_stub; diff --git a/UNITTESTS/stubs/cmac_stub.c b/UNITTESTS/stubs/cmac_stub.c new file mode 100644 index 0000000000..8ecd5709cd --- /dev/null +++ b/UNITTESTS/stubs/cmac_stub.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) , 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. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + + +#include "mbedtls/cmac.h" +#include "mbedtls/platform_util.h" +#include + +#include "cmac_stub.h" + +cmac_stub_def cmac_stub; + +int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits) +{ + if (cmac_stub.int_zero_counter) { + cmac_stub.int_zero_counter--; + return 0; + } + return cmac_stub.int_value; +} + +int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen) +{ + if (cmac_stub.int_zero_counter) { + cmac_stub.int_zero_counter--; + return 0; + } + return cmac_stub.int_value; +} + +int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx, + unsigned char *output) +{ + if (cmac_stub.int_zero_counter) { + cmac_stub.int_zero_counter--; + return 0; + } + return cmac_stub.int_value; +} + +int mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx) +{ + if (cmac_stub.int_zero_counter) { + cmac_stub.int_zero_counter--; + return 0; + } + return cmac_stub.int_value; +} + +int mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output) +{ + if (cmac_stub.int_zero_counter) { + cmac_stub.int_zero_counter--; + return 0; + } + return cmac_stub.int_value; +} + +int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_length, + const unsigned char *input, size_t in_len, + unsigned char *output) +{ + if (cmac_stub.int_zero_counter) { + cmac_stub.int_zero_counter--; + return 0; + } + return cmac_stub.int_value; +} + diff --git a/UNITTESTS/stubs/cmac_stub.h b/UNITTESTS/stubs/cmac_stub.h new file mode 100644 index 0000000000..4134f9d6cf --- /dev/null +++ b/UNITTESTS/stubs/cmac_stub.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) , 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. + */ + + +#include + +typedef struct { + int int_value; + uint8_t int_zero_counter; +} cmac_stub_def; + +extern cmac_stub_def cmac_stub; diff --git a/UNITTESTS/stubs/equeue_stub.c b/UNITTESTS/stubs/equeue_stub.c index cbda94c36b..40cdcd65b0 100644 --- a/UNITTESTS/stubs/equeue_stub.c +++ b/UNITTESTS/stubs/equeue_stub.c @@ -18,6 +18,10 @@ #include "equeue.h" #include +#include "equeue_stub.h" + +equeue_stub_def equeue_stub; + int equeue_create(equeue_t *queue, size_t size) { return 0; @@ -55,7 +59,7 @@ int equeue_call_every(equeue_t *queue, int ms, void (*cb)(void *), void *data) void *equeue_alloc(equeue_t *queue, size_t size) { - return malloc(size); + return equeue_stub.void_ptr; } void equeue_dealloc(equeue_t *queue, void *event) @@ -80,11 +84,10 @@ void equeue_event_dtor(void *event, void (*dtor)(void *)) int equeue_post(equeue_t *queue, void (*cb)(void *), void *event) { - if (cb) - { - cb(event); - free(event); - return 1; //Fake ID for calling cancel + struct equeue_event *e = (struct equeue_event *)event - 1; + if (cb && equeue_stub.call_cb_immediately) { + cb(e + 1); + return 1; } return 0; } @@ -105,7 +108,8 @@ void equeue_chain(equeue_t *queue, equeue_t *target) } -int equeue_call_in(equeue_t *q, int ms, void (*cb)(void*), void *data) { +int equeue_call_in(equeue_t *q, int ms, void (*cb)(void *), void *data) +{ // The stub does not implement the delay mechanism. return equeue_post(q, cb, data); } diff --git a/UNITTESTS/stubs/equeue_stub.h b/UNITTESTS/stubs/equeue_stub.h new file mode 100644 index 0000000000..648d920058 --- /dev/null +++ b/UNITTESTS/stubs/equeue_stub.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) , 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. + */ + +#include "stdint.h" +#include "stdbool.h" + +typedef struct { + void *void_ptr; + bool call_cb_immediately; +} equeue_stub_def; + +extern equeue_stub_def equeue_stub; diff --git a/UNITTESTS/stubs/ip4tos_stub.c b/UNITTESTS/stubs/ip4tos_stub.c index 35957fe232..c45c1383bb 100644 --- a/UNITTESTS/stubs/ip4tos_stub.c +++ b/UNITTESTS/stubs/ip4tos_stub.c @@ -1,18 +1,20 @@ /* - * Copyright (c) 2014-2018 ARM Limited. All rights reserved. + * Copyright (c) , 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. + * + * 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 + * 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. + * 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. */ + #include #include #include "common_functions.h" diff --git a/UNITTESTS/stubs/mbed_assert_stub.c b/UNITTESTS/stubs/mbed_assert_stub.c index 9029a6192d..afe6fb3ff3 100644 --- a/UNITTESTS/stubs/mbed_assert_stub.c +++ b/UNITTESTS/stubs/mbed_assert_stub.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Arm Limited and affiliates. + * Copyright (c) , Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/mbed_critical_stub.c b/UNITTESTS/stubs/mbed_critical_stub.c index f812764382..ca08e252d4 100644 --- a/UNITTESTS/stubs/mbed_critical_stub.c +++ b/UNITTESTS/stubs/mbed_critical_stub.c @@ -1,16 +1,16 @@ /* - * Copyright (c) 2015-2016, ARM Limited, All Rights Reserved + * Copyright (c) 2017, 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. + * 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 + * 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. + * 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. */ diff --git a/UNITTESTS/stubs/mbed_poll_stub.cpp b/UNITTESTS/stubs/mbed_poll_stub.cpp index 1914399d2a..4db534ed10 100644 --- a/UNITTESTS/stubs/mbed_poll_stub.cpp +++ b/UNITTESTS/stubs/mbed_poll_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) , Arm Limited and affiliates. + * Copyright (c) 2017, Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/mbed_poll_stub.h b/UNITTESTS/stubs/mbed_poll_stub.h index 6c0a4327a9..930766e840 100644 --- a/UNITTESTS/stubs/mbed_poll_stub.h +++ b/UNITTESTS/stubs/mbed_poll_stub.h @@ -1,5 +1,5 @@ /* - * Copyright (c) , Arm Limited and affiliates. + * Copyright (c) 2017, Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef __MBED_POLL_STUB_H__ #define __MBED_POLL_STUB_H__ diff --git a/UNITTESTS/stubs/mbed_wait_api_stub.cpp b/UNITTESTS/stubs/mbed_wait_api_stub.cpp index f8b240544d..68a265308c 100644 --- a/UNITTESTS/stubs/mbed_wait_api_stub.cpp +++ b/UNITTESTS/stubs/mbed_wait_api_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) , Arm Limited and affiliates. + * Copyright (c) 2017, Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/UNITTESTS/stubs/nvic_wrapper_stub.c b/UNITTESTS/stubs/nvic_wrapper_stub.c index 636f05bae5..9cd88195c0 100644 --- a/UNITTESTS/stubs/nvic_wrapper_stub.c +++ b/UNITTESTS/stubs/nvic_wrapper_stub.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017, 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. + */ + #include "nvic_wrapper.h" void NVIC_SystemReset(void) {} diff --git a/UNITTESTS/stubs/randLIB_stub.c b/UNITTESTS/stubs/randLIB_stub.c index 97154cf2ee..e9fd486adb 100644 --- a/UNITTESTS/stubs/randLIB_stub.c +++ b/UNITTESTS/stubs/randLIB_stub.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017, Arm Limited and affiliates. + * Copyright (c) 2017, Arm Limited and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include #include #include diff --git a/UNITTESTS/stubs/randLIB_stub.cpp b/UNITTESTS/stubs/randLIB_stub.cpp index 61cd893d0e..28989c444e 100644 --- a/UNITTESTS/stubs/randLIB_stub.cpp +++ b/UNITTESTS/stubs/randLIB_stub.cpp @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "randLIB.h" void randLIB_seed_random(void) diff --git a/UNITTESTS/stubs/stoip4_stub.c b/UNITTESTS/stubs/stoip4_stub.c index d22c20e23e..9cb8036577 100644 --- a/UNITTESTS/stubs/stoip4_stub.c +++ b/UNITTESTS/stubs/stoip4_stub.c @@ -1,18 +1,20 @@ /* - * Copyright (c) 2014-2018 ARM Limited. All rights reserved. + * Copyright (c) , 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. + * + * 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 + * 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. + * 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. */ + #include #include #include diff --git a/UNITTESTS/target_h/cmsis_os2.h b/UNITTESTS/target_h/cmsis_os2.h index c2a601fb16..c45760f27b 100644 --- a/UNITTESTS/target_h/cmsis_os2.h +++ b/UNITTESTS/target_h/cmsis_os2.h @@ -51,12 +51,12 @@ typedef struct { } osThreadAttr_t; #define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value. - + // Flags options (\ref osThreadFlagsWait and \ref osEventFlagsWait). #define osFlagsWaitAny 0x00000000U ///< Wait for any flag (default). #define osFlagsWaitAll 0x00000001U ///< Wait for all flags. #define osFlagsNoClear 0x00000002U ///< Do not clear flags which have been specified to wait for. - + // Flags errors (returned by osThreadFlagsXxxx and osEventFlagsXxxx). #define osFlagsError 0x80000000U ///< Error indicator. #define osFlagsErrorUnknown 0xFFFFFFFFU ///< osError (-1). @@ -64,11 +64,11 @@ typedef struct { #define osFlagsErrorResource 0xFFFFFFFDU ///< osErrorResource (-3). #define osFlagsErrorParameter 0xFFFFFFFCU ///< osErrorParameter (-4). #define osFlagsErrorISR 0xFFFFFFFAU ///< osErrorISR (-6). - + // Thread attributes (attr_bits in \ref osThreadAttr_t). #define osThreadDetached 0x00000000U ///< Thread created in detached mode (default) #define osThreadJoinable 0x00000001U ///< Thread created in joinable mode - + // Mutex attributes (attr_bits in \ref osMutexAttr_t). #define osMutexRecursive 0x00000001U ///< Recursive mutex. #define osMutexPrioInherit 0x00000002U ///< Priority inherit protocol. diff --git a/UNITTESTS/target_h/rtos.h b/UNITTESTS/target_h/rtos.h new file mode 100644 index 0000000000..b6246789a6 --- /dev/null +++ b/UNITTESTS/target_h/rtos.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018, 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. + */ + +#ifndef RTOS_H +#define RTOS_H + +typedef enum { + osTimerOnce = 0, ///< One-shot timer. + osTimerPeriodic = 1 ///< Repeating timer. +} os_timer_type; + +#endif /* RTOS_H */ diff --git a/UNITTESTS/target_h/rtos/Mutex.h b/UNITTESTS/target_h/rtos/Mutex.h index a804e17212..4f38c37fe0 100644 --- a/UNITTESTS/target_h/rtos/Mutex.h +++ b/UNITTESTS/target_h/rtos/Mutex.h @@ -28,7 +28,7 @@ public: Mutex(const char *name); - osStatus lock(uint32_t millisec=osWaitForever); + osStatus lock(uint32_t millisec = osWaitForever); bool trylock(); diff --git a/UNITTESTS/target_h/rtx_os.h b/UNITTESTS/target_h/rtx_os.h index dfa7082fa1..f280c6733f 100644 --- a/UNITTESTS/target_h/rtx_os.h +++ b/UNITTESTS/target_h/rtx_os.h @@ -58,13 +58,13 @@ typedef struct osRtxThread_s { } osRtxThread_t; typedef struct { - uint8_t id; ///< Object Identifier - uint8_t state; ///< Object State - uint8_t flags; ///< Object Flags - uint8_t reserved; - const char *name; ///< Object Name - osRtxThread_t *thread_list; ///< Waiting Threads List - uint32_t event_flags; ///< Event Flags + uint8_t id; ///< Object Identifier + uint8_t state; ///< Object State + uint8_t flags; ///< Object Flags + uint8_t reserved; + const char *name; ///< Object Name + osRtxThread_t *thread_list; ///< Waiting Threads List + uint32_t event_flags; ///< Event Flags } osRtxEventFlags_t; #endif diff --git a/astyle-branch.out b/astyle-branch.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/rtos/TARGET_CORTEX/TARGET_CORTEX_M/TOOLCHAIN_ARM/except.S b/cmsis/TARGET_CORTEX_M/TOOLCHAIN_ARM/except.S similarity index 97% rename from rtos/TARGET_CORTEX/TARGET_CORTEX_M/TOOLCHAIN_ARM/except.S rename to cmsis/TARGET_CORTEX_M/TOOLCHAIN_ARM/except.S index 71607bf0b7..9eaf7e8aff 100644 --- a/rtos/TARGET_CORTEX/TARGET_CORTEX_M/TOOLCHAIN_ARM/except.S +++ b/cmsis/TARGET_CORTEX_M/TOOLCHAIN_ARM/except.S @@ -68,7 +68,6 @@ UsageFault_Handler\ Fault_Handler PROC EXPORT Fault_Handler #if (DOMAIN_NS == 1) - IMPORT osRtxInfo IMPORT mbed_fault_handler IMPORT mbed_fault_context @@ -149,11 +148,9 @@ Fault_Handler_Continue2 ADDS R1,#4 MRS R2,CONTROL ; Get CONTROL Reg STR R2,[R1] - LDR R3,=mbed_fault_handler ; Load address of mbedFaultHandler MOV R0,R12 LDR R1,=mbed_fault_context - LDR R2,=osRtxInfo - BLX R3 + BL mbed_fault_handler #endif B . ; Just in case we come back here ENDP diff --git a/rtos/TARGET_CORTEX/TARGET_CORTEX_M/TOOLCHAIN_GCC/except.S b/cmsis/TARGET_CORTEX_M/TOOLCHAIN_GCC/except.S similarity index 97% rename from rtos/TARGET_CORTEX/TARGET_CORTEX_M/TOOLCHAIN_GCC/except.S rename to cmsis/TARGET_CORTEX_M/TOOLCHAIN_GCC/except.S index 2266d07223..fdd3844896 100644 --- a/rtos/TARGET_CORTEX/TARGET_CORTEX_M/TOOLCHAIN_GCC/except.S +++ b/cmsis/TARGET_CORTEX_M/TOOLCHAIN_GCC/except.S @@ -181,11 +181,9 @@ Fault_Handler_Continue2: ADDS R1,#4 MRS R2,CONTROL // Get CONTROL Reg STR R2,[R1] - LDR R3,=mbed_fault_handler // Load address of mbedFaultHandler MOV R0,R12 LDR R1,=mbed_fault_context - LDR R2,=osRtxInfo - BLX R3 + BL mbed_fault_handler #endif B . // Just in case we come back here diff --git a/rtos/TARGET_CORTEX/TARGET_CORTEX_M/TOOLCHAIN_IAR/except.S b/cmsis/TARGET_CORTEX_M/TOOLCHAIN_IAR/except.S similarity index 97% rename from rtos/TARGET_CORTEX/TARGET_CORTEX_M/TOOLCHAIN_IAR/except.S rename to cmsis/TARGET_CORTEX_M/TOOLCHAIN_IAR/except.S index d76fb473fb..e6cf1ba6fb 100644 --- a/rtos/TARGET_CORTEX/TARGET_CORTEX_M/TOOLCHAIN_IAR/except.S +++ b/cmsis/TARGET_CORTEX_M/TOOLCHAIN_IAR/except.S @@ -63,7 +63,6 @@ UsageFault_Handler Fault_Handler EXPORT Fault_Handler #if (DOMAIN_NS == 1) - IMPORT osRtxInfo IMPORT mbed_fault_context IMPORT mbed_fault_handler @@ -144,11 +143,9 @@ Fault_Handler_Continue2 ADDS R1,#4 MRS R2,CONTROL ; Get CONTROL Reg STR R2,[R1] - LDR R3,=mbed_fault_handler ; Load address of mbedFaultHandler MOV R0,R12 LDR R1,=mbed_fault_context - LDR R2,=osRtxInfo - BLX R3 + BL mbed_fault_handler #endif B . ; Just in case we come back here #endif ; #if (MBED_FAULT_HANDLER_SUPPORT == 1) diff --git a/rtos/TARGET_CORTEX/TARGET_CORTEX_M/mbed_rtx_fault_handler.c b/cmsis/TARGET_CORTEX_M/mbed_fault_handler.c similarity index 79% rename from rtos/TARGET_CORTEX/TARGET_CORTEX_M/mbed_rtx_fault_handler.c rename to cmsis/TARGET_CORTEX_M/mbed_fault_handler.c index d9545b3f91..c56ad0d45f 100644 --- a/rtos/TARGET_CORTEX/TARGET_CORTEX_M/mbed_rtx_fault_handler.c +++ b/cmsis/TARGET_CORTEX_M/mbed_fault_handler.c @@ -14,14 +14,17 @@ * limitations under the License. */ -#include "rtx_os.h" +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#include + #include "device.h" #include "platform/mbed_error.h" #include "platform/mbed_interface.h" -#include "hal/serial_api.h" #ifndef MBED_FAULT_HANDLER_DISABLED -#include "mbed_rtx_fault_handler.h" +#include "mbed_fault_handler.h" //Functions Prototypes void print_context_info(void); @@ -31,7 +34,7 @@ mbed_fault_context_t mbed_fault_context; //This is a handler function called from Fault handler to print the error information out. //This runs in fault context and uses special functions(defined in mbed_rtx_fault_handler.c) to print the information without using C-lib support. -void mbed_fault_handler (uint32_t fault_type, void *mbed_fault_context_in, void *osRtxInfoIn) +void mbed_fault_handler (uint32_t fault_type, void *mbed_fault_context_in) { mbed_error_status_t faultStatus = MBED_SUCCESS; @@ -74,37 +77,37 @@ MBED_NOINLINE void print_context_info(void) { //Context Regs for(int i=0;i<13;i++) { - mbed_error_printf("\nR%-4d: %08X", i, ((uint32_t *)&mbed_fault_context)[i]); + mbed_error_printf("\nR%-4d: %08" PRIX32, i, ((uint32_t *)&mbed_fault_context)[i]); } - mbed_error_printf("\nSP : %08X" - "\nLR : %08X" - "\nPC : %08X" - "\nxPSR : %08X" - "\nPSP : %08X" - "\nMSP : %08X", mbed_fault_context.SP_reg, mbed_fault_context.LR_reg, mbed_fault_context.PC_reg, + mbed_error_printf("\nSP : %08" PRIX32 + "\nLR : %08" PRIX32 + "\nPC : %08" PRIX32 + "\nxPSR : %08" PRIX32 + "\nPSP : %08" PRIX32 + "\nMSP : %08" PRIX32, mbed_fault_context.SP_reg, mbed_fault_context.LR_reg, mbed_fault_context.PC_reg, mbed_fault_context.xPSR, mbed_fault_context.PSP, mbed_fault_context.MSP ); //Capture CPUID to get core/cpu info - mbed_error_printf("\nCPUID: %08X", SCB->CPUID); + mbed_error_printf("\nCPUID: %08" PRIX32, SCB->CPUID); #if !defined(TARGET_M0) && !defined(TARGET_M0P) //Capture fault information registers to infer the cause of exception - mbed_error_printf("\nHFSR : %08X" - "\nMMFSR: %08X" - "\nBFSR : %08X" - "\nUFSR : %08X" - "\nDFSR : %08X" - "\nAFSR : %08X" ////Split/Capture CFSR into MMFSR, BFSR, UFSR + mbed_error_printf("\nHFSR : %08" PRIX32 + "\nMMFSR: %08" PRIX32 + "\nBFSR : %08" PRIX32 + "\nUFSR : %08" PRIX32 + "\nDFSR : %08" PRIX32 + "\nAFSR : %08" PRIX32 ////Split/Capture CFSR into MMFSR, BFSR, UFSR ,SCB->HFSR, (0xFF & SCB->CFSR), ((0xFF00 & SCB->CFSR) >> 8), ((0xFFFF0000 & SCB->CFSR) >> 16), SCB->DFSR, SCB->AFSR ); //Print MMFAR only if its valid as indicated by MMFSR if ((0xFF & SCB->CFSR) & 0x80) { - mbed_error_printf("\nMMFAR: %08X",SCB->MMFAR); + mbed_error_printf("\nMMFAR: %08" PRIX32, SCB->MMFAR); } //Print BFAR only if its valid as indicated by BFSR if (((0xFF00 & SCB->CFSR) >> 8) & 0x80) { - mbed_error_printf("\nBFAR : %08X",SCB->BFAR); + mbed_error_printf("\nBFAR : %08" PRIX32, SCB->BFAR); } #endif diff --git a/rtos/TARGET_CORTEX/TARGET_CORTEX_M/mbed_rtx_fault_handler.h b/cmsis/TARGET_CORTEX_M/mbed_fault_handler.h similarity index 91% rename from rtos/TARGET_CORTEX/TARGET_CORTEX_M/mbed_rtx_fault_handler.h rename to cmsis/TARGET_CORTEX_M/mbed_fault_handler.h index 2039f0bcd0..bcc3ded135 100644 --- a/rtos/TARGET_CORTEX/TARGET_CORTEX_M/mbed_rtx_fault_handler.h +++ b/cmsis/TARGET_CORTEX_M/mbed_fault_handler.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef MBED_RTX_FAULT_HANDLER_H -#define MBED_RTX_FAULT_HANDLER_H +#ifndef MBED_FAULT_HANDLER_H +#define MBED_FAULT_HANDLER_H //Fault context struct //WARNING: DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES in except.S files. @@ -52,7 +52,7 @@ typedef struct { #define USAGE_FAULT_EXCEPTION (0x40) //This is a handler function called from Fault handler to print the error information out. -//This runs in fault context and uses special functions(defined in mbed_rtx_fault_handler.c) to print the information without using C-lib support. -void mbed_fault_handler (uint32_t fault_type, void *mbed_fault_context_in, void *osRtxInfoIn); +//This runs in fault context and uses special functions(defined in mbed_fault_handler.c) to print the information without using C-lib support. +void mbed_fault_handler (uint32_t fault_type, void *mbed_fault_context_in); #endif diff --git a/cmsis/TARGET_CORTEX_M/mpu_armv7.h b/cmsis/TARGET_CORTEX_M/mpu_armv7.h index 01422033d0..03b4c68568 100644 --- a/cmsis/TARGET_CORTEX_M/mpu_armv7.h +++ b/cmsis/TARGET_CORTEX_M/mpu_armv7.h @@ -1,8 +1,8 @@ /****************************************************************************** * @file mpu_armv7.h * @brief CMSIS MPU API for Armv7-M MPU - * @version V5.0.4 - * @date 10. January 2018 + * @version V5.0.5 + * @date 06. September 2018 ******************************************************************************/ /* * Copyright (c) 2017-2018 Arm Limited. All rights reserved. @@ -86,10 +86,10 @@ * \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. */ #define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \ - ((((TypeExtField ) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ - (((IsShareable ) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ - (((IsCacheable ) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ - (((IsBufferable ) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) + ((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ + (((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ + (((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ + (((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) /** * MPU Region Attribute and Size Register Value @@ -100,11 +100,14 @@ * \param SubRegionDisable Sub-region disable field. * \param Size Region size of the region to be configured, for example 4K, 8K. */ -#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ - ((((DisableExec ) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ - (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ - (((AccessAttributes) ) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) - +#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ + ((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ + (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ + (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \ + (((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \ + (((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \ + (((MPU_RASR_ENABLE_Msk)))) + /** * MPU Region Attribute and Size Register Value * diff --git a/components/802.15.4_RF/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h b/components/802.15.4_RF/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h index 664d537770..0adcb7c308 100644 --- a/components/802.15.4_RF/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h +++ b/components/802.15.4_RF/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h @@ -20,7 +20,7 @@ #include "at24mac.h" #include "PinNames.h" -#if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI +#if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI && DEVICE_I2C #include "NanostackRfPhy.h" @@ -58,8 +58,8 @@ class RFBits; class NanostackRfPhyAtmel : public NanostackRfPhy { public: NanostackRfPhyAtmel(PinName spi_mosi, PinName spi_miso, - PinName spi_sclk, PinName spi_cs, PinName spi_rst, PinName spi_slp, PinName spi_irq, - PinName i2c_sda, PinName i2c_scl); + PinName spi_sclk, PinName spi_cs, PinName spi_rst, PinName spi_slp, PinName spi_irq, + PinName i2c_sda, PinName i2c_scl); virtual ~NanostackRfPhyAtmel(); virtual int8_t rf_register(); virtual void rf_unregister(); diff --git a/components/802.15.4_RF/atmel-rf-driver/mbed_lib.json b/components/802.15.4_RF/atmel-rf-driver/mbed_lib.json index 9d8424f2d5..e44a0dc527 100644 --- a/components/802.15.4_RF/atmel-rf-driver/mbed_lib.json +++ b/components/802.15.4_RF/atmel-rf-driver/mbed_lib.json @@ -24,6 +24,10 @@ "provide-default": { "help": "Provide default NanostackRfpy. [true/false]", "value": false + }, + "irq-thread-stack-size": { + "help": "The stack size of the Thread serving the Atmel RF interrupts", + "value": 1024 } }, "target_overrides": { diff --git a/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp b/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp index 86db3ab3ee..89652958bb 100644 --- a/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp +++ b/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp @@ -15,7 +15,7 @@ */ #include -#if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI +#if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI && DEVICE_I2C #include "platform/arm_hal_interrupt.h" #include "nanostack/platform/arm_hal_phy.h" @@ -50,25 +50,22 @@ #define RFF_TX 0x04 #define RFF_CCA 0x08 -typedef enum -{ +typedef enum { RF_MODE_NORMAL = 0, RF_MODE_SNIFFER = 1, RF_MODE_ED = 2 -}rf_mode_t; +} rf_mode_t; /*Atmel RF Part Type*/ -typedef enum -{ +typedef enum { ATMEL_UNKNOW_DEV = 0, ATMEL_AT86RF212, ATMEL_AT86RF231, // No longer supported (doesn't give ED+status on frame read) ATMEL_AT86RF233 -}rf_trx_part_e; +} rf_trx_part_e; /*Atmel RF states*/ -typedef enum -{ +typedef enum { NOP = 0x00, BUSY_RX = 0x01, BUSY_TX = 0x02, @@ -83,7 +80,7 @@ typedef enum RX_AACK_ON = 0x16, TX_ARET_ON = 0x19, STATE_TRANSITION_IN_PROGRESS = 0x1F -}rf_trx_states_t; +} rf_trx_states_t; static const uint8_t *rf_tx_data; // Points to Nanostack's buffer static uint8_t rf_tx_length; @@ -109,9 +106,9 @@ static const phy_rf_channel_configuration_s phy_24ghz = {2405000000U, 5000000U, static const phy_rf_channel_configuration_s phy_subghz = {868300000U, 2000000U, 250000U, 11U, M_OQPSK}; static const phy_device_channel_page_s phy_channel_pages[] = { - { CHANNEL_PAGE_0, &phy_24ghz}, - { CHANNEL_PAGE_2, &phy_subghz}, - { CHANNEL_PAGE_0, NULL} + { CHANNEL_PAGE_0, &phy_24ghz}, + { CHANNEL_PAGE_2, &phy_subghz}, + { CHANNEL_PAGE_0, NULL} }; /** @@ -156,7 +153,7 @@ static rf_trx_states_t rf_poll_trx_state_change(rf_trx_states_t trx_state); static void rf_init(void); static int8_t rf_device_register(const uint8_t *mac_addr); static void rf_device_unregister(void); -static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol ); +static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol); static void rf_cca_abort(void); static void rf_calibration_cb(void); static void rf_init_phy_mode(void); @@ -168,8 +165,8 @@ static void rf_cca_timer_start(uint32_t slots); static uint8_t rf_scale_lqi(int8_t rssi); static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel); -static int8_t rf_extension(phy_extension_type_e extension_type,uint8_t *data_ptr); -static int8_t rf_address_write(phy_address_type_e address_type,uint8_t *address_ptr); +static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr); +static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr); static void rf_if_cca_timer_start(uint32_t slots); static void rf_if_enable_promiscuous_mode(void); @@ -214,12 +211,14 @@ static void rf_if_spi_exchange_n(const void *tx, size_t tx_len, void *rx, size_t static inline rf_trx_states_t rf_if_trx_status_from_full(uint8_t full_trx_status) { - return (rf_trx_states_t) (full_trx_status & 0x1F); + return (rf_trx_states_t)(full_trx_status & 0x1F); } #ifdef MBED_CONF_RTOS_PRESENT #include "mbed.h" #include "rtos.h" +using namespace mbed; +using namespace rtos; static void rf_if_irq_task_process_irq(); @@ -271,7 +270,7 @@ RFBits::RFBits(PinName spi_mosi, PinName spi_miso, SLP_TR(spi_slp), IRQ(spi_irq) #ifdef MBED_CONF_RTOS_PRESENT -,irq_thread(osPriorityRealtime, 1024) + , irq_thread(osPriorityRealtime, MBED_CONF_ATMEL_RF_IRQ_THREAD_STACK_SIZE, NULL, "atmel_irq_thread") #endif { #ifdef MBED_CONF_RTOS_PRESENT @@ -297,21 +296,21 @@ static void rf_if_unlock(void) #ifdef MBED_CONF_RTOS_PRESENT static void rf_if_cca_timer_signal(void) { - rf->irq_thread.signal_set(SIG_TIMER_CCA); + rf->irq_thread.flags_set(SIG_TIMER_CCA); } static void rf_if_cal_timer_signal(void) { - rf->irq_thread.signal_set(SIG_TIMER_CAL); + rf->irq_thread.flags_set(SIG_TIMER_CAL); } static void rf_if_ack_timer_signal(void) { - rf->irq_thread.signal_set(SIG_TIMER_ACK); + rf->irq_thread.flags_set(SIG_TIMER_ACK); } #endif - +// *INDENT-OFF* /* Delay functions for RF Chip SPI access */ #ifdef __CC_ARM __asm static void delay_loop(uint32_t count) @@ -357,27 +356,28 @@ static void delay_loop(uint32_t count) ); } #endif +// *INDENT-ON* static void delay_ns(uint32_t ns) { - uint32_t cycles_per_us = SystemCoreClock / 1000000; - // Cortex-M0 takes 4 cycles per loop (SUB=1, BCS=3) - // Cortex-M3 and M4 takes 3 cycles per loop (SUB=1, BCS=2) - // Cortex-M7 - who knows? - // Cortex M3-M7 have "CYCCNT" - would be better than a software loop, but M0 doesn't - // Assume 3 cycles per loop for now - will be 33% slow on M0. No biggie, - // as original version of code was 300% slow on M4. - // [Note that this very calculation, plus call overhead, will take multiple - // cycles. Could well be 100ns on its own... So round down here, startup is - // worth at least one loop iteration.] - uint32_t count = (cycles_per_us * ns) / 3000; + uint32_t cycles_per_us = SystemCoreClock / 1000000; + // Cortex-M0 takes 4 cycles per loop (SUB=1, BCS=3) + // Cortex-M3 and M4 takes 3 cycles per loop (SUB=1, BCS=2) + // Cortex-M7 - who knows? + // Cortex M3-M7 have "CYCCNT" - would be better than a software loop, but M0 doesn't + // Assume 3 cycles per loop for now - will be 33% slow on M0. No biggie, + // as original version of code was 300% slow on M4. + // [Note that this very calculation, plus call overhead, will take multiple + // cycles. Could well be 100ns on its own... So round down here, startup is + // worth at least one loop iteration.] + uint32_t count = (cycles_per_us * ns) / 3000; - delay_loop(count); + delay_loop(count); } // t1 = 180ns, SEL falling edge to MISO active [SPI setup assumed slow enough to not need manual delay] #define CS_SELECT() {rf->CS = 0; /* delay_ns(180); */} - // t9 = 250ns, last clock to SEL rising edge, t8 = 250ns, SPI idle time between consecutive access +// t9 = 250ns, last clock to SEL rising edge, t8 = 250ns, SPI idle time between consecutive access #define CS_RELEASE() {delay_ns(250); rf->CS = 1; delay_ns(250);} /* @@ -389,21 +389,20 @@ static void delay_ns(uint32_t ns) */ static rf_trx_part_e rf_radio_type_read(void) { - rf_trx_part_e ret_val = ATMEL_UNKNOW_DEV; + rf_trx_part_e ret_val = ATMEL_UNKNOW_DEV; - switch (rf_part_num) - { - case PART_AT86RF212: - ret_val = ATMEL_AT86RF212; - break; - case PART_AT86RF233: - ret_val = ATMEL_AT86RF233; - break; - default: - break; - } + switch (rf_part_num) { + case PART_AT86RF212: + ret_val = ATMEL_AT86RF212; + break; + case PART_AT86RF233: + ret_val = ATMEL_AT86RF233; + break; + default: + break; + } - return ret_val; + return ret_val; } @@ -417,9 +416,9 @@ static rf_trx_part_e rf_radio_type_read(void) static void rf_if_ack_wait_timer_start(uint16_t slots) { #ifdef MBED_CONF_RTOS_PRESENT - rf->ack_timer.attach_us(rf_if_ack_timer_signal, slots*50); + rf->ack_timer.attach_us(rf_if_ack_timer_signal, slots * 50); #else - rf->ack_timer.attach_us(rf_ack_wait_timer_interrupt, slots*50); + rf->ack_timer.attach_us(rf_ack_wait_timer_interrupt, slots * 50); #endif } @@ -433,9 +432,9 @@ static void rf_if_ack_wait_timer_start(uint16_t slots) static void rf_if_calibration_timer_start(uint32_t slots) { #ifdef MBED_CONF_RTOS_PRESENT - rf->cal_timer.attach_us(rf_if_cal_timer_signal, slots*50); + rf->cal_timer.attach_us(rf_if_cal_timer_signal, slots * 50); #else - rf->cal_timer.attach_us(rf_calibration_timer_interrupt, slots*50); + rf->cal_timer.attach_us(rf_calibration_timer_interrupt, slots * 50); #endif } @@ -449,9 +448,9 @@ static void rf_if_calibration_timer_start(uint32_t slots) static void rf_if_cca_timer_start(uint32_t slots) { #ifdef MBED_CONF_RTOS_PRESENT - rf->cca_timer.attach_us(rf_if_cca_timer_signal, slots*50); + rf->cca_timer.attach_us(rf_if_cca_timer_signal, slots * 50); #else - rf->cca_timer.attach_us(rf_cca_timer_interrupt, slots*50); + rf->cca_timer.attach_us(rf_cca_timer_interrupt, slots * 50); #endif } @@ -462,7 +461,7 @@ static void rf_if_cca_timer_start(uint32_t slots) */ static void rf_if_cca_timer_stop(void) { - rf->cca_timer.detach(); + rf->cca_timer.detach(); } /* @@ -474,7 +473,7 @@ static void rf_if_cca_timer_stop(void) */ static void rf_if_ack_wait_timer_stop(void) { - rf->ack_timer.detach(); + rf->ack_timer.detach(); } /* @@ -488,10 +487,10 @@ static void rf_if_ack_wait_timer_stop(void) */ static void rf_if_set_bit(uint8_t addr, uint8_t bit, uint8_t bit_mask) { - uint8_t reg = rf_if_read_register(addr); - reg &= ~bit_mask; - reg |= bit; - rf_if_write_register(addr, reg); + uint8_t reg = rf_if_read_register(addr); + reg &= ~bit_mask; + reg |= bit; + rf_if_write_register(addr, reg); } /* @@ -504,7 +503,7 @@ static void rf_if_set_bit(uint8_t addr, uint8_t bit, uint8_t bit_mask) */ static void rf_if_clear_bit(uint8_t addr, uint8_t bit) { - rf_if_set_bit(addr, 0, bit); + rf_if_set_bit(addr, 0, bit); } /* @@ -517,11 +516,11 @@ static void rf_if_clear_bit(uint8_t addr, uint8_t bit) */ static void rf_if_write_register(uint8_t addr, uint8_t data) { - const uint8_t tx[2] = { static_cast(0xC0 | addr), data }; - uint8_t rx[2]; - CS_SELECT(); - rf_if_spi_exchange_n(tx, 2, rx, 2); - CS_RELEASE(); + const uint8_t tx[2] = { static_cast(0xC0 | addr), data }; + uint8_t rx[2]; + CS_SELECT(); + rf_if_spi_exchange_n(tx, 2, rx, 2); + CS_RELEASE(); } /* @@ -534,15 +533,15 @@ static void rf_if_write_register(uint8_t addr, uint8_t data) */ static uint8_t rf_if_read_register_with_status(uint8_t addr, uint8_t *status_out) { - const uint8_t tx[1] = { static_cast(0x80 | addr) }; - uint8_t rx[2]; - CS_SELECT(); - rf_if_spi_exchange_n(tx, 1, rx, 2); - CS_RELEASE(); - if (status_out) { - *status_out = rx[0]; - } - return rx[1]; + const uint8_t tx[1] = { static_cast(0x80 | addr) }; + uint8_t rx[2]; + CS_SELECT(); + rf_if_spi_exchange_n(tx, 1, rx, 2); + CS_RELEASE(); + if (status_out) { + *status_out = rx[0]; + } + return rx[1]; } /* @@ -554,7 +553,7 @@ static uint8_t rf_if_read_register_with_status(uint8_t addr, uint8_t *status_out */ static uint8_t rf_if_read_register(uint8_t addr) { - return rf_if_read_register_with_status(addr, NULL); + return rf_if_read_register_with_status(addr, NULL); } /* @@ -567,29 +566,29 @@ static uint8_t rf_if_read_register(uint8_t addr) static void rf_if_reset_radio(void) { #if MBED_CONF_ATMEL_RF_USE_SPI_SPACING_API - rf->spi.frequency(MBED_CONF_ATMEL_RF_FULL_SPI_SPEED); - int spacing = rf->spi.write_spacing(MBED_CONF_ATMEL_RF_FULL_SPI_SPEED_BYTE_SPACING); - if (spacing < MBED_CONF_ATMEL_RF_FULL_SPI_SPEED_BYTE_SPACING) { - rf->spi.frequency(MBED_CONF_ATMEL_RF_LOW_SPI_SPEED); - rf->spi.write_spacing(0); - } + rf->spi.frequency(MBED_CONF_ATMEL_RF_FULL_SPI_SPEED); + int spacing = rf->spi.write_spacing(MBED_CONF_ATMEL_RF_FULL_SPI_SPEED_BYTE_SPACING); + if (spacing < MBED_CONF_ATMEL_RF_FULL_SPI_SPEED_BYTE_SPACING) { + rf->spi.frequency(MBED_CONF_ATMEL_RF_LOW_SPI_SPEED); + rf->spi.write_spacing(0); + } #elif MBED_CONF_ATMEL_RF_ASSUME_SPACED_SPI - rf->spi.frequency(MBED_CONF_ATMEL_RF_FULL_SPI_SPEED); + rf->spi.frequency(MBED_CONF_ATMEL_RF_FULL_SPI_SPEED); #else - rf->spi.frequency(MBED_CONF_ATMEL_RF_LOW_SPI_SPEED); + rf->spi.frequency(MBED_CONF_ATMEL_RF_LOW_SPI_SPEED); #endif - rf->IRQ.rise(0); - rf->RST = 1; - wait_ms(1); - rf->RST = 0; - wait_ms(10); - CS_RELEASE(); - rf->SLP_TR = 0; - wait_ms(10); - rf->RST = 1; - wait_ms(10); + rf->IRQ.rise(0); + rf->RST = 1; + wait_ms(1); + rf->RST = 0; + wait_ms(10); + CS_RELEASE(); + rf->SLP_TR = 0; + wait_ms(10); + rf->RST = 1; + wait_ms(10); - rf->IRQ.rise(&rf_if_interrupt_handler); + rf->IRQ.rise(&rf_if_interrupt_handler); } /* @@ -601,10 +600,10 @@ static void rf_if_reset_radio(void) */ static void rf_if_enable_promiscuous_mode(void) { - if (!(xah_ctrl_1 & AACK_PROM_MODE)) { - /*Set AACK_PROM_MODE to enable the promiscuous mode*/ - rf_if_write_register(XAH_CTRL_1, xah_ctrl_1 |= AACK_PROM_MODE); - } + if (!(xah_ctrl_1 & AACK_PROM_MODE)) { + /*Set AACK_PROM_MODE to enable the promiscuous mode*/ + rf_if_write_register(XAH_CTRL_1, xah_ctrl_1 |= AACK_PROM_MODE); + } } /* @@ -616,10 +615,10 @@ static void rf_if_enable_promiscuous_mode(void) */ static void rf_if_disable_promiscuous_mode(void) { - if (xah_ctrl_1 & AACK_PROM_MODE) { - /*Clear AACK_PROM_MODE to disable the promiscuous mode*/ - rf_if_write_register(XAH_CTRL_1, xah_ctrl_1 &= ~AACK_PROM_MODE); - } + if (xah_ctrl_1 & AACK_PROM_MODE) { + /*Clear AACK_PROM_MODE to disable the promiscuous mode*/ + rf_if_write_register(XAH_CTRL_1, xah_ctrl_1 &= ~AACK_PROM_MODE); + } } /* @@ -631,8 +630,8 @@ static void rf_if_disable_promiscuous_mode(void) */ static void rf_if_enable_ant_div(void) { - /*Set ANT_EXT_SW_EN to enable controlling of antenna diversity*/ - rf_if_set_bit(ANT_DIV, ANT_EXT_SW_EN, ANT_EXT_SW_EN); + /*Set ANT_EXT_SW_EN to enable controlling of antenna diversity*/ + rf_if_set_bit(ANT_DIV, ANT_EXT_SW_EN, ANT_EXT_SW_EN); } /* @@ -644,7 +643,7 @@ static void rf_if_enable_ant_div(void) */ static void rf_if_disable_ant_div(void) { - rf_if_clear_bit(ANT_DIV, ANT_EXT_SW_EN); + rf_if_clear_bit(ANT_DIV, ANT_EXT_SW_EN); } /* @@ -656,7 +655,7 @@ static void rf_if_disable_ant_div(void) */ static void rf_if_enable_slptr(void) { - rf->SLP_TR = 1; + rf->SLP_TR = 1; } /* @@ -668,7 +667,7 @@ static void rf_if_enable_slptr(void) */ static void rf_if_disable_slptr(void) { - rf->SLP_TR = 0; + rf->SLP_TR = 0; } /* @@ -680,9 +679,9 @@ static void rf_if_disable_slptr(void) */ static void rf_if_write_antenna_diversity_settings(void) { - /*Recommended setting of PDT_THRES is 3 when antenna diversity is used*/ - rf_if_set_bit(RX_CTRL, 0x03, 0x0f); - rf_if_write_register(ANT_DIV, ANT_DIV_EN | ANT_EXT_SW_EN | ANT_CTRL_DEFAULT); + /*Recommended setting of PDT_THRES is 3 when antenna diversity is used*/ + rf_if_set_bit(RX_CTRL, 0x03, 0x0f); + rf_if_write_register(ANT_DIV, ANT_DIV_EN | ANT_EXT_SW_EN | ANT_CTRL_DEFAULT); } /* @@ -694,7 +693,7 @@ static void rf_if_write_antenna_diversity_settings(void) */ static void rf_if_write_set_tx_power_register(uint8_t value) { - rf_if_write_register(PHY_TX_PWR, value); + rf_if_write_register(PHY_TX_PWR, value); } /* @@ -706,7 +705,7 @@ static void rf_if_write_set_tx_power_register(uint8_t value) */ static uint8_t rf_if_read_part_num(void) { - return rf_if_read_register(PART_NUM); + return rf_if_read_register(PART_NUM); } /* @@ -718,58 +717,53 @@ static uint8_t rf_if_read_part_num(void) */ static void rf_if_write_rf_settings(void) { - /*Reset RF module*/ - rf_if_reset_radio(); + /*Reset RF module*/ + rf_if_reset_radio(); - rf_part_num = rf_if_read_part_num(); + rf_part_num = rf_if_read_part_num(); - rf_if_write_register(XAH_CTRL_0,0); + rf_if_write_register(XAH_CTRL_0, 0); - /* Auto CRC on, IRQ status shows unmasked only, TRX_STATUS output on all accesses */ - rf_if_write_register(TRX_CTRL_1, TX_AUTO_CRC_ON | SPI_CMD_MODE_TRX_STATUS); + /* Auto CRC on, IRQ status shows unmasked only, TRX_STATUS output on all accesses */ + rf_if_write_register(TRX_CTRL_1, TX_AUTO_CRC_ON | SPI_CMD_MODE_TRX_STATUS); - rf_if_write_register(IRQ_MASK, CCA_ED_DONE | TRX_END | TRX_UR); + rf_if_write_register(IRQ_MASK, CCA_ED_DONE | TRX_END | TRX_UR); - xah_ctrl_1 = rf_if_read_register(XAH_CTRL_1); + xah_ctrl_1 = rf_if_read_register(XAH_CTRL_1); - /*Read transceiver PART_NUM*/ - rf_part_num = rf_if_read_register(PART_NUM); + /*Read transceiver PART_NUM*/ + rf_part_num = rf_if_read_register(PART_NUM); - /*Sub-GHz RF settings*/ - if(rf_part_num == PART_AT86RF212) - { - /*GC_TX_OFFS mode-dependent setting - OQPSK*/ - rf_if_write_register(RF_CTRL_0, 0x32); + /*Sub-GHz RF settings*/ + if (rf_part_num == PART_AT86RF212) { + /*GC_TX_OFFS mode-dependent setting - OQPSK*/ + rf_if_write_register(RF_CTRL_0, 0x32); - if(rf_if_read_register(VERSION_NUM) == VERSION_AT86RF212B) - { - /*TX Output Power setting - 0 dBm North American Band*/ - rf_if_write_register(PHY_TX_PWR, 0x03); + if (rf_if_read_register(VERSION_NUM) == VERSION_AT86RF212B) { + /*TX Output Power setting - 0 dBm North American Band*/ + rf_if_write_register(PHY_TX_PWR, 0x03); + } else { + /*TX Output Power setting - 0 dBm North American Band*/ + rf_if_write_register(PHY_TX_PWR, 0x24); + } + + /*PHY Mode: IEEE 802.15.4-2006/2011 - OQPSK-SIN-250*/ + rf_if_write_register(TRX_CTRL_2, RX_SAFE_MODE | RF_PHY_MODE); + /*Based on receiver Characteristics. See AT86RF212B Datasheet where RSSI BASE VALUE in range -97 - -100 dBm*/ + rf_rssi_base_val = -98; } - else - { - /*TX Output Power setting - 0 dBm North American Band*/ - rf_if_write_register(PHY_TX_PWR, 0x24); - } - - /*PHY Mode: IEEE 802.15.4-2006/2011 - OQPSK-SIN-250*/ - rf_if_write_register(TRX_CTRL_2, RX_SAFE_MODE | RF_PHY_MODE); - /*Based on receiver Characteristics. See AT86RF212B Datasheet where RSSI BASE VALUE in range -97 - -100 dBm*/ - rf_rssi_base_val = -98; - } - /*2.4GHz RF settings*/ - else - { + /*2.4GHz RF settings*/ + else { #if 0 - /* Disable power saving functions for now - can only impact reliability, - * and don't have any users demanding it. */ - /*Set RPC register*/ - rf_if_write_register(TRX_RPC, RX_RPC_CTRL|RX_RPC_EN|PLL_RPC_EN|XAH_TX_RPC_EN|IPAN_RPC_EN|TRX_RPC_RSVD_1); + /* Disable power saving functions for now - can only impact reliability, + * and don't have any users demanding it. */ + /*Set RPC register*/ + rf_if_write_register(TRX_RPC, RX_RPC_CTRL | RX_RPC_EN | PLL_RPC_EN | XAH_TX_RPC_EN | IPAN_RPC_EN | TRX_RPC_RSVD_1); #endif - /*PHY Mode: IEEE 802.15.4 - Data Rate 250 kb/s*/ - rf_if_write_register(TRX_CTRL_2, RX_SAFE_MODE); - rf_rssi_base_val = -91; - } + /*PHY Mode: IEEE 802.15.4 - Data Rate 250 kb/s*/ + rf_if_write_register(TRX_CTRL_2, RX_SAFE_MODE); + rf_rssi_base_val = -91; + } } /* @@ -781,7 +775,7 @@ static void rf_if_write_rf_settings(void) */ static rf_trx_states_t rf_if_read_trx_state(void) { - return rf_if_trx_status_from_full(rf_if_read_register(TRX_STATUS)); + return rf_if_trx_status_from_full(rf_if_read_register(TRX_STATUS)); } /* @@ -796,19 +790,19 @@ static rf_trx_states_t rf_if_read_trx_state(void) */ static uint16_t rf_if_read_packet(uint8_t data_out[RF_MTU], uint8_t *lqi_out, uint8_t *ed_out, bool *crc_good) { - CS_SELECT(); - const uint8_t tx[1] = { 0x20 }; - uint8_t rx[3]; - rf_if_spi_exchange_n(tx, 1, rx, 2); - uint8_t len = rx[1] & 0x7F; - rf_if_spi_exchange_n(NULL, 0, data_out, len); - rf_if_spi_exchange_n(NULL, 0, rx, 3); - *lqi_out = rx[0]; - *ed_out = rx[1]; - *crc_good = rx[2] & 0x80; - CS_RELEASE(); + CS_SELECT(); + const uint8_t tx[1] = { 0x20 }; + uint8_t rx[3]; + rf_if_spi_exchange_n(tx, 1, rx, 2); + uint8_t len = rx[1] & 0x7F; + rf_if_spi_exchange_n(NULL, 0, data_out, len); + rf_if_spi_exchange_n(NULL, 0, rx, 3); + *lqi_out = rx[0]; + *ed_out = rx[1]; + *crc_good = rx[2] & 0x80; + CS_RELEASE(); - return len; + return len; } /* @@ -820,8 +814,8 @@ static uint16_t rf_if_read_packet(uint8_t data_out[RF_MTU], uint8_t *lqi_out, ui */ static void rf_if_write_short_addr_registers(uint8_t *short_address) { - rf_if_write_register(SHORT_ADDR_1, *short_address++); - rf_if_write_register(SHORT_ADDR_0, *short_address); + rf_if_write_register(SHORT_ADDR_1, *short_address++); + rf_if_write_register(SHORT_ADDR_0, *short_address); } /* @@ -833,16 +827,13 @@ static void rf_if_write_short_addr_registers(uint8_t *short_address) */ static void rf_if_ack_pending_ctrl(uint8_t state) { - rf_if_lock(); - if(state) - { - rf_if_set_bit(CSMA_SEED_1, (1 << AACK_SET_PD), (1 << AACK_SET_PD)); - } - else - { - rf_if_clear_bit(CSMA_SEED_1, (1 << AACK_SET_PD)); - } - rf_if_unlock(); + rf_if_lock(); + if (state) { + rf_if_set_bit(CSMA_SEED_1, (1 << AACK_SET_PD), (1 << AACK_SET_PD)); + } else { + rf_if_clear_bit(CSMA_SEED_1, (1 << AACK_SET_PD)); + } + rf_if_unlock(); } /* @@ -854,16 +845,17 @@ static void rf_if_ack_pending_ctrl(uint8_t state) */ static uint8_t rf_if_last_acked_pending(void) { - uint8_t last_acked_data_pending; + uint8_t last_acked_data_pending; - rf_if_lock(); - if(rf_if_read_register(CSMA_SEED_1) & (1 << AACK_SET_PD)) - last_acked_data_pending = 1; - else - last_acked_data_pending = 0; - rf_if_unlock(); + rf_if_lock(); + if (rf_if_read_register(CSMA_SEED_1) & (1 << AACK_SET_PD)) { + last_acked_data_pending = 1; + } else { + last_acked_data_pending = 0; + } + rf_if_unlock(); - return last_acked_data_pending; + return last_acked_data_pending; } /* @@ -875,9 +867,9 @@ static uint8_t rf_if_last_acked_pending(void) */ static void rf_if_calibration(void) { - rf_if_set_bit(FTN_CTRL, FTN_START, FTN_START); - /*Wait while calibration is running*/ - while(rf_if_read_register(FTN_CTRL) & FTN_START); + rf_if_set_bit(FTN_CTRL, FTN_START, FTN_START); + /*Wait while calibration is running*/ + while (rf_if_read_register(FTN_CTRL) & FTN_START); } /* @@ -889,8 +881,8 @@ static void rf_if_calibration(void) */ static void rf_if_write_pan_id_registers(uint8_t *pan_id) { - rf_if_write_register(PAN_ID_1, *pan_id++); - rf_if_write_register(PAN_ID_0, *pan_id); + rf_if_write_register(PAN_ID_1, *pan_id++); + rf_if_write_register(PAN_ID_0, *pan_id); } /* @@ -902,11 +894,12 @@ static void rf_if_write_pan_id_registers(uint8_t *pan_id) */ static void rf_if_write_ieee_addr_registers(uint8_t *address) { - uint8_t i; - uint8_t temp = IEEE_ADDR_0; + uint8_t i; + uint8_t temp = IEEE_ADDR_0; - for(i=0; i<8; i++) - rf_if_write_register(temp++, address[7-i]); + for (i = 0; i < 8; i++) { + rf_if_write_register(temp++, address[7 - i]); + } } /* @@ -919,12 +912,12 @@ static void rf_if_write_ieee_addr_registers(uint8_t *address) */ static void rf_if_write_frame_buffer(const uint8_t *ptr, uint8_t length) { - const uint8_t cmd[2] = { 0x60, static_cast(length + 2) }; + const uint8_t cmd[2] = { 0x60, static_cast(length + 2) }; - CS_SELECT(); - rf_if_spi_exchange_n(cmd, 2, NULL, 0); - rf_if_spi_exchange_n(ptr, length, NULL, 0); - CS_RELEASE(); + CS_SELECT(); + rf_if_spi_exchange_n(cmd, 2, NULL, 0); + rf_if_spi_exchange_n(ptr, length, NULL, 0); + CS_RELEASE(); } /* @@ -936,27 +929,27 @@ static void rf_if_write_frame_buffer(const uint8_t *ptr, uint8_t length) */ static uint8_t rf_if_read_rnd(void) { - uint8_t temp; - uint8_t tmp_rpc_val = 0; - /*RPC must be disabled while reading the random number*/ - if(rf_part_num == PART_AT86RF233) - { - tmp_rpc_val = rf_if_read_register(TRX_RPC); - rf_if_write_register(TRX_RPC, RX_RPC_CTRL|TRX_RPC_RSVD_1); - } + uint8_t temp; + uint8_t tmp_rpc_val = 0; + /*RPC must be disabled while reading the random number*/ + if (rf_part_num == PART_AT86RF233) { + tmp_rpc_val = rf_if_read_register(TRX_RPC); + rf_if_write_register(TRX_RPC, RX_RPC_CTRL | TRX_RPC_RSVD_1); + } - wait_ms(1); - temp = ((rf_if_read_register(PHY_RSSI)>>5) << 6); - wait_ms(1); - temp |= ((rf_if_read_register(PHY_RSSI)>>5) << 4); - wait_ms(1); - temp |= ((rf_if_read_register(PHY_RSSI)>>5) << 2); - wait_ms(1); - temp |= ((rf_if_read_register(PHY_RSSI)>>5)); - wait_ms(1); - if(rf_part_num == PART_AT86RF233) - rf_if_write_register(TRX_RPC, tmp_rpc_val); - return temp; + wait_ms(1); + temp = ((rf_if_read_register(PHY_RSSI) >> 5) << 6); + wait_ms(1); + temp |= ((rf_if_read_register(PHY_RSSI) >> 5) << 4); + wait_ms(1); + temp |= ((rf_if_read_register(PHY_RSSI) >> 5) << 2); + wait_ms(1); + temp |= ((rf_if_read_register(PHY_RSSI) >> 5)); + wait_ms(1); + if (rf_part_num == PART_AT86RF233) { + rf_if_write_register(TRX_RPC, tmp_rpc_val); + } + return temp; } /* @@ -968,9 +961,9 @@ static uint8_t rf_if_read_rnd(void) */ static rf_trx_states_t rf_if_change_trx_state(rf_trx_states_t trx_state) { - rf_if_write_register(TRX_STATE, trx_state); - /*Wait while not in desired state*/ - return rf_poll_trx_state_change(trx_state); + rf_if_write_register(TRX_STATE, trx_state); + /*Wait while not in desired state*/ + return rf_poll_trx_state_change(trx_state); } /* @@ -982,7 +975,7 @@ static rf_trx_states_t rf_if_change_trx_state(rf_trx_states_t trx_state) */ static void rf_if_start_cca_process(void) { - rf_if_write_register(PHY_CC_CCA, CCA_REQUEST | CCA_MODE_3A | rf_phy_channel); + rf_if_write_register(PHY_CC_CCA, CCA_REQUEST | CCA_MODE_3A | rf_phy_channel); } /* @@ -994,11 +987,11 @@ static void rf_if_start_cca_process(void) */ static int8_t rf_if_scale_rssi(uint8_t ed_level) { - if (rf_part_num == PART_AT86RF212) { - /* Data sheet says to multiply by 1.03 - this is 1.03125, rounding down */ - ed_level += ed_level >> 5; - } - return rf_rssi_base_val + ed_level; + if (rf_part_num == PART_AT86RF212) { + /* Data sheet says to multiply by 1.03 - this is 1.03125, rounding down */ + ed_level += ed_level >> 5; + } + return rf_rssi_base_val + ed_level; } /* @@ -1010,7 +1003,7 @@ static int8_t rf_if_scale_rssi(uint8_t ed_level) */ static void rf_if_set_channel_register(uint8_t channel) { - rf_if_set_bit(PHY_CC_CCA, channel, CCA_CHANNEL_MASK); + rf_if_set_bit(PHY_CC_CCA, channel, CCA_CHANNEL_MASK); } /* @@ -1022,7 +1015,7 @@ static void rf_if_set_channel_register(uint8_t channel) */ static void rf_if_enable_irq(void) { - rf->IRQ.enable_irq(); + rf->IRQ.enable_irq(); } /* @@ -1034,13 +1027,13 @@ static void rf_if_enable_irq(void) */ static void rf_if_disable_irq(void) { - rf->IRQ.disable_irq(); + rf->IRQ.disable_irq(); } #ifdef MBED_CONF_RTOS_PRESENT static void rf_if_interrupt_handler(void) { - rf->irq_thread.signal_set(SIG_RADIO); + rf->irq_thread.flags_set(SIG_RADIO); } // Started during construction of rf, so variable @@ -1048,21 +1041,18 @@ static void rf_if_interrupt_handler(void) void RFBits::rf_if_irq_task(void) { for (;;) { - osEvent event = irq_thread.signal_wait(0); - if (event.status != osEventSignal) { - continue; - } + uint32_t flags = ThisThread::flags_wait_any(SIG_ALL); rf_if_lock(); - if (event.value.signals & SIG_RADIO) { + if (flags & SIG_RADIO) { rf_if_irq_task_process_irq(); } - if (event.value.signals & SIG_TIMER_ACK) { + if (flags & SIG_TIMER_ACK) { rf_ack_wait_timer_interrupt(); } - if (event.value.signals & SIG_TIMER_CCA) { + if (flags & SIG_TIMER_CCA) { rf_cca_timer_interrupt(); } - if (event.value.signals & SIG_TIMER_CAL) { + if (flags & SIG_TIMER_CAL) { rf_calibration_timer_interrupt(); } rf_if_unlock(); @@ -1081,39 +1071,30 @@ static void rf_if_irq_task_process_irq(void) static void rf_if_interrupt_handler(void) #endif { - static uint8_t last_is, last_ts; - uint8_t irq_status, full_trx_status; - uint8_t orig_xah_ctrl_1 = xah_ctrl_1; + uint8_t irq_status, full_trx_status; - /*Read and clear interrupt flag, and pick up trx_status*/ - irq_status = rf_if_read_register_with_status(IRQ_STATUS, &full_trx_status); - uint8_t orig_flags = rf_flags; + /*Read and clear interrupt flag, and pick up trx_status*/ + irq_status = rf_if_read_register_with_status(IRQ_STATUS, &full_trx_status); - /*Frame end interrupt (RX and TX)*/ - if(irq_status & TRX_END) - { - /*TX done interrupt*/ - rf_trx_states_t trx_status = rf_if_trx_status_from_full(full_trx_status); - if(trx_status == PLL_ON || trx_status == TX_ARET_ON) - { - rf_handle_tx_end(trx_status); + /*Frame end interrupt (RX and TX)*/ + if (irq_status & TRX_END) { + /*TX done interrupt*/ + rf_trx_states_t trx_status = rf_if_trx_status_from_full(full_trx_status); + if (trx_status == PLL_ON || trx_status == TX_ARET_ON) { + rf_handle_tx_end(trx_status); + } + /*Frame received interrupt*/ + else { + rf_handle_rx_end(trx_status); + } } - /*Frame received interrupt*/ - else - { - rf_handle_rx_end(trx_status); + if (irq_status & CCA_ED_DONE) { + rf_handle_cca_ed_done(full_trx_status); + } + if (irq_status & TRX_UR) { + // Here some counter could be used to monitor the underrun occurancy count. + // Do not print anything here! } - } - if(irq_status & CCA_ED_DONE) - { - rf_handle_cca_ed_done(full_trx_status); - } - if (irq_status & TRX_UR) - { - tr_error("Radio underrun is %x->%x ts %x->%x fl %x->%x x1 %x", last_is, irq_status, last_ts, full_trx_status, orig_flags, rf_flags, orig_xah_ctrl_1); - } - last_is = irq_status; - last_ts = full_trx_status; } /* @@ -1122,25 +1103,25 @@ static void rf_if_interrupt_handler(void) static void rf_if_spi_exchange_n(const void *tx, size_t tx_len, void *rx, size_t rx_len) { #if 1 - rf->spi.write(static_cast(tx), tx_len, - static_cast(rx), rx_len); + rf->spi.write(static_cast(tx), tx_len, + static_cast(rx), rx_len); #else - const uint8_t *txb = static_cast(tx); - uint8_t *rxb = static_cast(rx); - while (tx_len > 0 || rx_len > 0) { - uint8_t b; - if (tx_len) { - tx_len--; - b = *txb++; - } else { - b = 0xFF; - } - b = rf->spi.write(b); - if (rx_len) { - rx_len--; - *rxb++ = b; - } - } + const uint8_t *txb = static_cast(tx); + uint8_t *rxb = static_cast(rx); + while (tx_len > 0 || rx_len > 0) { + uint8_t b; + if (tx_len) { + tx_len--; + b = *txb++; + } else { + b = 0xFF; + } + b = rf->spi.write(b); + if (rx_len) { + rx_len--; + *rxb++ = b; + } + } #endif } @@ -1206,18 +1187,14 @@ static int8_t rf_device_register(const uint8_t *mac_addr) rf_init(); radio_type = rf_radio_type_read(); - if(radio_type != ATMEL_UNKNOW_DEV) - { + if (radio_type != ATMEL_UNKNOW_DEV) { /*Set pointer to MAC address*/ device_driver.PHY_MAC = (uint8_t *)mac_addr; - device_driver.driver_description = (char*)"ATMEL_MAC"; + device_driver.driver_description = (char *)"ATMEL_MAC"; //Create setup Used Radio chips - if(radio_type == ATMEL_AT86RF212) - { + if (radio_type == ATMEL_AT86RF212) { device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE; - } - else - { + } else { device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE; } device_driver.phy_channel_pages = phy_channel_pages; @@ -1365,8 +1342,9 @@ static void rf_write_settings(void) /*Set output power*/ rf_if_write_set_tx_power_register(radio_tx_power); /*Initialise Antenna Diversity*/ - if(rf_use_antenna_diversity) + if (rf_use_antenna_diversity) { rf_if_write_antenna_diversity_settings(); + } rf_if_unlock(); } @@ -1377,20 +1355,18 @@ static void rf_write_settings(void) * * \return none */ -static void rf_set_short_adr(uint8_t * short_address) +static void rf_set_short_adr(uint8_t *short_address) { rf_if_lock(); /*Wake up RF if sleeping*/ - if(rf_flags_check(RFF_ON) == 0) - { + if (rf_flags_check(RFF_ON) == 0) { rf_if_disable_slptr(); rf_poll_trx_state_change(TRX_OFF); } /*Write address filter registers*/ rf_if_write_short_addr_registers(short_address); /*RF back to sleep*/ - if(rf_flags_check(RFF_ON) == 0) - { + if (rf_flags_check(RFF_ON) == 0) { rf_if_enable_slptr(); } rf_if_unlock(); @@ -1407,16 +1383,14 @@ static void rf_set_pan_id(uint8_t *pan_id) { rf_if_lock(); /*Wake up RF if sleeping*/ - if(rf_flags_check(RFF_ON) == 0) - { + if (rf_flags_check(RFF_ON) == 0) { rf_if_disable_slptr(); rf_poll_trx_state_change(TRX_OFF); } /*Write address filter registers*/ rf_if_write_pan_id_registers(pan_id); /*RF back to sleep*/ - if(rf_flags_check(RFF_ON) == 0) - { + if (rf_flags_check(RFF_ON) == 0) { rf_if_enable_slptr(); } rf_if_unlock(); @@ -1433,16 +1407,14 @@ static void rf_set_address(uint8_t *address) { rf_if_lock(); /*Wake up RF if sleeping*/ - if(rf_flags_check(RFF_ON) == 0) - { + if (rf_flags_check(RFF_ON) == 0) { rf_if_disable_slptr(); rf_poll_trx_state_change(TRX_OFF); } /*Write address filter registers*/ rf_if_write_ieee_addr_registers(address); /*RF back to sleep*/ - if(rf_flags_check(RFF_ON) == 0) - { + if (rf_flags_check(RFF_ON) == 0) { rf_if_enable_slptr(); } rf_if_unlock(); @@ -1459,8 +1431,9 @@ static void rf_channel_set(uint8_t ch) { rf_if_lock(); rf_phy_channel = ch; - if(ch < 0x1f) + if (ch < 0x1f) { rf_if_set_channel_register(ch); + } rf_if_unlock(); } @@ -1505,29 +1478,28 @@ static void rf_init(void) */ static void rf_off(void) { - if(rf_flags_check(RFF_ON)) - { + if (rf_flags_check(RFF_ON)) { rf_if_lock(); rf_cca_abort(); uint16_t while_counter = 0; /*Wait while receiving*/ - while(rf_if_read_trx_state() == BUSY_RX_AACK) - { + while (rf_if_read_trx_state() == BUSY_RX_AACK) { while_counter++; - if(while_counter == 0xffff) + if (while_counter == 0xffff) { break; + } } /*RF state change: RX_AACK_ON->PLL_ON->TRX_OFF->SLEEP*/ - if(rf_if_read_trx_state() == RX_AACK_ON) - { + if (rf_if_read_trx_state() == RX_AACK_ON) { rf_if_change_trx_state(PLL_ON); } rf_if_change_trx_state(TRX_OFF); rf_if_enable_slptr(); /*Disable Antenna Diversity*/ - if(rf_use_antenna_diversity) + if (rf_use_antenna_diversity) { rf_if_disable_ant_div(); + } rf_if_unlock(); } @@ -1546,17 +1518,18 @@ static rf_trx_states_t rf_poll_trx_state_change(rf_trx_states_t trx_state) { uint16_t while_counter = 0; - if(trx_state == FORCE_PLL_ON) + if (trx_state == FORCE_PLL_ON) { trx_state = PLL_ON; - else if(trx_state == FORCE_TRX_OFF) + } else if (trx_state == FORCE_TRX_OFF) { trx_state = TRX_OFF; + } rf_trx_states_t state_out; - while((state_out = rf_if_read_trx_state()) != trx_state) - { + while ((state_out = rf_if_read_trx_state()) != trx_state) { while_counter++; - if(while_counter == 0x1ff) + if (while_counter == 0x1ff) { break; + } } return state_out; @@ -1572,8 +1545,7 @@ static rf_trx_states_t rf_poll_trx_state_change(rf_trx_states_t trx_state) static rf_trx_states_t rf_poll_for_state(void) { rf_trx_states_t state_out; - while((state_out = rf_if_read_trx_state()) == STATE_TRANSITION_IN_PROGRESS) - { + while ((state_out = rf_if_read_trx_state()) == STATE_TRANSITION_IN_PROGRESS) { } return state_out; @@ -1588,20 +1560,17 @@ static rf_trx_states_t rf_poll_for_state(void) * \return 0 Success * \return -1 Busy */ -static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol ) +static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol) { (void)data_protocol; rf_if_lock(); /*Check if transmitter is busy*/ rf_trx_states_t trx_state = rf_if_read_trx_state(); - if(trx_state == BUSY_RX || trx_state == BUSY_RX_AACK || data_length > RF_MTU - 2) - { + if (trx_state == BUSY_RX || trx_state == BUSY_RX_AACK || data_length > RF_MTU - 2) { rf_if_unlock(); /*Return busy*/ return -1; - } - else - { + } else { rf_give_up_on_ack(); /*Nanostack has a static TX buffer, which will remain valid until we*/ @@ -1661,7 +1630,6 @@ static bool rf_start_tx() rf_flags_clear(RFF_RX); // Check whether we saw any delay in the PLL_ON transition. if (poll_count > 0) { - tr_warning("PLL_ON delayed, retry count: %d", poll_count); // let's get back to the receiving state. rf_receive(state); return false; @@ -1687,42 +1655,32 @@ static bool rf_start_tx() static void rf_receive(rf_trx_states_t trx_status) { uint16_t while_counter = 0; - if(rf_flags_check(RFF_ON) == 0) - { + if (rf_flags_check(RFF_ON) == 0) { rf_on(); rf_channel_set(rf_phy_channel); trx_status = TRX_OFF; } /*If not yet in RX state set it*/ - if(rf_flags_check(RFF_RX) == 0) - { + if (rf_flags_check(RFF_RX) == 0) { /*Wait while receiving data. Just making sure, usually this shouldn't happen. */ - while(trx_status == BUSY_RX || trx_status == BUSY_RX_AACK || trx_status == STATE_TRANSITION_IN_PROGRESS) - { + while (trx_status == BUSY_RX || trx_status == BUSY_RX_AACK || trx_status == STATE_TRANSITION_IN_PROGRESS) { while_counter++; - if(while_counter == 0xffff) - { + if (while_counter == 0xffff) { break; } trx_status = rf_if_read_trx_state(); } - if((rf_mode == RF_MODE_SNIFFER) || (rf_mode == RF_MODE_ED)) - { + if ((rf_mode == RF_MODE_SNIFFER) || (rf_mode == RF_MODE_ED)) { if (trx_status != RX_ON) { trx_status = rf_if_change_trx_state(RX_ON); } - } - else - { + } else { /*ACK is always received in promiscuous mode to bypass address filters*/ - if(rf_rx_mode) - { + if (rf_rx_mode) { rf_rx_mode = 0; rf_if_enable_promiscuous_mode(); - } - else - { + } else { rf_if_disable_promiscuous_mode(); } if (trx_status != RX_AACK_ON) { @@ -1730,8 +1688,7 @@ static void rf_receive(rf_trx_states_t trx_status) } } /*If calibration timer was unable to calibrate the RF, run calibration now*/ - if(!rf_tuned) - { + if (!rf_tuned) { /*Start calibration. This can be done in states TRX_OFF, PLL_ON or in any receive state*/ rf_if_calibration(); /*RF is tuned now*/ @@ -1754,8 +1711,7 @@ static void rf_calibration_cb(void) /*clear tuned flag to start tuning in rf_receive*/ rf_tuned = 0; /*If RF is in default receive state, start calibration*/ - if(rf_if_read_trx_state() == RX_AACK_ON) - { + if (rf_if_read_trx_state() == RX_AACK_ON) { rf_if_lock(); /*Set RF in PLL_ON state*/ rf_if_change_trx_state(PLL_ON); @@ -1784,14 +1740,15 @@ static void rf_calibration_cb(void) static void rf_on(void) { /*Set RFF_ON flag*/ - if(rf_flags_check(RFF_ON) == 0) - { + if (rf_flags_check(RFF_ON) == 0) { rf_if_lock(); rf_flags_set(RFF_ON); /*Enable Antenna diversity*/ - if(rf_use_antenna_diversity) + if (rf_use_antenna_diversity) /*Set ANT_EXT_SW_EN to enable controlling of antenna diversity*/ + { rf_if_enable_ant_div(); + } /*Wake up from sleep state*/ rf_if_disable_slptr(); @@ -1815,7 +1772,7 @@ static void rf_give_up_on_ack(void) rf_if_ack_wait_timer_stop(); expected_ack_sequence = -1; - if(device_driver.phy_tx_done_cb){ + if (device_driver.phy_tx_done_cb) { device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_FAIL, 0, 0); } } @@ -1832,20 +1789,20 @@ static void rf_handle_ack(uint8_t seq_number, uint8_t data_pending) { phy_link_tx_status_e phy_status; /*Received ACK sequence must be equal with transmitted packet sequence*/ - if(expected_ack_sequence == seq_number) - { + if (expected_ack_sequence == seq_number) { rf_if_disable_promiscuous_mode(); rf_if_ack_wait_timer_stop(); expected_ack_sequence = -1; /*When data pending bit in ACK frame is set, inform NET library*/ - if(data_pending) + if (data_pending) { phy_status = PHY_LINK_TX_DONE_PENDING; - else + } else { phy_status = PHY_LINK_TX_DONE; + } /*Call PHY TX Done API*/ - if(device_driver.phy_tx_done_cb){ - device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle,phy_status, 0, 0); + if (device_driver.phy_tx_done_cb) { + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, phy_status, 0, 0); } } else { rf_give_up_on_ack(); @@ -1862,7 +1819,7 @@ static void rf_handle_ack(uint8_t seq_number, uint8_t data_pending) static void rf_handle_rx_end(rf_trx_states_t trx_status) { /*Frame received interrupt*/ - if(!rf_flags_check(RFF_RX)) { + if (!rf_flags_check(RFF_RX)) { return; } @@ -1887,8 +1844,7 @@ static void rf_handle_rx_end(rf_trx_states_t trx_status) rf_lqi = rf_scale_lqi(rf_rssi); /*Handle received ACK*/ - if((rf_buffer[0] & 0x07) == 0x02 && rf_mode != RF_MODE_SNIFFER) - { + if ((rf_buffer[0] & 0x07) == 0x02 && rf_mode != RF_MODE_SNIFFER) { /*Check if data is pending*/ bool pending = (rf_buffer[0] & 0x10); @@ -1896,7 +1852,7 @@ static void rf_handle_rx_end(rf_trx_states_t trx_status) rf_handle_ack(rf_buffer[2], pending); } else { rf_give_up_on_ack(); - if( device_driver.phy_rx_cb ){ + if (device_driver.phy_rx_cb) { device_driver.phy_rx_cb(rf_buffer, len - 2, rf_lqi, rf_rssi, rf_radio_driver_id); } } @@ -1926,8 +1882,7 @@ static void rf_handle_tx_end(rf_trx_states_t trx_status) { rf_rx_mode = 0; /*If ACK is needed for this transmission*/ - if((rf_tx_data[0] & 0x20) && rf_flags_check(RFF_TX)) - { + if ((rf_tx_data[0] & 0x20) && rf_flags_check(RFF_TX)) { expected_ack_sequence = rf_tx_data[2]; rf_ack_wait_timer_start(rf_ack_wait_duration); rf_rx_mode = 1; @@ -1937,7 +1892,7 @@ static void rf_handle_tx_end(rf_trx_states_t trx_status) rf_receive(trx_status); /*Call PHY TX Done API*/ - if(device_driver.phy_tx_done_cb){ + if (device_driver.phy_tx_done_cb) { device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 0, 0); } } @@ -1959,15 +1914,13 @@ static void rf_handle_cca_ed_done(uint8_t full_trx_status) bool success = false; /*Check the result of CCA process*/ - if((full_trx_status & CCA_STATUS) && rf_if_trx_status_from_full(full_trx_status) == RX_AACK_ON) - { + if ((full_trx_status & CCA_STATUS) && rf_if_trx_status_from_full(full_trx_status) == RX_AACK_ON) { success = rf_start_tx(); } - if (!success) - { + if (!success) { /*Send CCA fail notification*/ - if(device_driver.phy_tx_done_cb){ + if (device_driver.phy_tx_done_cb) { device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0); } } @@ -1984,8 +1937,7 @@ static void rf_handle_cca_ed_done(uint8_t full_trx_status) static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel) { int8_t ret_val = 0; - switch (new_state) - { + switch (new_state) { /*Reset PHY driver and set to idle*/ case PHY_INTERFACE_RESET: break; @@ -2034,16 +1986,12 @@ static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_ */ static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr) { - switch (extension_type) - { + switch (extension_type) { /*Control MAC pending bit for Indirect data transmission*/ case PHY_EXTENSION_CTRL_PENDING_BIT: - if(*data_ptr) - { + if (*data_ptr) { rf_if_ack_pending_ctrl(1); - } - else - { + } else { rf_if_ack_pending_ctrl(0); } break; @@ -2085,12 +2033,11 @@ static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_pt static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr) { int8_t ret_val = 0; - switch (address_type) - { + switch (address_type) { /*Set 48-bit address*/ case PHY_MAC_48BIT: break; - /*Set 64-bit address*/ + /*Set 64-bit address*/ case PHY_MAC_64BIT: rf_set_address(address_ptr); break; @@ -2120,137 +2067,93 @@ static void rf_init_phy_mode(void) /*Read used PHY Mode*/ tmp = rf_if_read_register(TRX_CTRL_2); /*Set ACK wait time for used data rate*/ - if(part == PART_AT86RF212) - { - if((tmp & 0x1f) == 0x00) - { + if (part == PART_AT86RF212) { + if ((tmp & 0x1f) == 0x00) { rf_sensitivity = -110; rf_ack_wait_duration = 938; tmp = BPSK_20; - } - else if((tmp & 0x1f) == 0x04) - { + } else if ((tmp & 0x1f) == 0x04) { rf_sensitivity = -108; rf_ack_wait_duration = 469; tmp = BPSK_40; - } - else if((tmp & 0x1f) == 0x14) - { + } else if ((tmp & 0x1f) == 0x14) { rf_sensitivity = -108; rf_ack_wait_duration = 469; tmp = BPSK_40_ALT; - } - else if((tmp & 0x1f) == 0x08) - { + } else if ((tmp & 0x1f) == 0x08) { rf_sensitivity = -101; rf_ack_wait_duration = 50; tmp = OQPSK_SIN_RC_100; - } - else if((tmp & 0x1f) == 0x09) - { + } else if ((tmp & 0x1f) == 0x09) { rf_sensitivity = -99; rf_ack_wait_duration = 30; tmp = OQPSK_SIN_RC_200; - } - else if((tmp & 0x1f) == 0x18) - { + } else if ((tmp & 0x1f) == 0x18) { rf_sensitivity = -102; rf_ack_wait_duration = 50; tmp = OQPSK_RC_100; - } - else if((tmp & 0x1f) == 0x19) - { + } else if ((tmp & 0x1f) == 0x19) { rf_sensitivity = -100; rf_ack_wait_duration = 30; tmp = OQPSK_RC_200; - } - else if((tmp & 0x1f) == 0x0c) - { + } else if ((tmp & 0x1f) == 0x0c) { rf_sensitivity = -100; rf_ack_wait_duration = 20; tmp = OQPSK_SIN_250; - } - else if((tmp & 0x1f) == 0x0d) - { + } else if ((tmp & 0x1f) == 0x0d) { rf_sensitivity = -98; rf_ack_wait_duration = 25; tmp = OQPSK_SIN_500; - } - else if((tmp & 0x1f) == 0x0f) - { + } else if ((tmp & 0x1f) == 0x0f) { rf_sensitivity = -98; rf_ack_wait_duration = 25; tmp = OQPSK_SIN_500_ALT; - } - else if((tmp & 0x1f) == 0x1c) - { + } else if ((tmp & 0x1f) == 0x1c) { rf_sensitivity = -101; rf_ack_wait_duration = 20; tmp = OQPSK_RC_250; - } - else if((tmp & 0x1f) == 0x1d) - { + } else if ((tmp & 0x1f) == 0x1d) { rf_sensitivity = -99; rf_ack_wait_duration = 25; tmp = OQPSK_RC_500; - } - else if((tmp & 0x1f) == 0x1f) - { + } else if ((tmp & 0x1f) == 0x1f) { rf_sensitivity = -99; rf_ack_wait_duration = 25; tmp = OQPSK_RC_500_ALT; - } - else if((tmp & 0x3f) == 0x2A) - { + } else if ((tmp & 0x3f) == 0x2A) { rf_sensitivity = -91; rf_ack_wait_duration = 25; tmp = OQPSK_SIN_RC_400_SCR_ON; - } - else if((tmp & 0x3f) == 0x0A) - { + } else if ((tmp & 0x3f) == 0x0A) { rf_sensitivity = -91; rf_ack_wait_duration = 25; tmp = OQPSK_SIN_RC_400_SCR_OFF; - } - else if((tmp & 0x3f) == 0x3A) - { + } else if ((tmp & 0x3f) == 0x3A) { rf_sensitivity = -97; rf_ack_wait_duration = 25; tmp = OQPSK_RC_400_SCR_ON; - } - else if((tmp & 0x3f) == 0x1A) - { + } else if ((tmp & 0x3f) == 0x1A) { rf_sensitivity = -97; rf_ack_wait_duration = 25; tmp = OQPSK_RC_400_SCR_OFF; - } - else if((tmp & 0x3f) == 0x2E) - { + } else if ((tmp & 0x3f) == 0x2E) { rf_sensitivity = -93; rf_ack_wait_duration = 13; tmp = OQPSK_SIN_1000_SCR_ON; - } - else if((tmp & 0x3f) == 0x0E) - { + } else if ((tmp & 0x3f) == 0x0E) { rf_sensitivity = -93; rf_ack_wait_duration = 13; tmp = OQPSK_SIN_1000_SCR_OFF; - } - else if((tmp & 0x3f) == 0x3E) - { + } else if ((tmp & 0x3f) == 0x3E) { rf_sensitivity = -95; rf_ack_wait_duration = 13; tmp = OQPSK_RC_1000_SCR_ON; - } - else if((tmp & 0x3f) == 0x1E) - { + } else if ((tmp & 0x3f) == 0x1E) { rf_sensitivity = -95; rf_ack_wait_duration = 13; tmp = OQPSK_RC_1000_SCR_OFF; } - } - else - { + } else { rf_sensitivity = -101; rf_ack_wait_duration = 20; } @@ -2264,50 +2167,60 @@ static uint8_t rf_scale_lqi(int8_t rssi) uint8_t scaled_lqi; /*rssi < RF sensitivity*/ - if(rssi < rf_sensitivity) - scaled_lqi=0; + if (rssi < rf_sensitivity) { + scaled_lqi = 0; + } /*-91 dBm < rssi < -81 dBm (AT86RF233 XPro)*/ /*-90 dBm < rssi < -80 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 10)) - scaled_lqi=31; + else if (rssi < (rf_sensitivity + 10)) { + scaled_lqi = 31; + } /*-81 dBm < rssi < -71 dBm (AT86RF233 XPro)*/ /*-80 dBm < rssi < -70 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 20)) - scaled_lqi=207; + else if (rssi < (rf_sensitivity + 20)) { + scaled_lqi = 207; + } /*-71 dBm < rssi < -61 dBm (AT86RF233 XPro)*/ /*-70 dBm < rssi < -60 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 30)) - scaled_lqi=255; + else if (rssi < (rf_sensitivity + 30)) { + scaled_lqi = 255; + } /*-61 dBm < rssi < -51 dBm (AT86RF233 XPro)*/ /*-60 dBm < rssi < -50 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 40)) - scaled_lqi=255; + else if (rssi < (rf_sensitivity + 40)) { + scaled_lqi = 255; + } /*-51 dBm < rssi < -41 dBm (AT86RF233 XPro)*/ /*-50 dBm < rssi < -40 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 50)) - scaled_lqi=255; + else if (rssi < (rf_sensitivity + 50)) { + scaled_lqi = 255; + } /*-41 dBm < rssi < -31 dBm (AT86RF233 XPro)*/ /*-40 dBm < rssi < -30 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 60)) - scaled_lqi=255; + else if (rssi < (rf_sensitivity + 60)) { + scaled_lqi = 255; + } /*-31 dBm < rssi < -21 dBm (AT86RF233 XPro)*/ /*-30 dBm < rssi < -20 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 70)) - scaled_lqi=255; + else if (rssi < (rf_sensitivity + 70)) { + scaled_lqi = 255; + } /*rssi > RF saturation*/ - else if(rssi > (rf_sensitivity + 80)) - scaled_lqi=111; + else if (rssi > (rf_sensitivity + 80)) { + scaled_lqi = 111; + } /*-21 dBm < rssi < -11 dBm (AT86RF233 XPro)*/ /*-20 dBm < rssi < -10 dBm (AT86RF212B XPro)*/ - else - scaled_lqi=255; + else { + scaled_lqi = 255; + } return scaled_lqi; } NanostackRfPhyAtmel::NanostackRfPhyAtmel(PinName spi_mosi, PinName spi_miso, - PinName spi_sclk, PinName spi_cs, PinName spi_rst, PinName spi_slp, PinName spi_irq, - PinName i2c_sda, PinName i2c_scl) + PinName spi_sclk, PinName spi_cs, PinName spi_rst, PinName spi_slp, PinName spi_irq, + PinName i2c_sda, PinName i2c_scl) : _mac(i2c_sda, i2c_scl), _mac_addr(), _rf(NULL), _mac_set(false), _spi_mosi(spi_mosi), _spi_miso(spi_miso), _spi_sclk(spi_sclk), _spi_cs(spi_cs), _spi_rst(spi_rst), _spi_slp(spi_slp), _spi_irq(spi_irq) @@ -2337,7 +2250,7 @@ int8_t NanostackRfPhyAtmel::rf_register() // Read the mac address if it hasn't been set by a user rf = _rf; if (!_mac_set) { - int ret = _mac.read_eui64((void*)_mac_addr); + int ret = _mac.read_eui64((void *)_mac_addr); if (ret < 0) { rf = NULL; rf_if_unlock(); @@ -2378,7 +2291,7 @@ void NanostackRfPhyAtmel::get_mac_address(uint8_t *mac) rf_if_unlock(); return; } - memcpy((void*)mac, (void*)_mac_addr, sizeof(_mac_addr)); + memcpy((void *)mac, (void *)_mac_addr, sizeof(_mac_addr)); rf_if_unlock(); } @@ -2392,7 +2305,7 @@ void NanostackRfPhyAtmel::set_mac_address(uint8_t *mac) rf_if_unlock(); return; } - memcpy((void*)_mac_addr, (void*)mac, sizeof(_mac_addr)); + memcpy((void *)_mac_addr, (void *)mac, sizeof(_mac_addr)); _mac_set = true; rf_if_unlock(); @@ -2402,9 +2315,9 @@ void NanostackRfPhyAtmel::set_mac_address(uint8_t *mac) NanostackRfPhy &NanostackRfPhy::get_default_instance() { - static NanostackRfPhyAtmel rf_phy(ATMEL_SPI_MOSI, ATMEL_SPI_MISO, ATMEL_SPI_SCLK, ATMEL_SPI_CS, - ATMEL_SPI_RST, ATMEL_SPI_SLP, ATMEL_SPI_IRQ, ATMEL_I2C_SDA, ATMEL_I2C_SCL); - return rf_phy; + static NanostackRfPhyAtmel rf_phy(ATMEL_SPI_MOSI, ATMEL_SPI_MISO, ATMEL_SPI_SCLK, ATMEL_SPI_CS, + ATMEL_SPI_RST, ATMEL_SPI_SLP, ATMEL_SPI_IRQ, ATMEL_I2C_SDA, ATMEL_I2C_SCL); + return rf_phy; } #endif // MBED_CONF_ATMEL_RF_PROVIDE_DEFAULT diff --git a/components/802.15.4_RF/atmel-rf-driver/source/at24mac.cpp b/components/802.15.4_RF/atmel-rf-driver/source/at24mac.cpp index 0f45f5f158..cdb18a0cb7 100644 --- a/components/802.15.4_RF/atmel-rf-driver/source/at24mac.cpp +++ b/components/802.15.4_RF/atmel-rf-driver/source/at24mac.cpp @@ -15,44 +15,25 @@ */ #include "at24mac.h" +#if DEVICE_I2C + /* Device addressing */ -#define AT24MAC_EEPROM_ADDRESS (0x0A<<4) -#define AT24MAC_RW_PROTECT_ADDRESS (0x06<<4) -#define AT24MAC_SERIAL_ADDRESS (0x0B<<4) +#define AT24MAC_EEPROM_ADDRESS (0x0A<<4) +#define AT24MAC_RW_PROTECT_ADDRESS (0x06<<4) +#define AT24MAC_SERIAL_ADDRESS (0x0B<<4) /* Known memory blocks */ -#define AT24MAC_SERIAL_OFFSET (0x80) -#define AT24MAC_EUI64_OFFSET (0x98) -#define AT24MAC_EUI48_OFFSET (0x9A) +#define AT24MAC_SERIAL_OFFSET (0x80) +#define AT24MAC_EUI64_OFFSET (0x98) +#define AT24MAC_EUI48_OFFSET (0x9A) #define SERIAL_LEN 16 #define EUI64_LEN 8 #define EUI48_LEN 6 -AT24Mac::I2CReset::I2CReset(PinName sda, PinName scl) -{ - mbed::DigitalInOut pin_sda(sda, PIN_OUTPUT, PullUp, 1); - mbed::DigitalInOut pin_scl(scl, PIN_OUTPUT, PullUp, 0); - //generate 9 clocks for worst-case scenario - for (int i = 0; i < 10; ++i) { - pin_scl = 1; - wait_us(5); - pin_scl = 0; - wait_us(5); - } - //generate a STOP condition - pin_sda = 0; - wait_us(5); - pin_scl = 1; - wait_us(5); - pin_sda = 1; - wait_us(5); -} +using namespace mbed; -/*I2C needs to be reset before constructing the I2C object (in case I2C is stuck) - because they use the same pins, therefore i2c_reset has to be before _i2c - in the initializer list*/ -AT24Mac::AT24Mac(PinName sda, PinName scl) : i2c_reset(sda, scl), _i2c(sda, scl) +AT24Mac::AT24Mac(PinName sda, PinName scl) : _i2c(sda, scl) { // Do nothing } @@ -60,23 +41,28 @@ AT24Mac::AT24Mac(PinName sda, PinName scl) : i2c_reset(sda, scl), _i2c(sda, scl) int AT24Mac::read_serial(void *buf) { char offset = AT24MAC_SERIAL_OFFSET; - if (_i2c.write(AT24MAC_SERIAL_ADDRESS, &offset, 1, true)) - return -1; //No ACK - return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char*)buf, SERIAL_LEN); + if (_i2c.write(AT24MAC_SERIAL_ADDRESS, &offset, 1, true)) { + return -1; //No ACK + } + return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char *)buf, SERIAL_LEN); } int AT24Mac::read_eui64(void *buf) { char offset = AT24MAC_EUI64_OFFSET; - if (_i2c.write(AT24MAC_SERIAL_ADDRESS, &offset, 1, true)) - return -1; //No ACK - return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char*)buf, EUI64_LEN); + if (_i2c.write(AT24MAC_SERIAL_ADDRESS, &offset, 1, true)) { + return -1; //No ACK + } + return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char *)buf, EUI64_LEN); } int AT24Mac::read_eui48(void *buf) { char offset = AT24MAC_EUI48_OFFSET; - if (_i2c.write(AT24MAC_SERIAL_ADDRESS, &offset, 1, true)) - return -1; //No ACK - return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char*)buf, EUI48_LEN); + if (_i2c.write(AT24MAC_SERIAL_ADDRESS, &offset, 1, true)) { + return -1; //No ACK + } + return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char *)buf, EUI48_LEN); } + +#endif /* DEVICE_I2C */ diff --git a/components/802.15.4_RF/atmel-rf-driver/source/at24mac.h b/components/802.15.4_RF/atmel-rf-driver/source/at24mac.h index 2a2c79f549..d89d24400f 100644 --- a/components/802.15.4_RF/atmel-rf-driver/source/at24mac.h +++ b/components/802.15.4_RF/atmel-rf-driver/source/at24mac.h @@ -17,6 +17,9 @@ #define AT24MAC_H #include "PinNames.h" + +#if DEVICE_I2C + #include "I2C.h" #include "drivers/DigitalInOut.h" #include "platform/mbed_wait_api.h" @@ -59,16 +62,8 @@ public: int read_eui48(void *buf); private: - /* - * Dummy class to allow us to reset I2C before the I2C constructor is called in - * the initializer list of AT24Mac's constructor - */ - class I2CReset { - public: - I2CReset(PinName sda, PinName scl); - }; - I2CReset i2c_reset; mbed::I2C _i2c; }; +#endif /* DEVICE_I2C */ #endif /* AT24MAC_H */ diff --git a/components/802.15.4_RF/mcr20a-rf-driver/mcr20a-rf-driver/NanostackRfPhyMcr20a.h b/components/802.15.4_RF/mcr20a-rf-driver/mcr20a-rf-driver/NanostackRfPhyMcr20a.h index e4f1a65a42..6ef567ad0d 100644 --- a/components/802.15.4_RF/mcr20a-rf-driver/mcr20a-rf-driver/NanostackRfPhyMcr20a.h +++ b/components/802.15.4_RF/mcr20a-rf-driver/mcr20a-rf-driver/NanostackRfPhyMcr20a.h @@ -55,12 +55,12 @@ public: virtual void set_mac_address(uint8_t *mac); private: - SPI _spi; - DigitalOut _rf_cs; - DigitalOut _rf_rst; - InterruptIn _rf_irq; - DigitalIn _rf_irq_pin; - Thread _irq_thread; + mbed::SPI _spi; + mbed::DigitalOut _rf_cs; + mbed::DigitalOut _rf_rst; + mbed::InterruptIn _rf_irq; + mbed::DigitalIn _rf_irq_pin; + rtos::Thread _irq_thread; void _pins_set(); void _pins_clear(); diff --git a/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Drv.c b/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Drv.c index a148cc5da0..f561c0d412 100644 --- a/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Drv.c +++ b/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Drv.c @@ -44,7 +44,7 @@ #if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI -#include "platform/arm_hal_interrupt.h" +#include "platform/mbed_critical.h" /***************************************************************************** * PRIVATE VARIABLES * @@ -106,16 +106,16 @@ uint32_t mPhyIrqDisableCnt = 1; *---------------------------------------------------------------------------*/ void MCR20Drv_Init ( -void + void ) { xcvr_spi_init(gXcvrSpiInstance_c); xcvr_spi_configure_speed(gXcvrSpiInstance_c, 8000000); gXcvrDeassertCS_d(); - #if !defined(TARGET_KW24D) - MCR20Drv_RST_B_Deassert(); - #endif +#if !defined(TARGET_KW24D) + MCR20Drv_RST_B_Deassert(); +#endif RF_IRQ_Init(); RF_IRQ_Disable(); mPhyIrqDisableCnt = 1; @@ -129,8 +129,8 @@ void *---------------------------------------------------------------------------*/ void MCR20Drv_DirectAccessSPIWrite ( -uint8_t address, -uint8_t value + uint8_t address, + uint8_t value ) { uint16_t txData; @@ -158,15 +158,14 @@ uint8_t value *---------------------------------------------------------------------------*/ void MCR20Drv_DirectAccessSPIMultiByteWrite ( -uint8_t startAddress, -uint8_t * byteArray, -uint8_t numOfBytes + uint8_t startAddress, + uint8_t *byteArray, + uint8_t numOfBytes ) { uint8_t txData; - if( (numOfBytes == 0) || (byteArray == 0) ) - { + if ((numOfBytes == 0) || (byteArray == 0)) { return; } @@ -193,8 +192,8 @@ uint8_t numOfBytes *---------------------------------------------------------------------------*/ void MCR20Drv_PB_SPIByteWrite ( -uint8_t address, -uint8_t value + uint8_t address, + uint8_t value ) { uint32_t txData; @@ -206,12 +205,12 @@ uint8_t value gXcvrAssertCS_d(); txData = TransceiverSPI_WriteSelect | - TransceiverSPI_PacketBuffAccessSelect | - TransceiverSPI_PacketBuffByteModeSelect; + TransceiverSPI_PacketBuffAccessSelect | + TransceiverSPI_PacketBuffByteModeSelect; txData |= (address) << 8; txData |= (value) << 16; - xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t*)&txData, 0, 3); + xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t *)&txData, 0, 3); gXcvrDeassertCS_d(); UnprotectFromMCR20Interrupt(); @@ -225,14 +224,13 @@ uint8_t value *---------------------------------------------------------------------------*/ void MCR20Drv_PB_SPIBurstWrite ( -uint8_t * byteArray, -uint8_t numOfBytes + uint8_t *byteArray, + uint8_t numOfBytes ) { uint8_t txData; - if( (numOfBytes == 0) || (byteArray == 0) ) - { + if ((numOfBytes == 0) || (byteArray == 0)) { return; } @@ -243,8 +241,8 @@ uint8_t numOfBytes gXcvrAssertCS_d(); txData = TransceiverSPI_WriteSelect | - TransceiverSPI_PacketBuffAccessSelect | - TransceiverSPI_PacketBuffBurstModeSelect; + TransceiverSPI_PacketBuffAccessSelect | + TransceiverSPI_PacketBuffBurstModeSelect; xcvr_spi_transfer(gXcvrSpiInstance_c, &txData, 0, 1); xcvr_spi_transfer(gXcvrSpiInstance_c, byteArray, 0, numOfBytes); @@ -262,7 +260,7 @@ uint8_t numOfBytes uint8_t MCR20Drv_DirectAccessSPIRead ( -uint8_t address + uint8_t address ) { uint8_t txData; @@ -275,7 +273,7 @@ uint8_t address gXcvrAssertCS_d(); txData = (address & TransceiverSPI_DirectRegisterAddressMask) | - TransceiverSPI_ReadSelect; + TransceiverSPI_ReadSelect; xcvr_spi_transfer(gXcvrSpiInstance_c, &txData, 0, sizeof(txData)); xcvr_spi_transfer(gXcvrSpiInstance_c, 0, &rxData, sizeof(rxData)); @@ -295,16 +293,15 @@ uint8_t address *---------------------------------------------------------------------------*/ uint8_t MCR20Drv_DirectAccessSPIMultiByteRead ( -uint8_t startAddress, -uint8_t * byteArray, -uint8_t numOfBytes + uint8_t startAddress, + uint8_t *byteArray, + uint8_t numOfBytes ) { uint8_t txData; uint8_t phyIRQSTS1; - if( (numOfBytes == 0) || (byteArray == 0) ) - { + if ((numOfBytes == 0) || (byteArray == 0)) { return 0; } @@ -315,7 +312,7 @@ uint8_t numOfBytes gXcvrAssertCS_d(); txData = (startAddress & TransceiverSPI_DirectRegisterAddressMask) | - TransceiverSPI_ReadSelect; + TransceiverSPI_ReadSelect; xcvr_spi_transfer(gXcvrSpiInstance_c, &txData, &phyIRQSTS1, sizeof(txData)); xcvr_spi_transfer(gXcvrSpiInstance_c, 0, byteArray, numOfBytes); @@ -334,15 +331,14 @@ uint8_t numOfBytes *---------------------------------------------------------------------------*/ uint8_t MCR20Drv_PB_SPIBurstRead ( -uint8_t * byteArray, -uint8_t numOfBytes + uint8_t *byteArray, + uint8_t numOfBytes ) { uint8_t txData; uint8_t phyIRQSTS1; - if( (numOfBytes == 0) || (byteArray == 0) ) - { + if ((numOfBytes == 0) || (byteArray == 0)) { return 0; } @@ -353,8 +349,8 @@ uint8_t numOfBytes gXcvrAssertCS_d(); txData = TransceiverSPI_ReadSelect | - TransceiverSPI_PacketBuffAccessSelect | - TransceiverSPI_PacketBuffBurstModeSelect; + TransceiverSPI_PacketBuffAccessSelect | + TransceiverSPI_PacketBuffBurstModeSelect; xcvr_spi_transfer(gXcvrSpiInstance_c, &txData, &phyIRQSTS1, sizeof(txData)); xcvr_spi_transfer(gXcvrSpiInstance_c, 0, byteArray, numOfBytes); @@ -373,8 +369,8 @@ uint8_t numOfBytes *---------------------------------------------------------------------------*/ void MCR20Drv_IndirectAccessSPIWrite ( -uint8_t address, -uint8_t value + uint8_t address, + uint8_t value ) { uint32_t txData; @@ -389,7 +385,7 @@ uint8_t value txData |= (address) << 8; txData |= (value) << 16; - xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t*)&txData, 0, 3); + xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t *)&txData, 0, 3); gXcvrDeassertCS_d(); UnprotectFromMCR20Interrupt(); @@ -403,15 +399,14 @@ uint8_t value *---------------------------------------------------------------------------*/ void MCR20Drv_IndirectAccessSPIMultiByteWrite ( -uint8_t startAddress, -uint8_t * byteArray, -uint8_t numOfBytes + uint8_t startAddress, + uint8_t *byteArray, + uint8_t numOfBytes ) { uint16_t txData; - if( (numOfBytes == 0) || (byteArray == 0) ) - { + if ((numOfBytes == 0) || (byteArray == 0)) { return; } @@ -424,8 +419,8 @@ uint8_t numOfBytes txData = TransceiverSPI_IARIndexReg; txData |= (startAddress) << 8; - xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t*)&txData, 0, sizeof(txData)); - xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t*)byteArray, 0, numOfBytes); + xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t *)&txData, 0, sizeof(txData)); + xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t *)byteArray, 0, numOfBytes); gXcvrDeassertCS_d(); UnprotectFromMCR20Interrupt(); @@ -439,7 +434,7 @@ uint8_t numOfBytes *---------------------------------------------------------------------------*/ uint8_t MCR20Drv_IndirectAccessSPIRead ( -uint8_t address + uint8_t address ) { uint16_t txData; @@ -454,7 +449,7 @@ uint8_t address txData = TransceiverSPI_IARIndexReg | TransceiverSPI_ReadSelect; txData |= (address) << 8; - xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t*)&txData, 0, sizeof(txData)); + xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t *)&txData, 0, sizeof(txData)); xcvr_spi_transfer(gXcvrSpiInstance_c, 0, &rxData, sizeof(rxData)); gXcvrDeassertCS_d(); @@ -471,15 +466,14 @@ uint8_t address *---------------------------------------------------------------------------*/ void MCR20Drv_IndirectAccessSPIMultiByteRead ( -uint8_t startAddress, -uint8_t * byteArray, -uint8_t numOfBytes + uint8_t startAddress, + uint8_t *byteArray, + uint8_t numOfBytes ) { uint16_t txData; - if( (numOfBytes == 0) || (byteArray == 0) ) - { + if ((numOfBytes == 0) || (byteArray == 0)) { return; } @@ -492,7 +486,7 @@ uint8_t numOfBytes txData = (TransceiverSPI_IARIndexReg | TransceiverSPI_ReadSelect); txData |= (startAddress) << 8; - xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t*)&txData, 0, sizeof(txData)); + xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t *)&txData, 0, sizeof(txData)); xcvr_spi_transfer(gXcvrSpiInstance_c, 0, byteArray, numOfBytes); gXcvrDeassertCS_d(); @@ -507,7 +501,7 @@ uint8_t numOfBytes *---------------------------------------------------------------------------*/ uint32_t MCR20Drv_IsIrqPending ( -void + void ) { return RF_isIRQ_Pending(); @@ -521,19 +515,18 @@ void *---------------------------------------------------------------------------*/ void MCR20Drv_IRQ_Disable ( -void + void ) { - platform_enter_critical(); + core_util_critical_section_enter(); - if( mPhyIrqDisableCnt == 0 ) - { + if (mPhyIrqDisableCnt == 0) { RF_IRQ_Disable(); } mPhyIrqDisableCnt++; - platform_exit_critical(); + core_util_critical_section_exit(); } /*--------------------------------------------------------------------------- @@ -544,22 +537,20 @@ void *---------------------------------------------------------------------------*/ void MCR20Drv_IRQ_Enable ( -void + void ) { - platform_enter_critical(); + core_util_critical_section_enter(); - if( mPhyIrqDisableCnt ) - { + if (mPhyIrqDisableCnt) { mPhyIrqDisableCnt--; - if( mPhyIrqDisableCnt == 0 ) - { + if (mPhyIrqDisableCnt == 0) { RF_IRQ_Enable(); } } - platform_exit_critical(); + core_util_critical_section_exit(); } /*--------------------------------------------------------------------------- @@ -570,7 +561,7 @@ void *---------------------------------------------------------------------------*/ void MCR20Drv_RST_B_Assert ( -void + void ) { RF_RST_Set(0); @@ -584,7 +575,7 @@ void *---------------------------------------------------------------------------*/ void MCR20Drv_RST_B_Deassert ( -void + void ) { RF_RST_Set(1); @@ -598,7 +589,7 @@ void *---------------------------------------------------------------------------*/ void MCR20Drv_SoftRST_Assert ( -void + void ) { MCR20Drv_IndirectAccessSPIWrite(SOFT_RESET, (0x80)); @@ -612,7 +603,7 @@ void *---------------------------------------------------------------------------*/ void MCR20Drv_SoftRST_Deassert ( -void + void ) { MCR20Drv_IndirectAccessSPIWrite(SOFT_RESET, (0x00)); @@ -626,7 +617,7 @@ void *---------------------------------------------------------------------------*/ void MCR20Drv_Soft_RESET ( -void + void ) { //assert SOG_RST @@ -644,19 +635,19 @@ void *---------------------------------------------------------------------------*/ void MCR20Drv_RESET ( -void + void ) { - #if !defined(TARGET_KW24D) +#if !defined(TARGET_KW24D) volatile uint32_t delay = 1000; //assert RST_B MCR20Drv_RST_B_Assert(); - while(delay--); + while (delay--); //deassert RST_B MCR20Drv_RST_B_Deassert(); - #endif +#endif } /*--------------------------------------------------------------------------- @@ -667,13 +658,12 @@ void *---------------------------------------------------------------------------*/ void MCR20Drv_Set_CLK_OUT_Freq ( -uint8_t freqDiv + uint8_t freqDiv ) { uint8_t clkOutCtrlReg = (freqDiv & cCLK_OUT_DIV_Mask) | cCLK_OUT_EN | cCLK_OUT_EXTEND; - if(freqDiv == gCLK_OUT_FREQ_DISABLE) - { + if (freqDiv == gCLK_OUT_FREQ_DISABLE) { clkOutCtrlReg = (cCLK_OUT_EXTEND | gCLK_OUT_FREQ_4_MHz); //reset value with clock out disabled } diff --git a/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Drv.h b/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Drv.h index 332de94a5d..c2d013eb52 100644 --- a/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Drv.h +++ b/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Drv.h @@ -53,7 +53,7 @@ *****************************************************************************/ /* Disable XCVR clock output by default, to reduce power consumption */ -#ifndef gMCR20_ClkOutFreq_d +#ifndef gMCR20_ClkOutFreq_d #define gMCR20_ClkOutFreq_d gCLK_OUT_FREQ_DISABLE #endif @@ -73,7 +73,7 @@ *---------------------------------------------------------------------------*/ extern void MCR20Drv_Init ( - void + void ); /*--------------------------------------------------------------------------- @@ -84,7 +84,7 @@ extern void MCR20Drv_Init *---------------------------------------------------------------------------*/ void MCR20Drv_SPI_DMA_Init ( - void + void ); /*--------------------------------------------------------------------------- @@ -95,8 +95,8 @@ void MCR20Drv_SPI_DMA_Init *---------------------------------------------------------------------------*/ void MCR20Drv_Start_PB_DMA_SPI_Write ( - uint8_t * srcAddress, - uint8_t numOfBytes + uint8_t *srcAddress, + uint8_t numOfBytes ); /*--------------------------------------------------------------------------- @@ -107,8 +107,8 @@ void MCR20Drv_Start_PB_DMA_SPI_Write *---------------------------------------------------------------------------*/ void MCR20Drv_Start_PB_DMA_SPI_Read ( - uint8_t * dstAddress, - uint8_t numOfBytes + uint8_t *dstAddress, + uint8_t numOfBytes ); /*--------------------------------------------------------------------------- @@ -119,8 +119,8 @@ void MCR20Drv_Start_PB_DMA_SPI_Read *---------------------------------------------------------------------------*/ void MCR20Drv_DirectAccessSPIWrite ( - uint8_t address, - uint8_t value + uint8_t address, + uint8_t value ); /*--------------------------------------------------------------------------- @@ -131,9 +131,9 @@ void MCR20Drv_DirectAccessSPIWrite *---------------------------------------------------------------------------*/ void MCR20Drv_DirectAccessSPIMultiByteWrite ( - uint8_t startAddress, - uint8_t * byteArray, - uint8_t numOfBytes + uint8_t startAddress, + uint8_t *byteArray, + uint8_t numOfBytes ); /*--------------------------------------------------------------------------- @@ -144,8 +144,8 @@ void MCR20Drv_DirectAccessSPIMultiByteWrite *---------------------------------------------------------------------------*/ void MCR20Drv_PB_SPIBurstWrite ( - uint8_t * byteArray, - uint8_t numOfBytes + uint8_t *byteArray, + uint8_t numOfBytes ); /*--------------------------------------------------------------------------- @@ -156,7 +156,7 @@ void MCR20Drv_PB_SPIBurstWrite *---------------------------------------------------------------------------*/ uint8_t MCR20Drv_DirectAccessSPIRead ( - uint8_t address + uint8_t address ); /*--------------------------------------------------------------------------- @@ -168,9 +168,9 @@ uint8_t MCR20Drv_DirectAccessSPIRead uint8_t MCR20Drv_DirectAccessSPIMultiByteRead ( - uint8_t startAddress, - uint8_t * byteArray, - uint8_t numOfBytes + uint8_t startAddress, + uint8_t *byteArray, + uint8_t numOfBytes ); /*--------------------------------------------------------------------------- @@ -181,8 +181,8 @@ uint8_t MCR20Drv_DirectAccessSPIMultiByteRead *---------------------------------------------------------------------------*/ void MCR20Drv_PB_SPIByteWrite ( - uint8_t address, - uint8_t value + uint8_t address, + uint8_t value ); /*--------------------------------------------------------------------------- @@ -193,8 +193,8 @@ void MCR20Drv_PB_SPIByteWrite *---------------------------------------------------------------------------*/ uint8_t MCR20Drv_PB_SPIBurstRead ( - uint8_t * byteArray, - uint8_t numOfBytes + uint8_t *byteArray, + uint8_t numOfBytes ); /*--------------------------------------------------------------------------- @@ -205,8 +205,8 @@ uint8_t MCR20Drv_PB_SPIBurstRead *---------------------------------------------------------------------------*/ void MCR20Drv_IndirectAccessSPIWrite ( - uint8_t address, - uint8_t value + uint8_t address, + uint8_t value ); /*--------------------------------------------------------------------------- @@ -217,9 +217,9 @@ void MCR20Drv_IndirectAccessSPIWrite *---------------------------------------------------------------------------*/ void MCR20Drv_IndirectAccessSPIMultiByteWrite ( - uint8_t startAddress, - uint8_t * byteArray, - uint8_t numOfBytes + uint8_t startAddress, + uint8_t *byteArray, + uint8_t numOfBytes ); /*--------------------------------------------------------------------------- @@ -230,7 +230,7 @@ void MCR20Drv_IndirectAccessSPIMultiByteWrite *---------------------------------------------------------------------------*/ uint8_t MCR20Drv_IndirectAccessSPIRead ( - uint8_t address + uint8_t address ); /*--------------------------------------------------------------------------- * Name: MCR20Drv_IndirectAccessSPIMultiByteRead @@ -240,9 +240,9 @@ uint8_t MCR20Drv_IndirectAccessSPIRead *---------------------------------------------------------------------------*/ void MCR20Drv_IndirectAccessSPIMultiByteRead ( - uint8_t startAddress, - uint8_t * byteArray, - uint8_t numOfBytes + uint8_t startAddress, + uint8_t *byteArray, + uint8_t numOfBytes ); /*--------------------------------------------------------------------------- @@ -253,7 +253,7 @@ void MCR20Drv_IndirectAccessSPIMultiByteRead *---------------------------------------------------------------------------*/ uint32_t MCR20Drv_IsIrqPending ( - void + void ); /*--------------------------------------------------------------------------- @@ -264,7 +264,7 @@ uint32_t MCR20Drv_IsIrqPending *---------------------------------------------------------------------------*/ void MCR20Drv_IRQ_Disable ( - void + void ); /*--------------------------------------------------------------------------- @@ -275,7 +275,7 @@ void MCR20Drv_IRQ_Disable *---------------------------------------------------------------------------*/ void MCR20Drv_IRQ_Enable ( - void + void ); /*--------------------------------------------------------------------------- @@ -286,7 +286,7 @@ void MCR20Drv_IRQ_Enable *---------------------------------------------------------------------------*/ void MCR20Drv_RST_B_PortConfig ( - void + void ); /*--------------------------------------------------------------------------- @@ -297,7 +297,7 @@ void MCR20Drv_RST_B_PortConfig *---------------------------------------------------------------------------*/ void MCR20Drv_RST_B_Assert ( - void + void ); /*--------------------------------------------------------------------------- @@ -308,7 +308,7 @@ void MCR20Drv_RST_B_Assert *---------------------------------------------------------------------------*/ void MCR20Drv_RST_B_Deassert ( - void + void ); /*--------------------------------------------------------------------------- @@ -319,7 +319,7 @@ void MCR20Drv_RST_B_Deassert *---------------------------------------------------------------------------*/ void MCR20Drv_SoftRST_Assert ( - void + void ); /*--------------------------------------------------------------------------- @@ -330,7 +330,7 @@ void MCR20Drv_SoftRST_Assert *---------------------------------------------------------------------------*/ void MCR20Drv_SoftRST_Deassert ( - void + void ); @@ -342,7 +342,7 @@ void MCR20Drv_SoftRST_Deassert *---------------------------------------------------------------------------*/ void MCR20Drv_RESET ( - void + void ); /*--------------------------------------------------------------------------- @@ -353,7 +353,7 @@ void MCR20Drv_RESET *---------------------------------------------------------------------------*/ void MCR20Drv_Soft_RESET ( - void + void ); /*--------------------------------------------------------------------------- @@ -364,7 +364,7 @@ void MCR20Drv_Soft_RESET *---------------------------------------------------------------------------*/ void MCR20Drv_Set_CLK_OUT_Freq ( - uint8_t freqDiv + uint8_t freqDiv ); #define ProtectFromMCR20Interrupt() MCR20Drv_IRQ_Disable() diff --git a/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Overwrites.h b/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Overwrites.h index 4b0221132b..3b2c063f3f 100644 --- a/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Overwrites.h +++ b/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Overwrites.h @@ -35,9 +35,9 @@ #define OVERWRITES_H_ typedef struct overwrites_tag { - char address; - char data; -}overwrites_t; + char address; + char data; +} overwrites_t; /*****************************************************************************************************************/ @@ -66,37 +66,37 @@ typedef struct overwrites_tag { // // Write access to direct space requires only a single address, data pair. -overwrites_t const overwrites_direct[] ={ -{0x3B, 0x0C}, //version 0C: new value for ACKDELAY targeting 198us (23 May, 2013, Larry Roshak) -{0x23, 0x17} //PA_PWR new default Power Step is "23" +overwrites_t const overwrites_direct[] = { + {0x3B, 0x0C}, //version 0C: new value for ACKDELAY targeting 198us (23 May, 2013, Larry Roshak) + {0x23, 0x17} //PA_PWR new default Power Step is "23" }; -overwrites_t const overwrites_indirect[] ={ -{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) -{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 -{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 -{0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid) -{0x79, 0x2F}, //CHF_IBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) -{0x7A, 0x2F}, //CHF_QBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) -{0x7B, 0x24}, //CHF_IRIN Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x7C, 0x24}, //CHF_QRIN Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x7D, 0x24}, //CHF_IL Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x7E, 0x24}, //CHF_QL Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x7F, 0x32}, //CHF_CC1 Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x80, 0x1D}, //CHF_CCL Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x81, 0x2D}, //CHF_CC2 Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x82, 0x24}, //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x83, 0x24}, //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x64, 0x28}, //PA_CAL_DIS=1 Disabled PA calibration -{0x52, 0x55}, //AGC_THR1 RSSI tune up -{0x53, 0x2D}, //AGC_THR2 RSSI tune up -{0x66, 0x5F}, //ATT_RSSI1 tune up -{0x67, 0x8F}, //ATT_RSSI2 tune up -{0x68, 0x61}, //RSSI_OFFSET -{0x78, 0x03}, //CHF_PMAGAIN -{0x22, 0x50}, //CCA1_THRESH -{0x4D, 0x13}, //CORR_NVAL moved from 0x14 to 0x13 for 0.5 dB improved Rx Sensitivity -{0x39, 0x3D} //ACKDELAY new value targeting a delay of 198us (23 May, 2013, Larry Roshak) +overwrites_t const overwrites_indirect[] = { + {0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) + {0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 + {0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 + {0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid) + {0x79, 0x2F}, //CHF_IBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) + {0x7A, 0x2F}, //CHF_QBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) + {0x7B, 0x24}, //CHF_IRIN Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) + {0x7C, 0x24}, //CHF_QRIN Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) + {0x7D, 0x24}, //CHF_IL Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) + {0x7E, 0x24}, //CHF_QL Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) + {0x7F, 0x32}, //CHF_CC1 Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) + {0x80, 0x1D}, //CHF_CCL Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) + {0x81, 0x2D}, //CHF_CC2 Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) + {0x82, 0x24}, //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) + {0x83, 0x24}, //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) + {0x64, 0x28}, //PA_CAL_DIS=1 Disabled PA calibration + {0x52, 0x55}, //AGC_THR1 RSSI tune up + {0x53, 0x2D}, //AGC_THR2 RSSI tune up + {0x66, 0x5F}, //ATT_RSSI1 tune up + {0x67, 0x8F}, //ATT_RSSI2 tune up + {0x68, 0x61}, //RSSI_OFFSET + {0x78, 0x03}, //CHF_PMAGAIN + {0x22, 0x50}, //CCA1_THRESH + {0x4D, 0x13}, //CORR_NVAL moved from 0x14 to 0x13 for 0.5 dB improved Rx Sensitivity + {0x39, 0x3D} //ACKDELAY new value targeting a delay of 198us (23 May, 2013, Larry Roshak) }; @@ -107,25 +107,25 @@ overwrites_t const overwrites_indirect[] ={ ==VERSION 2== overwrites_t const overwrites_indirect[] ={ -{0x31, 0x02} //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) +{0x31, 0x02} //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) }; ==VERSION 3== overwrites_t const overwrites_indirect[] ={ -{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) -{0x91, 0xB3}, //VCO_CTRL1: override VCOALC_REF_TX to 3 -{0x92, 0x07} //VCO_CTRL2: override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 +{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) +{0x91, 0xB3}, //VCO_CTRL1: override VCOALC_REF_TX to 3 +{0x92, 0x07} //VCO_CTRL2: override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 }; ==VERSION 4== overwrites_t const overwrites_direct[] ={ -{0x3B, 0x04} //version 04 is the current version: update PA_COILTUNING default +{0x3B, 0x04} //version 04 is the current version: update PA_COILTUNING default }; overwrites_t const overwrites_indirect[] ={ -{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) -{0x91, 0xB3}, //VCO_CTRL1: override VCOALC_REF_TX to 3 -{0x92, 0x07} //VCO_CTRL2: override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 +{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) +{0x91, 0xB3}, //VCO_CTRL1: override VCOALC_REF_TX to 3 +{0x92, 0x07} //VCO_CTRL2: override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 {0x8A, 0x71} //PA_TUNING: override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid) }; @@ -135,9 +135,9 @@ overwrites_t const overwrites_direct[] ={ }; overwrites_t const overwrites_indirect[] ={ -{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) -{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 -{0x92, 0x07} //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 +{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) +{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 +{0x92, 0x07} //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 {0x8A, 0x71} //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid) {0x79, 0x2F} //CHF_IBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) {0x7A, 0x2F} //CHF_QBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) @@ -154,13 +154,13 @@ overwrites_t const overwrites_indirect[] ={ ==VERSION 6== overwrites_t const overwrites_direct[] ={ -{0x3B, 0x06} //version 06: disable PA calibration +{0x3B, 0x06} //version 06: disable PA calibration }; overwrites_t const overwrites_indirect[] ={ -{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) -{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 -{0x92, 0x07} //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 +{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) +{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 +{0x92, 0x07} //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 {0x8A, 0x71} //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid) {0x79, 0x2F} //CHF_IBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) {0x7A, 0x2F} //CHF_QBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) @@ -173,18 +173,18 @@ overwrites_t const overwrites_indirect[] ={ {0x7F, 0x32} //CHF_CC1 Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) {0x80, 0x1D} //CHF_CCL Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) {0x81, 0x2D} //CHF_CC2 Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x64, 0x28} //PA_CAL_DIS=1 Disabled PA calibration +{0x64, 0x28} //PA_CAL_DIS=1 Disabled PA calibration }; ==VERSION 7== overwrites_t const overwrites_direct[] ={ -{0x3B, 0x07} //version 07: updated registers for ED/RSSI +{0x3B, 0x07} //version 07: updated registers for ED/RSSI }; overwrites_t const overwrites_indirect[] ={ -{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) -{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 -{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 +{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) +{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 +{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 {0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid) {0x79, 0x2F}, //CHF_IBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) {0x7A, 0x2F}, //CHF_QBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) @@ -197,25 +197,25 @@ overwrites_t const overwrites_indirect[] ={ {0x7F, 0x32}, //CHF_CC1 Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) {0x80, 0x1D}, //CHF_CCL Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) {0x81, 0x2D}, //CHF_CC2 Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x64, 0x28}, //PA_CAL_DIS=1 Disabled PA calibration -{0x52, 0x73}, //AGC_THR1 RSSI tune up -{0x53, 0x2D}, //AGC_THR2 RSSI tune up -{0x66, 0x5F}, //ATT_RSSI1 tune up -{0x67, 0x8F}, //ATT_RSSI2 tune up -{0x68, 0x60}, //RSSI_OFFSET -{0x69, 0x65} //RSSI_SLOPE +{0x64, 0x28}, //PA_CAL_DIS=1 Disabled PA calibration +{0x52, 0x73}, //AGC_THR1 RSSI tune up +{0x53, 0x2D}, //AGC_THR2 RSSI tune up +{0x66, 0x5F}, //ATT_RSSI1 tune up +{0x67, 0x8F}, //ATT_RSSI2 tune up +{0x68, 0x60}, //RSSI_OFFSET +{0x69, 0x65} //RSSI_SLOPE }; ==VERSION 8== overwrites_t const overwrites_direct[] ={ -{0x3B, 0x08} //version 08: updated registers for ED/RSSI +{0x3B, 0x08} //version 08: updated registers for ED/RSSI }; overwrites_t const overwrites_indirect[] ={ -{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) -{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 -{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 +{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) +{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 +{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 {0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid) {0x79, 0x2F}, //CHF_IBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) {0x7A, 0x2F}, //CHF_QBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) @@ -228,27 +228,27 @@ overwrites_t const overwrites_indirect[] ={ {0x7F, 0x32}, //CHF_CC1 Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) {0x80, 0x1D}, //CHF_CCL Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) {0x81, 0x2D}, //CHF_CC2 Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x64, 0x28}, //PA_CAL_DIS=1 Disabled PA calibration -{0x52, 0x73}, //AGC_THR1 RSSI tune up -{0x53, 0x2D}, //AGC_THR2 RSSI tune up -{0x66, 0x5F}, //ATT_RSSI1 tune up -{0x67, 0x8F}, //ATT_RSSI2 tune up -{0x69, 0x65} //RSSI_SLOPE -{0x68, 0x61}, //RSSI_OFFSET -{0x78, 0x03} //CHF_PMAGAIN +{0x64, 0x28}, //PA_CAL_DIS=1 Disabled PA calibration +{0x52, 0x73}, //AGC_THR1 RSSI tune up +{0x53, 0x2D}, //AGC_THR2 RSSI tune up +{0x66, 0x5F}, //ATT_RSSI1 tune up +{0x67, 0x8F}, //ATT_RSSI2 tune up +{0x69, 0x65} //RSSI_SLOPE +{0x68, 0x61}, //RSSI_OFFSET +{0x78, 0x03} //CHF_PMAGAIN }; ==VERSION 9== overwrites_t const overwrites_direct[] ={ -{0x3B, 0x09} //version 09: updated registers for ED/RSSI and PowerStep -{0x23, 0x17} //PA_PWR new default value +{0x3B, 0x09} //version 09: updated registers for ED/RSSI and PowerStep +{0x23, 0x17} //PA_PWR new default value }; overwrites_t const overwrites_indirect[] ={ -{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) -{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 -{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 +{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) +{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 +{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 {0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid) {0x79, 0x2F}, //CHF_IBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) {0x7A, 0x2F}, //CHF_QBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) @@ -261,25 +261,25 @@ overwrites_t const overwrites_indirect[] ={ {0x81, 0x2D}, //CHF_CC2 Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) {0x82, 0x24}, //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) {0x83, 0x24}, //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x64, 0x28}, //PA_CAL_DIS=1 Disabled PA calibration -{0x52, 0x55}, //AGC_THR1 RSSI tune up -{0x53, 0x2D}, //AGC_THR2 RSSI tune up -{0x66, 0x5F}, //ATT_RSSI1 tune up -{0x67, 0x8F}, //ATT_RSSI2 tune up -{0x68, 0x61}, //RSSI_OFFSET -{0x78, 0x03} //CHF_PMAGAIN +{0x64, 0x28}, //PA_CAL_DIS=1 Disabled PA calibration +{0x52, 0x55}, //AGC_THR1 RSSI tune up +{0x53, 0x2D}, //AGC_THR2 RSSI tune up +{0x66, 0x5F}, //ATT_RSSI1 tune up +{0x67, 0x8F}, //ATT_RSSI2 tune up +{0x68, 0x61}, //RSSI_OFFSET +{0x78, 0x03} //CHF_PMAGAIN }; ==VERSION A== overwrites_t const overwrites_direct[] ={ -{0x3B, 0x0A} //version 0A: updated registers for CCA -{0x23, 0x17} //PA_PWR new default Power Step is "23" +{0x3B, 0x0A} //version 0A: updated registers for CCA +{0x23, 0x17} //PA_PWR new default Power Step is "23" }; overwrites_t const overwrites_indirect[] ={ -{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) -{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 -{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 +{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) +{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3 +{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 {0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid) {0x79, 0x2F}, //CHF_IBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) {0x7A, 0x2F}, //CHF_QBUF Adjust the gm-C filter gain (+/- 6dB) (21 Dec, 2012, on behalf of S. Soca) @@ -292,14 +292,14 @@ overwrites_t const overwrites_indirect[] ={ {0x81, 0x2D}, //CHF_CC2 Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca) {0x82, 0x24}, //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) {0x83, 0x24}, //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz) (21 Dec, 2012, on behalf of S. Soca) -{0x64, 0x28}, //PA_CAL_DIS=1 Disabled PA calibration -{0x52, 0x55}, //AGC_THR1 RSSI tune up -{0x53, 0x2D}, //AGC_THR2 RSSI tune up -{0x66, 0x5F}, //ATT_RSSI1 tune up -{0x67, 0x8F}, //ATT_RSSI2 tune up -{0x68, 0x61}, //RSSI_OFFSET -{0x78, 0x03} //CHF_PMAGAIN -{0x22, 0x50} //CCA1_THRESH +{0x64, 0x28}, //PA_CAL_DIS=1 Disabled PA calibration +{0x52, 0x55}, //AGC_THR1 RSSI tune up +{0x53, 0x2D}, //AGC_THR2 RSSI tune up +{0x66, 0x5F}, //ATT_RSSI1 tune up +{0x67, 0x8F}, //ATT_RSSI2 tune up +{0x68, 0x61}, //RSSI_OFFSET +{0x78, 0x03} //CHF_PMAGAIN +{0x22, 0x50} //CCA1_THRESH }; end of deprecated versions */ diff --git a/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Reg.h b/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Reg.h index a77686f2a0..96410c9a9c 100644 --- a/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Reg.h +++ b/components/802.15.4_RF/mcr20a-rf-driver/source/MCR20Reg.h @@ -312,18 +312,18 @@ #define cIRQSTS1_TXIRQ (1<<1) #define cIRQSTS1_SEQIRQ (1<<0) -typedef union regIRQSTS1_tag{ - uint8_t byte; - struct{ - uint8_t SEQIRQ:1; - uint8_t TXIRQ:1; - uint8_t RXIRQ:1; - uint8_t CCAIRQ:1; - uint8_t RXWTRMRKIRQ:1; - uint8_t FILTERFAIL_IRQ:1; - uint8_t PLL_UNLOCK_IRQ:1; - uint8_t RX_FRM_PEND:1; - }bit; +typedef union regIRQSTS1_tag { + uint8_t byte; + struct { + uint8_t SEQIRQ: 1; + uint8_t TXIRQ: 1; + uint8_t RXIRQ: 1; + uint8_t CCAIRQ: 1; + uint8_t RXWTRMRKIRQ: 1; + uint8_t FILTERFAIL_IRQ: 1; + uint8_t PLL_UNLOCK_IRQ: 1; + uint8_t RX_FRM_PEND: 1; + } bit; } regIRQSTS1_t; // IRQSTS2 bits @@ -336,18 +336,18 @@ typedef union regIRQSTS1_tag{ #define cIRQSTS2_PB_ERR_IRQ (1<<1) #define cIRQSTS2_WAKE_IRQ (1<<0) -typedef union regIRQSTS2_tag{ - uint8_t byte; - struct{ - uint8_t WAKE_IRQ:1; - uint8_t PB_ERR_IRQ:1; - uint8_t ASM_IRQ:1; - uint8_t TMRSTATUS:1; - uint8_t PI_:1; - uint8_t SRCADDR:1; - uint8_t CCA:1; - uint8_t CRCVALID:1; - }bit; +typedef union regIRQSTS2_tag { + uint8_t byte; + struct { + uint8_t WAKE_IRQ: 1; + uint8_t PB_ERR_IRQ: 1; + uint8_t ASM_IRQ: 1; + uint8_t TMRSTATUS: 1; + uint8_t PI_: 1; + uint8_t SRCADDR: 1; + uint8_t CCA: 1; + uint8_t CRCVALID: 1; + } bit; } regIRQSTS2_t; // IRQSTS3 bits @@ -360,18 +360,18 @@ typedef union regIRQSTS2_tag{ #define cIRQSTS3_TMR2IRQ (1<<1) #define cIRQSTS3_TMR1IRQ (1<<0) -typedef union regIRQSTS3_tag{ - uint8_t byte; - struct{ - uint8_t TMR1IRQ:1; - uint8_t TMR2IRQ:1; - uint8_t TMR3IRQ:1; - uint8_t TMR4IRQ:1; - uint8_t TMR1MSK:1; - uint8_t TMR2MSK:1; - uint8_t TMR3MSK:1; - uint8_t TMR4MSK:1; - }bit; +typedef union regIRQSTS3_tag { + uint8_t byte; + struct { + uint8_t TMR1IRQ: 1; + uint8_t TMR2IRQ: 1; + uint8_t TMR3IRQ: 1; + uint8_t TMR4IRQ: 1; + uint8_t TMR1MSK: 1; + uint8_t TMR2MSK: 1; + uint8_t TMR3MSK: 1; + uint8_t TMR4MSK: 1; + } bit; } regIRQSTS3_t; // PHY_CTRL1 bits @@ -382,17 +382,17 @@ typedef union regIRQSTS3_tag{ #define cPHY_CTRL1_AUTOACK (1<<3) #define cPHY_CTRL1_XCVSEQ (7<<0) -typedef union regPHY_CTRL1_tag{ - uint8_t byte; - struct{ - uint8_t XCVSEQ:3; - uint8_t AUTOACK:1; - uint8_t RXACKRQD:1; - uint8_t CCABFRTX:1; - uint8_t SLOTTED:1; - uint8_t TMRTRIGEN:1; - }bit; -} regPHY_CTRL1_t; +typedef union regPHY_CTRL1_tag { + uint8_t byte; + struct { + uint8_t XCVSEQ: 3; + uint8_t AUTOACK: 1; + uint8_t RXACKRQD: 1; + uint8_t CCABFRTX: 1; + uint8_t SLOTTED: 1; + uint8_t TMRTRIGEN: 1; + } bit; +} regPHY_CTRL1_t; // PHY_CTRL2 bits #define cPHY_CTRL2_CRC_MSK (1<<7) @@ -404,19 +404,19 @@ typedef union regPHY_CTRL1_tag{ #define cPHY_CTRL2_TXMSK (1<<1) #define cPHY_CTRL2_SEQMSK (1<<0) -typedef union regPHY_CTRL2_tag{ - uint8_t byte; - struct{ - uint8_t SEQMSK:1; - uint8_t TXMSK:1; - uint8_t RXMSK:1; - uint8_t CCAMSK:1; - uint8_t RX_WMRK_MSK:1; - uint8_t FILTERFAIL_MSK:1; - uint8_t PLL_UNLOCK_MSK:1; - uint8_t CRC_MSK:1; - }bit; -} regPHY_CTRL2_t; +typedef union regPHY_CTRL2_tag { + uint8_t byte; + struct { + uint8_t SEQMSK: 1; + uint8_t TXMSK: 1; + uint8_t RXMSK: 1; + uint8_t CCAMSK: 1; + uint8_t RX_WMRK_MSK: 1; + uint8_t FILTERFAIL_MSK: 1; + uint8_t PLL_UNLOCK_MSK: 1; + uint8_t CRC_MSK: 1; + } bit; +} regPHY_CTRL2_t; // PHY_CTRL3 bits #define cPHY_CTRL3_TMR4CMP_EN (1<<7) @@ -427,18 +427,18 @@ typedef union regPHY_CTRL2_tag{ #define cPHY_CTRL3_PB_ERR_MSK (1<<1) #define cPHY_CTRL3_WAKE_MSK (1<<0) -typedef union regPHY_CTRL3_tag{ - uint8_t byte; - struct{ - uint8_t WAKE_MSK:1; - uint8_t PB_ERR_MSK:1; - uint8_t ASM_MSK:1; - uint8_t RESERVED:1; - uint8_t TMR1CMP_EN:1; - uint8_t TMR2CMP_EN:1; - uint8_t TMR3CMP_EN:1; - uint8_t TMR4CMP_EN:1; - }bit; +typedef union regPHY_CTRL3_tag { + uint8_t byte; + struct { + uint8_t WAKE_MSK: 1; + uint8_t PB_ERR_MSK: 1; + uint8_t ASM_MSK: 1; + uint8_t RESERVED: 1; + uint8_t TMR1CMP_EN: 1; + uint8_t TMR2CMP_EN: 1; + uint8_t TMR3CMP_EN: 1; + uint8_t TMR4CMP_EN: 1; + } bit; } regPHY_CTRL3_t; // RX_FRM_LEN bits @@ -454,17 +454,17 @@ typedef union regPHY_CTRL3_tag{ #define cPHY_CTRL4_PROMISCUOUS (1<<1) #define cPHY_CTRL4_TC2PRIME_EN (1<<0) -typedef union regPHY_CTRL4_tag{ - uint8_t byte; - struct{ - uint8_t TC2PRIME_EN:1; - uint8_t PROMISCUOUS:1; - uint8_t TMRLOAD:1; - uint8_t CCATYPE:2; - uint8_t PANCORDNTR0:1; - uint8_t TC3TMOUT:1; - uint8_t TRCV_MSK:1; - }bit; +typedef union regPHY_CTRL4_tag { + uint8_t byte; + struct { + uint8_t TC2PRIME_EN: 1; + uint8_t PROMISCUOUS: 1; + uint8_t TMRLOAD: 1; + uint8_t CCATYPE: 2; + uint8_t PANCORDNTR0: 1; + uint8_t TC3TMOUT: 1; + uint8_t TRCV_MSK: 1; + } bit; } regPHY_CTRL4_t; // SRC_CTRL bits @@ -475,15 +475,15 @@ typedef union regPHY_CTRL4_tag{ #define cSRC_CTRL_INDEX_EN (1<<1) #define cSRC_CTRL_INDEX_DISABLE (1<<0) -typedef union regSRC_CTRL_tag{ - uint8_t byte; - struct{ - uint8_t INDEX_DISABLE:1; - uint8_t INDEX_EN:1; - uint8_t SRCADDR_EN:1; - uint8_t ACK_FRM_PND:1; - uint8_t INDEX:4; - }bit; +typedef union regSRC_CTRL_tag { + uint8_t byte; + struct { + uint8_t INDEX_DISABLE: 1; + uint8_t INDEX_EN: 1; + uint8_t SRCADDR_EN: 1; + uint8_t ACK_FRM_PND: 1; + uint8_t INDEX: 4; + } bit; } regSRC_CTRL_t; // ASM_CTRL1 bits @@ -525,18 +525,18 @@ typedef union regSRC_CTRL_tag{ #define cRX_FRAME_FLT_DATA_FT (1<<1) #define cRX_FRAME_FLT_BEACON_FT (1<<0) -typedef union regRX_FRAME_FILTER_tag{ - uint8_t byte; - struct{ - uint8_t FRAME_FLT_BEACON_FT:1; - uint8_t FRAME_FLT_DATA_FT:1; - uint8_t FRAME_FLT_ACK_FT:1; - uint8_t FRAME_FLT_CMD_FT:1; - uint8_t FRAME_FLT_NS_FT:1; - uint8_t FRAME_FLT_ACTIVE_PROMISCUOUS:1; - uint8_t FRAME_FLT_FRM_VER:2; - }bit; -} regRX_FRAME_FILTER_t; +typedef union regRX_FRAME_FILTER_tag { + uint8_t byte; + struct { + uint8_t FRAME_FLT_BEACON_FT: 1; + uint8_t FRAME_FLT_DATA_FT: 1; + uint8_t FRAME_FLT_ACK_FT: 1; + uint8_t FRAME_FLT_CMD_FT: 1; + uint8_t FRAME_FLT_NS_FT: 1; + uint8_t FRAME_FLT_ACTIVE_PROMISCUOUS: 1; + uint8_t FRAME_FLT_FRM_VER: 2; + } bit; +} regRX_FRAME_FILTER_t; // DUAL_PAN_CTRL bits #define cDUAL_PAN_CTRL_DUAL_PAN_SAM_LVL_MSK (0xF0) diff --git a/components/802.15.4_RF/mcr20a-rf-driver/source/NanostackRfPhyMcr20a.cpp b/components/802.15.4_RF/mcr20a-rf-driver/source/NanostackRfPhyMcr20a.cpp index df2e4a3364..b2595401ba 100644 --- a/components/802.15.4_RF/mcr20a-rf-driver/source/NanostackRfPhyMcr20a.cpp +++ b/components/802.15.4_RF/mcr20a-rf-driver/source/NanostackRfPhyMcr20a.cpp @@ -23,6 +23,9 @@ #include #include "rtos.h" +using namespace mbed; +using namespace rtos; + /* Freescale headers which are for C files */ extern "C" { #include "MCR20Drv.h" @@ -57,40 +60,38 @@ extern "C" { #define gXcvrRunState_d gXcvrPwrAutodoze_c #if !defined(TARGET_KW24D) - #define gXcvrLowPowerState_d gXcvrPwrHibernate_c +#define gXcvrLowPowerState_d gXcvrPwrHibernate_c #else - #define gXcvrLowPowerState_d gXcvrPwrAutodoze_c +#define gXcvrLowPowerState_d gXcvrPwrAutodoze_c #endif /* MCR20A XCVR states */ -typedef enum xcvrState_tag{ - gIdle_c, - gRX_c, - gTX_c, - gCCA_c, - gTR_c, - gCCCA_c, -}xcvrState_t; +typedef enum xcvrState_tag { + gIdle_c, + gRX_c, + gTX_c, + gCCA_c, + gTR_c, + gCCCA_c, +} xcvrState_t; /* MCR20A XCVR low power states */ -typedef enum xcvrPwrMode_tag{ +typedef enum xcvrPwrMode_tag { gXcvrPwrIdle_c, gXcvrPwrAutodoze_c, gXcvrPwrDoze_c, gXcvrPwrHibernate_c -}xcvrPwrMode_t; +} xcvrPwrMode_t; /*RF Part Type*/ -typedef enum -{ +typedef enum { FREESCALE_UNKNOW_DEV = 0, FREESCALE_MCR20A -}rf_trx_part_e; +} rf_trx_part_e; /*Atmel RF states*/ -typedef enum -{ +typedef enum { NOP = 0x00, BUSY_RX = 0x01, RF_TX_START = 0x02, @@ -103,7 +104,7 @@ typedef enum SLEEP = 0x0F, RX_AACK_ON = 0x16, TX_ARET_ON = 0x19 -}rf_trx_states_t; +} rf_trx_states_t; /*RF receive buffer*/ static uint8_t rf_buffer[RF_BUFFER_SIZE]; @@ -140,8 +141,8 @@ static const uint16_t pll_frac[16] = {0x2800, 0x5000, 0x7800, 0xA000, 0xC800, 0x static const phy_rf_channel_configuration_s phy_24ghz = {2405000000U, 5000000U, 250000U, 16U, M_OQPSK}; static const phy_device_channel_page_s phy_channel_pages[] = { - { CHANNEL_PAGE_0, &phy_24ghz}, - { CHANNEL_PAGE_0, NULL} + { CHANNEL_PAGE_0, &phy_24ghz}, + { CHANNEL_PAGE_0, NULL} }; @@ -159,7 +160,7 @@ MBED_UNUSED static void rf_init(void); MBED_UNUSED static void rf_set_mac_address(const uint8_t *ptr); MBED_UNUSED static int8_t rf_device_register(void); MBED_UNUSED static void rf_device_unregister(void); -MBED_UNUSED static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol ); +MBED_UNUSED static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol); MBED_UNUSED static void rf_cca_abort(void); MBED_UNUSED static void rf_read_mac_address(uint8_t *ptr); MBED_UNUSED static int8_t rf_read_random(void); @@ -200,8 +201,8 @@ MBED_UNUSED static uint8_t rf_get_channel_energy(void); MBED_UNUSED static uint8_t rf_convert_energy_level(uint8_t energyLevel); MBED_UNUSED static int8_t rf_convert_LQI_to_RSSI(uint8_t lqi); MBED_UNUSED static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel); -MBED_UNUSED static int8_t rf_extension(phy_extension_type_e extension_type,uint8_t *data_ptr); -MBED_UNUSED static int8_t rf_address_write(phy_address_type_e address_type,uint8_t *address_ptr); +MBED_UNUSED static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr); +MBED_UNUSED static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr); static void PHY_InterruptThread(void); static void handle_interrupt(void); @@ -234,11 +235,10 @@ static int8_t rf_device_register(void) radio_type = rf_radio_type_read(); - if(radio_type == FREESCALE_MCR20A) - { + if (radio_type == FREESCALE_MCR20A) { /*Set pointer to MAC address*/ device_driver.PHY_MAC = MAC_address; - device_driver.driver_description = (char*)"FREESCALE_MAC"; + device_driver.driver_description = (char *)"FREESCALE_MAC"; //Create setup Used Radio chips /*Type of RF PHY is SubGHz*/ @@ -424,7 +424,7 @@ static uint16_t rf_get_phy_mtu_size(void) * * \return none */ -static void rf_set_short_adr(uint8_t * short_address) +static void rf_set_short_adr(uint8_t *short_address) { /* Write one register at a time to be accessible from hibernate mode */ MCR20Drv_IndirectAccessSPIWrite(MACSHORTADDRS0_MSB, short_address[0]); @@ -498,9 +498,9 @@ static void rf_init(void) /* Disable Tristate on MISO for SPI reads */ MCR20Drv_IndirectAccessSPIWrite(MISC_PAD_CTRL, 0x02); /* Set XCVR clock output settings */ - #if !defined(TARGET_KW24D) - MCR20Drv_Set_CLK_OUT_Freq(gMCR20_ClkOutFreq_d); - #endif +#if !defined(TARGET_KW24D) + MCR20Drv_Set_CLK_OUT_Freq(gMCR20_ClkOutFreq_d); +#endif /* Set default XCVR power state */ rf_set_power_state(gXcvrRunState_d); @@ -544,13 +544,15 @@ static void rf_init(void) MCR20Drv_IndirectAccessSPIWrite(RX_FRAME_FILTER, (cRX_FRAME_FLT_FRM_VER | \ cRX_FRAME_FLT_BEACON_FT | \ cRX_FRAME_FLT_DATA_FT | \ - cRX_FRAME_FLT_CMD_FT )); + cRX_FRAME_FLT_CMD_FT)); /* Direct register overwrites */ - for (index = 0; index < sizeof(overwrites_direct)/sizeof(overwrites_t); index++) + for (index = 0; index < sizeof(overwrites_direct) / sizeof(overwrites_t); index++) { MCR20Drv_DirectAccessSPIWrite(overwrites_direct[index].address, overwrites_direct[index].data); + } /* Indirect register overwrites */ - for (index = 0; index < sizeof(overwrites_indirect)/sizeof(overwrites_t); index++) + for (index = 0; index < sizeof(overwrites_indirect) / sizeof(overwrites_t); index++) { MCR20Drv_IndirectAccessSPIWrite(overwrites_indirect[index].address, overwrites_indirect[index].data); + } /* Set the CCA energy threshold value */ MCR20Drv_IndirectAccessSPIWrite(CCA1_THRESH, RF_CCA_THRESHOLD); @@ -605,22 +607,19 @@ static void rf_poll_trx_state_change(rf_trx_states_t trx_state) * \return 0 Success * \return -1 Busy */ -static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol ) +static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol) { uint8_t ccaMode; /* Parameter validation */ - if( !data_ptr || (data_length > 125) || (PHY_LAYER_PAYLOAD != data_protocol) ) - { + if (!data_ptr || (data_length > 125) || (PHY_LAYER_PAYLOAD != data_protocol)) { return -1; } - if( mPhySeqState == gRX_c ) - { + if (mPhySeqState == gRX_c) { uint8_t phyReg = MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F; /* Check for an Rx in progress. */ - if((phyReg <= 0x06) || (phyReg == 0x15) || (phyReg == 0x16)) - { + if ((phyReg <= 0x06) || (phyReg == 0x15) || (phyReg == 0x16)) { if (device_driver.phy_tx_done_cb) { device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1); } @@ -630,8 +629,7 @@ static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_h } /*Check if transmitter is busy*/ - if( mPhySeqState != gIdle_c ) - { + if (mPhySeqState != gIdle_c) { /*Return busy*/ return -1; } @@ -646,12 +644,11 @@ static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_h /* Load data into XCVR */ tx_len = data_length + 2; MCR20Drv_PB_SPIBurstWrite(data_ptr - 1, data_length + 1); - MCR20Drv_PB_SPIByteWrite(0,tx_len); + MCR20Drv_PB_SPIByteWrite(0, tx_len); /* Set CCA mode 1 */ ccaMode = (mStatusAndControlRegs[PHY_CTRL4] >> cPHY_CTRL4_CCATYPE_Shift_c) & cPHY_CTRL4_CCATYPE; - if( ccaMode != gCcaCCA_MODE1_c ) - { + if (ccaMode != gCcaCCA_MODE1_c) { mStatusAndControlRegs[PHY_CTRL4] &= ~(cPHY_CTRL4_CCATYPE << cPHY_CTRL4_CCATYPE_Shift_c); mStatusAndControlRegs[PHY_CTRL4] |= gCcaCCA_MODE1_c << cPHY_CTRL4_CCATYPE_Shift_c; MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, mStatusAndControlRegs[PHY_CTRL4]); @@ -701,13 +698,10 @@ static void rf_cca_abort(void) static void rf_start_tx(void) { /* Perform TxRxAck sequence if required by phyTxMode */ - if( need_ack ) - { + if (need_ack) { mStatusAndControlRegs[PHY_CTRL1] |= cPHY_CTRL1_RXACKRQD; mPhySeqState = gTR_c; - } - else - { + } else { mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_RXACKRQD); mPhySeqState = gTX_c; } @@ -721,8 +715,7 @@ static void rf_start_tx(void) /* Start the sequence immediately */ MCR20Drv_DirectAccessSPIMultiByteWrite(PHY_CTRL1, &mStatusAndControlRegs[PHY_CTRL1], 2); - if( need_ack ) - { + if (need_ack) { rf_ack_wait_timer_start(gPhyWarmUpTime_c + gPhySHRDuration_c + tx_len * gPhySymbolsPerOctet_c + gPhyAckWaitDuration_c); } } @@ -739,8 +732,7 @@ static void rf_receive(void) uint8_t phyRegs[5]; /* RX can start only from Idle state */ - if( mPhySeqState != gIdle_c ) - { + if (mPhySeqState != gIdle_c) { return; } @@ -801,8 +793,7 @@ static void rf_handle_rx_end(void) rf_receive(); /*Check the length is valid*/ - if(len > 1 && len < RF_BUFFER_SIZE) - { + if (len > 1 && len < RF_BUFFER_SIZE) { rf_lqi = rf_convert_LQI(rf_lqi); rf_rssi = rf_convert_LQI_to_RSSI(rf_lqi); /*gcararu: Scale LQI using received RSSI, to match the LQI reported by the ATMEL radio */ @@ -848,20 +839,14 @@ static void rf_handle_tx_end(void) } /*Call PHY TX Done API*/ - if( need_ack ) - { - if( rx_frame_pending ) - { + if (need_ack) { + if (rx_frame_pending) { device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE_PENDING, 1, 1); - } - else - { + } else { // arm_net_phy_tx_done(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1); device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE, 1, 1); } - } - else - { + } else { device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1); } } @@ -876,12 +861,9 @@ static void rf_handle_tx_end(void) static void rf_handle_cca_ed_done(void) { /*Check the result of CCA process*/ - if( !(mStatusAndControlRegs[IRQSTS2] & cIRQSTS2_CCA) ) - { + if (!(mStatusAndControlRegs[IRQSTS2] & cIRQSTS2_CCA)) { rf_start_tx(); - } - else if (device_driver.phy_tx_done_cb) - { + } else if (device_driver.phy_tx_done_cb) { /*Send CCA fail notification*/ device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1); } @@ -898,10 +880,9 @@ static void rf_handle_cca_ed_done(void) static int8_t rf_tx_power_set(uint8_t power) { /* gcapraru: Map MCR20A Tx power levels over ATMEL values */ - static uint8_t pwrLevelMapping[16] = {25,25,25,24,24,24,23,23,22,22,21,20,19,18,17,14}; + static uint8_t pwrLevelMapping[16] = {25, 25, 25, 24, 24, 24, 23, 23, 22, 22, 21, 20, 19, 18, 17, 14}; - if( power > 15 ) - { + if (power > 15) { return -1; } @@ -955,8 +936,7 @@ static int8_t rf_enable_antenna_diversity(void) static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel) { int8_t ret_val = 0; - switch (new_state) - { + switch (new_state) { /*Reset PHY driver and set to idle*/ case PHY_INTERFACE_RESET: break; @@ -993,19 +973,14 @@ static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_ */ static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr) { - switch (extension_type) - { + switch (extension_type) { /*Control MAC pending bit for Indirect data transmission*/ - case PHY_EXTENSION_CTRL_PENDING_BIT: - { + case PHY_EXTENSION_CTRL_PENDING_BIT: { uint8_t reg = MCR20Drv_DirectAccessSPIRead(SRC_CTRL); - if(*data_ptr) - { + if (*data_ptr) { reg |= cSRC_CTRL_ACK_FRM_PND; - } - else - { + } else { reg &= ~cSRC_CTRL_ACK_FRM_PND; } @@ -1023,19 +998,11 @@ static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_pt } break; } - /*Set channel*/ - case PHY_EXTENSION_SET_CHANNEL: - break; /*Read energy on the channel*/ case PHY_EXTENSION_READ_CHANNEL_ENERGY: *data_ptr = rf_get_channel_energy(); break; - /*Read status of the link*/ - case PHY_EXTENSION_READ_LINK_STATUS: - break; - case PHY_EXTENSION_CONVERT_SIGNAL_INFO: - break; - case PHY_EXTENSION_ACCEPT_ANY_BEACON: + default: break; } return 0; @@ -1052,12 +1019,11 @@ static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_pt static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr) { int8_t ret_val = 0; - switch (address_type) - { + switch (address_type) { /*Set 48-bit address*/ case PHY_MAC_48BIT: break; - /*Set 64-bit address*/ + /*Set 64-bit address*/ case PHY_MAC_64BIT: rf_set_address(address_ptr); break; @@ -1093,19 +1059,16 @@ static void rf_init_phy_mode(void) */ static void PHY_InterruptHandler(void) { - /* Disable and clear transceiver(IRQ_B) interrupt */ MCR20Drv_IRQ_Disable(); - irq_thread->signal_set(1); + irq_thread->flags_set(1); } static void PHY_InterruptThread(void) { for (;;) { - osEvent event = irq_thread->signal_wait(0); - if (event.status != osEventSignal) { - continue; - } + ThisThread::flags_wait_all(1); handle_interrupt(); + MCR20Drv_IRQ_Enable(); } } @@ -1113,8 +1076,6 @@ static void handle_interrupt(void) { uint8_t xcvseqCopy; - //MCR20Drv_IRQ_Clear(); - /* Read transceiver interrupt status and control registers */ mStatusAndControlRegs[IRQSTS1] = MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[IRQSTS2], 7); @@ -1122,11 +1083,9 @@ static void handle_interrupt(void) xcvseqCopy = mStatusAndControlRegs[PHY_CTRL1] & cPHY_CTRL1_XCVSEQ; /* Flter Fail IRQ */ - if( (mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_FILTERFAIL_IRQ) && - !(mStatusAndControlRegs[PHY_CTRL2] & cPHY_CTRL2_FILTERFAIL_MSK) ) - { - if( xcvseqCopy == gRX_c ) - { + if ((mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_FILTERFAIL_IRQ) && + !(mStatusAndControlRegs[PHY_CTRL2] & cPHY_CTRL2_FILTERFAIL_MSK)) { + if (xcvseqCopy == gRX_c) { /* Abort current SEQ */ mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ); MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]); @@ -1141,76 +1100,66 @@ static void handle_interrupt(void) } /* TMR3 IRQ: ACK wait time-out */ - if( (mStatusAndControlRegs[IRQSTS3] & cIRQSTS3_TMR3IRQ) && - !(mStatusAndControlRegs[IRQSTS3] & cIRQSTS3_TMR3MSK) ) - { + if ((mStatusAndControlRegs[IRQSTS3] & cIRQSTS3_TMR3IRQ) && + !(mStatusAndControlRegs[IRQSTS3] & cIRQSTS3_TMR3MSK)) { /* Disable TMR3 IRQ */ mStatusAndControlRegs[IRQSTS3] |= cIRQSTS3_TMR3MSK; - if( xcvseqCopy == gTR_c ) - { + if (xcvseqCopy == gTR_c) { /* Set XCVR to Idle */ mPhySeqState = gIdle_c; - mStatusAndControlRegs[PHY_CTRL1] &= ~( cPHY_CTRL1_XCVSEQ ); + mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ); /* Mask interrupts */ mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_CCAMSK | cPHY_CTRL2_RXMSK | cPHY_CTRL2_TXMSK | cPHY_CTRL2_SEQMSK; /* Sync settings with XCVR */ MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 5); rf_ack_wait_timer_interrupt(); - MCR20Drv_IRQ_Enable(); return; } } /* Sequencer interrupt, the autosequence has completed */ - if( (mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_SEQIRQ) && - !(mStatusAndControlRegs[PHY_CTRL2] & cPHY_CTRL2_SEQMSK) ) - { + if ((mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_SEQIRQ) && + !(mStatusAndControlRegs[PHY_CTRL2] & cPHY_CTRL2_SEQMSK)) { /* Set XCVR to Idle */ mPhySeqState = gIdle_c; - mStatusAndControlRegs[PHY_CTRL1] &= ~( cPHY_CTRL1_XCVSEQ ); + mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ); /* Mask interrupts */ mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_CCAMSK | cPHY_CTRL2_RXMSK | cPHY_CTRL2_TXMSK | cPHY_CTRL2_SEQMSK; /* Sync settings with XCVR */ MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 5); /* PLL unlock, the autosequence has been aborted due to PLL unlock */ - if( mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_PLL_UNLOCK_IRQ ) - { - if(xcvseqCopy == gRX_c) - { + if (mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_PLL_UNLOCK_IRQ) { + if (xcvseqCopy == gRX_c) { rf_receive(); } - MCR20Drv_IRQ_Enable(); return; } - switch(xcvseqCopy) - { - case gTX_c: - case gTR_c: - rf_handle_tx_end(); - break; + switch (xcvseqCopy) { + case gTX_c: + case gTR_c: + rf_handle_tx_end(); + break; - case gRX_c: - rf_handle_rx_end(); - break; + case gRX_c: + rf_handle_rx_end(); + break; - case gCCA_c: - rf_handle_cca_ed_done(); - break; + case gCCA_c: + rf_handle_cca_ed_done(); + break; - default: - break; + default: + break; } - MCR20Drv_IRQ_Enable(); return; } /* Other IRQ. Clear XCVR interrupt flags */ MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3); - MCR20Drv_IRQ_Enable(); } /* @@ -1233,8 +1182,7 @@ static void rf_abort(void) mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_SEQMSK; MCR20Drv_DirectAccessSPIWrite(PHY_CTRL2, mStatusAndControlRegs[PHY_CTRL2]); - if( (mStatusAndControlRegs[PHY_CTRL1] & cPHY_CTRL1_XCVSEQ) != gIdle_c ) - { + if ((mStatusAndControlRegs[PHY_CTRL1] & cPHY_CTRL1_XCVSEQ) != gIdle_c) { /* Abort current SEQ */ mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ); MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]); @@ -1264,8 +1212,7 @@ static void rf_abort(void) */ static void rf_get_timestamp(uint32_t *pRetClk) { - if(NULL == pRetClk) - { + if (NULL == pRetClk) { return; } @@ -1288,8 +1235,7 @@ static void rf_set_timeout(uint32_t *pEndTime) { uint8_t phyReg; - if(NULL == pEndTime) - { + if (NULL == pEndTime) { return; } @@ -1324,12 +1270,11 @@ static uint8_t rf_if_read_rnd(void) /* Check if XCVR is idle */ phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL1); - if( (phyReg & cPHY_CTRL1_XCVSEQ) == gIdle_c ) - { + if ((phyReg & cPHY_CTRL1_XCVSEQ) == gIdle_c) { /* Program a new sequence */ MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, phyReg | gCCA_c); /* Wait for sequence to finish */ - while( !(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ) ); + while (!(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ)); /* Clear interrupt flag */ MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_SEQIRQ); } @@ -1348,7 +1293,7 @@ static uint8_t rf_if_read_rnd(void) */ static int8_t rf_convert_LQI_to_RSSI(uint8_t lqi) { - int32_t rssi = (50*lqi - 16820) / 163; + int32_t rssi = (50 * lqi - 16820) / 163; return (int8_t)rssi; } @@ -1364,20 +1309,15 @@ static uint8_t rf_convert_LQI(uint8_t hwLqi) uint32_t tmpLQI; /* LQI Saturation Level */ - if (hwLqi >= 230) - { + if (hwLqi >= 230) { return 0xFF; - } - else if (hwLqi <= 9) - { + } else if (hwLqi <= 9) { return 0; - } - else - { + } else { /* Rescale the LQI values from min to saturation to the 0x00 - 0xFF range */ /* The LQI value mst be multiplied by ~1.1087 */ /* tmpLQI = hwLqi * 7123 ~= hwLqi * 65536 * 0.1087 = hwLqi * 2^16 * 0.1087*/ - tmpLQI = ((uint32_t)hwLqi * (uint32_t)7123 ); + tmpLQI = ((uint32_t)hwLqi * (uint32_t)7123); /* tmpLQI = (tmpLQI / 2^16) + hwLqi */ tmpLQI = (uint32_t)(tmpLQI >> 16) + (uint32_t)hwLqi; @@ -1399,16 +1339,13 @@ static void rf_promiscuous(uint8_t state) rxFrameFltReg = MCR20Drv_IndirectAccessSPIRead(RX_FRAME_FILTER); phyCtrl4Reg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL4); - if( state ) - { + if (state) { /* FRM_VER[1:0] = b00. 00: Any FrameVersion accepted (0,1,2 & 3) */ /* All frame types accepted*/ phyCtrl4Reg |= cPHY_CTRL4_PROMISCUOUS; rxFrameFltReg &= ~(cRX_FRAME_FLT_FRM_VER); - rxFrameFltReg |= (cRX_FRAME_FLT_ACK_FT | cRX_FRAME_FLT_NS_FT); - } - else - { + rxFrameFltReg |= (cRX_FRAME_FLT_ACK_FT | cRX_FRAME_FLT_NS_FT); + } else { phyCtrl4Reg &= ~cPHY_CTRL4_PROMISCUOUS; /* FRM_VER[1:0] = b11. Accept FrameVersion 0 and 1 packets, reject all others */ /* Beacon, Data and MAC command frame types accepted */ @@ -1433,8 +1370,7 @@ static void rf_set_power_state(xcvrPwrMode_t newState) uint8_t pwrMode; uint8_t xtalState; - if( mPwrState == newState ) - { + if (mPwrState == newState) { return; } @@ -1442,35 +1378,33 @@ static void rf_set_power_state(xcvrPwrMode_t newState) pwrMode = MCR20Drv_DirectAccessSPIRead(PWR_MODES); xtalState = pwrMode & cPWR_MODES_XTALEN; - switch( newState ) - { - case gXcvrPwrIdle_c: - pwrMode &= ~(cPWR_MODES_AUTODOZE); - pwrMode |= (cPWR_MODES_XTALEN | cPWR_MODES_PMC_MODE); - break; - case gXcvrPwrAutodoze_c: - pwrMode |= (cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE); - break; - case gXcvrPwrDoze_c: - pwrMode &= ~(cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE); - pwrMode |= cPWR_MODES_XTALEN; - break; - case gXcvrPwrHibernate_c: - pwrMode &= ~(cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE); - break; - default: - return; + switch (newState) { + case gXcvrPwrIdle_c: + pwrMode &= ~(cPWR_MODES_AUTODOZE); + pwrMode |= (cPWR_MODES_XTALEN | cPWR_MODES_PMC_MODE); + break; + case gXcvrPwrAutodoze_c: + pwrMode |= (cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE); + break; + case gXcvrPwrDoze_c: + pwrMode &= ~(cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE); + pwrMode |= cPWR_MODES_XTALEN; + break; + case gXcvrPwrHibernate_c: + pwrMode &= ~(cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE); + break; + default: + return; } mPwrState = newState; MCR20Drv_DirectAccessSPIWrite(PWR_MODES, pwrMode); - if( !xtalState && (pwrMode & cPWR_MODES_XTALEN)) - { + if (!xtalState && (pwrMode & cPWR_MODES_XTALEN)) { /* wait for crystal oscillator to complet its warmup */ - while( ( MCR20Drv_DirectAccessSPIRead(PWR_MODES) & cPWR_MODES_XTAL_READY ) != cPWR_MODES_XTAL_READY); + while ((MCR20Drv_DirectAccessSPIRead(PWR_MODES) & cPWR_MODES_XTAL_READY) != cPWR_MODES_XTAL_READY); /* wait for radio wakeup from hibernate interrupt */ - while( ( MCR20Drv_DirectAccessSPIRead(IRQSTS2) & (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS) ) != (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS) ); + while ((MCR20Drv_DirectAccessSPIRead(IRQSTS2) & (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS)) != (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS)); MCR20Drv_DirectAccessSPIWrite(IRQSTS2, cIRQSTS2_WAKE_IRQ); } @@ -1487,8 +1421,7 @@ static uint8_t rf_get_channel_energy(void) MCR20Drv_IRQ_Disable(); /* RX can start only from Idle state */ - if( mPhySeqState != gIdle_c ) - { + if (mPhySeqState != gIdle_c) { MCR20Drv_IRQ_Enable(); return 0; } @@ -1498,8 +1431,7 @@ static uint8_t rf_get_channel_energy(void) /* Switch to ED mode */ ccaMode = (mStatusAndControlRegs[PHY_CTRL4] >> cPHY_CTRL4_CCATYPE_Shift_c) & cPHY_CTRL4_CCATYPE; - if( ccaMode != gCcaED_c ) - { + if (ccaMode != gCcaED_c) { mStatusAndControlRegs[PHY_CTRL4] &= ~(cPHY_CTRL4_CCATYPE << cPHY_CTRL4_CCATYPE_Shift_c); mStatusAndControlRegs[PHY_CTRL4] |= gCcaED_c << cPHY_CTRL4_CCATYPE_Shift_c; MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, mStatusAndControlRegs[PHY_CTRL4]); @@ -1510,7 +1442,7 @@ static uint8_t rf_get_channel_energy(void) MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_CCAIRQ | cIRQSTS1_SEQIRQ); MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]); /* Wait for sequence to finish */ - while ( !(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ)); + while (!(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ)); /* Set XCVR to Idle */ mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ); MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]); @@ -1530,18 +1462,13 @@ static uint8_t rf_get_channel_energy(void) */ static uint8_t rf_convert_energy_level(uint8_t energyLevel) { - if(energyLevel >= 90) - { + if (energyLevel >= 90) { /* ED value is below minimum. Return 0x00. */ energyLevel = 0x00; - } - else if(energyLevel <= 26) - { + } else if (energyLevel <= 26) { /* ED value is above maximum. Return 0xFF. */ energyLevel = 0xFF; - } - else - { + } else { /* Energy level (-90 dBm to -26 dBm ) --> varies form 0 to 64 */ energyLevel = (90 - energyLevel); /* Rescale the energy level values to the 0x00-0xff range (0 to 64 translates in 0 to 255) */ @@ -1561,43 +1488,53 @@ static uint8_t rf_scale_lqi(int8_t rssi) const int8_t rf_sensitivity = -98; /*rssi < RF sensitivity*/ - if(rssi < rf_sensitivity) - scaled_lqi=0; + if (rssi < rf_sensitivity) { + scaled_lqi = 0; + } /*-91 dBm < rssi < -81 dBm (AT86RF233 XPro)*/ /*-90 dBm < rssi < -80 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 10)) - scaled_lqi=31; + else if (rssi < (rf_sensitivity + 10)) { + scaled_lqi = 31; + } /*-81 dBm < rssi < -71 dBm (AT86RF233 XPro)*/ /*-80 dBm < rssi < -70 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 20)) - scaled_lqi=207; + else if (rssi < (rf_sensitivity + 20)) { + scaled_lqi = 207; + } /*-71 dBm < rssi < -61 dBm (AT86RF233 XPro)*/ /*-70 dBm < rssi < -60 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 30)) - scaled_lqi=255; + else if (rssi < (rf_sensitivity + 30)) { + scaled_lqi = 255; + } /*-61 dBm < rssi < -51 dBm (AT86RF233 XPro)*/ /*-60 dBm < rssi < -50 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 40)) - scaled_lqi=255; + else if (rssi < (rf_sensitivity + 40)) { + scaled_lqi = 255; + } /*-51 dBm < rssi < -41 dBm (AT86RF233 XPro)*/ /*-50 dBm < rssi < -40 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 50)) - scaled_lqi=255; + else if (rssi < (rf_sensitivity + 50)) { + scaled_lqi = 255; + } /*-41 dBm < rssi < -31 dBm (AT86RF233 XPro)*/ /*-40 dBm < rssi < -30 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 60)) - scaled_lqi=255; + else if (rssi < (rf_sensitivity + 60)) { + scaled_lqi = 255; + } /*-31 dBm < rssi < -21 dBm (AT86RF233 XPro)*/ /*-30 dBm < rssi < -20 dBm (AT86RF212B XPro)*/ - else if(rssi < (rf_sensitivity + 70)) - scaled_lqi=255; + else if (rssi < (rf_sensitivity + 70)) { + scaled_lqi = 255; + } /*rssi > RF saturation*/ - else if(rssi > (rf_sensitivity + 80)) - scaled_lqi=111; + else if (rssi > (rf_sensitivity + 80)) { + scaled_lqi = 111; + } /*-21 dBm < rssi < -11 dBm (AT86RF233 XPro)*/ /*-20 dBm < rssi < -10 dBm (AT86RF212B XPro)*/ - else - scaled_lqi=255; + else { + scaled_lqi = 255; + } return scaled_lqi; } @@ -1611,28 +1548,33 @@ extern "C" void xcvr_spi_init(uint32_t instance) (void)instance; } -extern "C" void RF_IRQ_Init(void) { +extern "C" void RF_IRQ_Init(void) +{ MBED_ASSERT(irq != NULL); irq->mode(PullUp); irq->fall(&PHY_InterruptHandler); } -extern "C" void RF_IRQ_Enable(void) { +extern "C" void RF_IRQ_Enable(void) +{ MBED_ASSERT(irq != NULL); irq->enable_irq(); } -extern "C" void RF_IRQ_Disable(void) { +extern "C" void RF_IRQ_Disable(void) +{ MBED_ASSERT(irq != NULL); irq->disable_irq(); } -extern "C" uint8_t RF_isIRQ_Pending(void) { +extern "C" uint8_t RF_isIRQ_Pending(void) +{ MBED_ASSERT(rf != NULL); return !irq_pin->read(); } -extern "C" void RF_RST_Set(int state) { +extern "C" void RF_RST_Set(int state) +{ MBED_ASSERT(rst != NULL); *rst = state; } @@ -1657,36 +1599,33 @@ extern "C" void xcvr_spi_configure_speed(uint32_t instance, uint32_t freq) } extern "C" void xcvr_spi_transfer(uint32_t instance, - uint8_t * sendBuffer, - uint8_t * receiveBuffer, - size_t transferByteCount) + uint8_t *sendBuffer, + uint8_t *receiveBuffer, + size_t transferByteCount) { MBED_ASSERT(spi != NULL); (void)instance; volatile uint8_t dummy; - if( !transferByteCount ) + if (!transferByteCount) { return; + } - if( !sendBuffer && !receiveBuffer ) + if (!sendBuffer && !receiveBuffer) { return; + } - while( transferByteCount-- ) - { - if( sendBuffer ) - { + while (transferByteCount--) { + if (sendBuffer) { dummy = *sendBuffer; sendBuffer++; - } - else - { + } else { dummy = 0xFF; } dummy = spi->write(dummy); - if( receiveBuffer ) - { + if (receiveBuffer) { *receiveBuffer = dummy; receiveBuffer++; } @@ -1707,7 +1646,7 @@ static void rf_if_unlock(void) } NanostackRfPhyMcr20a::NanostackRfPhyMcr20a(PinName spi_mosi, PinName spi_miso, - PinName spi_sclk, PinName spi_cs, PinName spi_rst, PinName spi_irq) + PinName spi_sclk, PinName spi_cs, PinName spi_rst, PinName spi_irq) : _spi(spi_mosi, spi_miso, spi_sclk), _rf_cs(spi_cs), _rf_rst(spi_rst, 1), _rf_irq(spi_irq), _rf_irq_pin(spi_irq), _irq_thread(osPriorityRealtime, 1024) @@ -1774,7 +1713,7 @@ void NanostackRfPhyMcr20a::get_mac_address(uint8_t *mac) { rf_if_lock(); - memcpy((void*)mac, (void*)MAC_address, sizeof(MAC_address)); + memcpy((void *)mac, (void *)MAC_address, sizeof(MAC_address)); rf_if_unlock(); } @@ -1788,7 +1727,7 @@ void NanostackRfPhyMcr20a::set_mac_address(uint8_t *mac) rf_if_unlock(); return; } - memcpy((void*)MAC_address, (void*)mac, sizeof(MAC_address)); + memcpy((void *)MAC_address, (void *)mac, sizeof(MAC_address)); rf_if_unlock(); } diff --git a/components/802.15.4_RF/mcr20a-rf-driver/source/XcvrSpi.h b/components/802.15.4_RF/mcr20a-rf-driver/source/XcvrSpi.h index ca56cae6ca..9f1a1f71be 100644 --- a/components/802.15.4_RF/mcr20a-rf-driver/source/XcvrSpi.h +++ b/components/802.15.4_RF/mcr20a-rf-driver/source/XcvrSpi.h @@ -42,7 +42,7 @@ * files, so use this section only if there is no other better solution. * *---------------------------------------------------------------------------* *****************************************************************************/ - + /***************************************************************************** * PUBLIC MACROS * @@ -78,10 +78,10 @@ void gXcvrDeassertCS_d(void); void xcvr_spi_init(uint32_t instance); void xcvr_spi_configure_speed(uint32_t instance, uint32_t freq); void xcvr_spi_transfer(uint32_t instance, - uint8_t * sendBuffer, - uint8_t * receiveBuffer, - uint32_t transferByteCount); - + uint8_t *sendBuffer, + uint8_t *receiveBuffer, + uint32_t transferByteCount); + #if defined(__cplusplus) } #endif /* __cplusplus */ diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/README.md b/components/802.15.4_RF/stm-s2lp-rf-driver/README.md new file mode 100644 index 0000000000..a4adb28146 --- /dev/null +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/README.md @@ -0,0 +1,6 @@ +# Example RF driver for STM 802.15.4 transceivers # + +Support for: + * S2-LP + +This driver is used with 6LoWPAN and Wi-SUN stacks. \ No newline at end of file diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/mbed_lib.json b/components/802.15.4_RF/stm-s2lp-rf-driver/mbed_lib.json new file mode 100644 index 0000000000..a820f4f18f --- /dev/null +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/mbed_lib.json @@ -0,0 +1,9 @@ +{ + "name": "s2lp", + "config": { + "provide-default": { + "help": "Provide default NanostackRfpy. [true/false]", + "value": false + } + } +} diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp b/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp new file mode 100644 index 0000000000..3e56873814 --- /dev/null +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp @@ -0,0 +1,1376 @@ +/* + * Copyright (c) 2018 ARM Limited. All rights reserved. + * 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. + */ +#include +#if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI +#include "platform/arm_hal_interrupt.h" +#include "nanostack/platform/arm_hal_phy.h" +#include "ns_types.h" +#include "NanostackRfPhys2lp.h" +#include "s2lpReg.h" +#include "rf_configuration.h" +#include "randLIB.h" +#include "mbed_trace.h" +#include "mbed_toolchain.h" +#include "common_functions.h" +#include + +#define TRACE_GROUP "s2lp" + +#define INTERRUPT_GPIO S2LP_GPIO3 + +#if INTERRUPT_GPIO == S2LP_GPIO0 +#define INT_IN_GPIO rf->RF_S2LP_GPIO0 +#elif INTERRUPT_GPIO == S2LP_GPIO1 +#define INT_IN_GPIO rf->RF_S2LP_GPIO1 +#elif INTERRUPT_GPIO == S2LP_GPIO2 +#define INT_IN_GPIO rf->RF_S2LP_GPIO2 +#else +#define INT_IN_GPIO rf->RF_S2LP_GPIO3 +#endif + +#ifdef TEST_GPIOS_ENABLED +#define TEST_TX_STARTED rf->TEST1 = 1; +#define TEST_TX_DONE rf->TEST1 = 0; +#define TEST_RX_STARTED rf->TEST2 = 1; +#define TEST_RX_DONE rf->TEST2 = 0; +#define TEST_ACK_TX_STARTED rf->TEST3 = 1; +#define TEST_ACK_TX_DONE rf->TEST3 = 0; +#define TEST1_ON rf->TEST4 = 1; +#define TEST1_OFF rf->TEST4 = 0; +#define TEST2_ON rf->TEST5 = 1; +#define TEST2_OFF rf->TEST5 = 0; +extern void (*fhss_uc_switch)(void); +extern void (*fhss_bc_switch)(void); +#else //TEST_GPIOS_ENABLED +#define TEST_TX_STARTED +#define TEST_TX_DONE +#define TEST_RX_STARTED +#define TEST_RX_DONE +#define TEST_ACK_TX_STARTED +#define TEST_ACK_TX_DONE +#define TEST1_ON +#define TEST1_OFF +#define TEST2_ON +#define TEST2_OFF +#endif //TEST_GPIOS_ENABLED + +#define MAC_FRAME_TYPE_MASK 0x07 +#define MAC_FRAME_BEACON (0) +#define MAC_TYPE_DATA (1) +#define MAC_TYPE_ACK (2) +#define MAC_TYPE_COMMAND (3) +#define MAC_DATA_PENDING 0x10 +#define MAC_FRAME_VERSION_2 (2) +#define FC_DST_MODE 0x0C +#define FC_SRC_MODE 0xC0 +#define FC_DST_ADDR_NONE 0x00 +#define FC_DST_16_BITS 0x08 +#define FC_DST_64_BITS 0x0C +#define FC_SRC_64_BITS 0xC0 +#define FC_SEQUENCE_COMPRESSION 0x01 +#define FC_AR 0x20 +#define FC_PAN_ID_COMPRESSION 0x40 +#define VERSION_FIELD_MASK 0x30 +#define SHIFT_SEQ_COMP_FIELD (0) +#define SHIFT_VERSION_FIELD (4) +#define SHIFT_PANID_COMP_FIELD (6) +#define OFFSET_DST_PAN_ID (3) +#define OFFSET_DST_ADDR (5) + +#define CS_SELECT() {rf->CS = 0;} +#define CS_RELEASE() {rf->CS = 1;} + +class UnlockedSPI : public SPI { +public: + UnlockedSPI(PinName sdi, PinName sdo, PinName sclk) : + SPI(sdi, sdo, sclk) { } + virtual void lock() { } + virtual void unlock() { } +}; + +class RFPins { +public: + RFPins(PinName spi_sdi, PinName spi_sdo, + PinName spi_sclk, PinName spi_cs, PinName spi_sdn, +#ifdef TEST_GPIOS_ENABLED + PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5, +#endif //TEST_GPIOS_ENABLED + PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, + PinName spi_gpio3); + UnlockedSPI spi; + DigitalOut CS; + DigitalOut SDN; +#ifdef TEST_GPIOS_ENABLED + DigitalOut TEST1; + DigitalOut TEST2; + DigitalOut TEST3; + DigitalOut TEST4; + DigitalOut TEST5; +#endif //TEST_GPIOS_ENABLED + InterruptIn RF_S2LP_GPIO0; + InterruptIn RF_S2LP_GPIO1; + InterruptIn RF_S2LP_GPIO2; + InterruptIn RF_S2LP_GPIO3; + Timeout cca_timer; + Timeout backup_timer; + Timer tx_timer; +#ifdef MBED_CONF_RTOS_PRESENT + Thread irq_thread; + Mutex mutex; + void rf_irq_task(); +#endif //MBED_CONF_RTOS_PRESENT +}; + +RFPins::RFPins(PinName spi_sdi, PinName spi_sdo, + PinName spi_sclk, PinName spi_cs, PinName spi_sdn, +#ifdef TEST_GPIOS_ENABLED + PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5, +#endif //TEST_GPIOS_ENABLED + PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, + PinName spi_gpio3) + : spi(spi_sdi, spi_sdo, spi_sclk), + CS(spi_cs), + SDN(spi_sdn), +#ifdef TEST_GPIOS_ENABLED + TEST1(spi_test1), + TEST2(spi_test2), + TEST3(spi_test3), + TEST4(spi_test4), + TEST5(spi_test5), +#endif //TEST_GPIOS_ENABLED + RF_S2LP_GPIO0(spi_gpio0), + RF_S2LP_GPIO1(spi_gpio1), + RF_S2LP_GPIO2(spi_gpio2), + RF_S2LP_GPIO3(spi_gpio3) +#ifdef MBED_CONF_RTOS_PRESENT + , irq_thread(osPriorityRealtime, 1024) +#endif //MBED_CONF_RTOS_PRESENT +{ +#ifdef MBED_CONF_RTOS_PRESENT + irq_thread.start(mbed::callback(this, &RFPins::rf_irq_task)); +#endif //MBED_CONF_RTOS_PRESENT +} + +static uint8_t rf_read_register_with_status(uint8_t addr, uint16_t *status_out); +static s2lp_states_e rf_read_state(void); +static void rf_write_register(uint8_t addr, uint8_t data); +static void rf_print_registers(void); +static void rf_interrupt_handler(void); +static void rf_receive(uint8_t rx_channel); +static void rf_cca_timer_stop(void); +static void rf_backup_timer_start(uint32_t slots); +static void rf_backup_timer_stop(void); +static void rf_rx_ready_handler(void); +static uint32_t read_irq_status(void); +static bool rf_rx_filter(uint8_t *mac_header, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr, uint8_t *pan_id); + +static RFPins *rf; +static phy_device_driver_s device_driver; +static int8_t rf_radio_driver_id = -1; +static uint8_t *tx_data_ptr; +static uint16_t tx_data_length; +static uint16_t rx_data_length; +static uint32_t enabled_interrupts; +static uint8_t mac_tx_handle; +static uint8_t rf_rx_channel; +static uint8_t rf_new_channel; +static uint8_t rx_buffer[RF_MTU]; +static rf_states_e rf_state = RF_IDLE; +// This will be used when given channel spacing cannot be supported by transceiver +static uint8_t rf_channel_multiplier = 1; +static uint16_t tx_sequence = 0xffff; +static uint32_t tx_time = 0; +static uint32_t rx_time = 0; +static uint32_t tx_finnish_time = 0; +static uint32_t symbols_in_seconds; +static bool cca_enabled = true; +static uint8_t s2lp_PAN_ID[2] = {0xff, 0xff}; +static uint8_t s2lp_short_address[2]; +static uint8_t s2lp_MAC[8]; + +/* Channel configurations for sub-GHz */ +static const phy_rf_channel_configuration_s phy_subghz = {868300000U, 500000U, 250000U, 11U, M_UNDEFINED}; + +static const phy_device_channel_page_s phy_channel_pages[] = { + { CHANNEL_PAGE_2, &phy_subghz}, + { CHANNEL_PAGE_0, NULL} +}; + +#ifdef MBED_CONF_RTOS_PRESENT +#include "mbed.h" +#include "rtos.h" + +static void rf_irq_task_process_irq(); + +#define SIG_RADIO 1 +#define SIG_TIMER_CCA 2 +#define SIG_TIMER_BACKUP 4 + +#endif //MBED_CONF_RTOS_PRESENT + +#define ACK_FRAME_LENGTH 3 +// Give some additional time for processing, PHY headers, CRC etc. +#define PACKET_SENDING_EXTRA_TIME 10000 +#define MAX_PACKET_SENDING_TIME (uint32_t)(8000000/phy_subghz.datarate)*RF_MTU + PACKET_SENDING_EXTRA_TIME +#define ACK_SENDING_TIME (uint32_t)(8000000/phy_subghz.datarate)*ACK_FRAME_LENGTH + PACKET_SENDING_EXTRA_TIME + +#ifdef TEST_GPIOS_ENABLED +void test1_toggle(void) +{ + if (rf->TEST4) { + rf->TEST4 = 0; + } else { + rf->TEST4 = 1; + } +} +void test2_toggle(void) +{ + if (rf->TEST5) { + rf->TEST5 = 0; + } else { + rf->TEST5 = 1; + } +} +#endif //TEST_GPIOS_ENABLED + +static void rf_calculate_symbols_in_seconds(uint32_t baudrate, phy_modulation_e modulation) +{ + (void) modulation; + uint8_t bits_in_symbols = 1; + symbols_in_seconds = baudrate / bits_in_symbols; +} + +static uint32_t rf_get_timestamp(void) +{ + return (uint32_t)rf->tx_timer.read_us(); +} + +static void rf_lock(void) +{ + platform_enter_critical(); +} + +static void rf_unlock(void) +{ + platform_exit_critical(); +} + +#ifdef MBED_CONF_RTOS_PRESENT +static void rf_cca_timer_signal(void) +{ + rf->irq_thread.signal_set(SIG_TIMER_CCA); +} + +static void rf_backup_timer_signal(void) +{ + rf->irq_thread.signal_set(SIG_TIMER_BACKUP); +} +#endif //MBED_CONF_RTOS_PRESENT + +/* + * \brief Function writes/read data in SPI interface + */ +static void rf_spi_exchange(const void *tx, size_t tx_len, void *rx, size_t rx_len) +{ + rf->spi.write(static_cast(tx), tx_len, static_cast(rx), rx_len); +} + +static uint8_t rf_read_register_with_status(uint8_t addr, uint16_t *status_out) +{ + const uint8_t tx[2] = {SPI_RD_REG, addr}; + uint8_t rx[3]; + rf_lock(); + CS_SELECT(); + rf_spi_exchange(tx, sizeof(tx), rx, sizeof(rx)); + CS_RELEASE(); + if (status_out) { + *status_out = (rx[0] << 8) | rx[1]; + } + rf_unlock(); + return rx[2]; +} + +static void rf_write_register(uint8_t addr, uint8_t data) +{ + const uint8_t tx[3] = {SPI_WR_REG, addr, data}; + rf_lock(); + CS_SELECT(); + rf_spi_exchange(tx, sizeof(tx), NULL, 0); + CS_RELEASE(); + rf_unlock(); +} + +static void rf_write_register_field(uint8_t addr, uint8_t field, uint8_t value) +{ + uint8_t reg_tmp = rf_read_register_with_status(addr, NULL); + reg_tmp &= ~field; + reg_tmp |= value; + rf_write_register(addr, reg_tmp); +} + +static s2lp_states_e rf_read_state(void) +{ + return (s2lp_states_e)(rf_read_register_with_status(MC_STATE0, NULL) >> 1); +} + +static void rf_poll_state_change(s2lp_states_e state) +{ + uint16_t break_counter = 0; + while (state != rf_read_state()) { + if (break_counter++ == 0xffff) { + tr_err("Failed to change state from %x to: %x", rf_read_state(), state); + break; + } + } +} + +static void rf_enable_gpio_signal(uint8_t gpio_pin, uint8_t interrupt_signal, uint8_t gpio_mode) +{ + rf_write_register(GPIO0_CONF + gpio_pin, (interrupt_signal << 3) | gpio_mode); +} + +static void rf_enable_interrupt(uint8_t event) +{ + rf_write_register_field(IRQ_MASK0 - (event / 8), 1 << (event % 8), 1 << (event % 8)); + enabled_interrupts |= (1 << event); +} + +static void rf_disable_interrupt(uint8_t event) +{ + rf_write_register_field(IRQ_MASK0 - (event / 8), 1 << (event % 8), 0 << (event % 8)); + enabled_interrupts &= ~(1 << event); +} + +static void rf_disable_all_interrupts(void) +{ + rf_write_register(IRQ_MASK0, 0); + rf_write_register(IRQ_MASK1, 0); + rf_write_register(IRQ_MASK2, 0); + rf_write_register(IRQ_MASK3, 0); + enabled_interrupts = 0; + read_irq_status(); +} + +static void rf_enable_gpio_interrupt(void) +{ + rf_enable_gpio_signal(INTERRUPT_GPIO, NIRQ, DIG_OUT_HIGH); + INT_IN_GPIO.mode(PullUp); + INT_IN_GPIO.fall(&rf_interrupt_handler); + INT_IN_GPIO.enable_irq(); +} + +static void rf_send_command(s2lp_commands_e command) +{ + const uint8_t tx[2] = {SPI_CMD, command}; + rf_lock(); + CS_SELECT(); + rf_spi_exchange(tx, sizeof(tx), NULL, 0); + CS_RELEASE(); + rf_unlock(); +} + +static void rf_state_change(s2lp_states_e state, bool lock_mode_tx) +{ + s2lp_commands_e command; + + if (S2LP_STATE_READY == state) { + s2lp_states_e cur_state = rf_read_state(); + if (S2LP_STATE_TX == cur_state || S2LP_STATE_RX == cur_state) { + command = S2LP_CMD_SABORT; + } else { + command = S2LP_CMD_READY; + } + } else if (S2LP_STATE_LOCK == state && lock_mode_tx) { + command = S2LP_CMD_LOCKTX; + } else if (S2LP_STATE_LOCK == state && !lock_mode_tx) { + command = S2LP_CMD_LOCKRX; + } else if (S2LP_STATE_RX == state) { + command = S2LP_CMD_RX; + } else if (S2LP_STATE_TX == state) { + command = S2LP_CMD_TX; + } else { + tr_err("Invalid state %x", state); + return; + } + rf_send_command(command); + rf_poll_state_change(state); +} + +static uint8_t rf_write_tx_fifo(uint8_t *ptr, uint16_t length, uint8_t max_write) +{ + const uint8_t spi_header[SPI_HEADER_LENGTH] = {SPI_WR_REG, TX_FIFO}; + uint8_t written_length = length; + if (length > max_write) { + written_length = max_write; + } + CS_SELECT(); + rf_spi_exchange(spi_header, SPI_HEADER_LENGTH, NULL, 0); + rf_spi_exchange(ptr, written_length, NULL, 0); + CS_RELEASE(); + return written_length; +} + +static uint8_t rf_read_rx_fifo(uint8_t *ptr, uint16_t length) +{ + const uint8_t spi_header[SPI_HEADER_LENGTH] = {SPI_RD_REG, RX_FIFO}; + CS_SELECT(); + rf_spi_exchange(spi_header, SPI_HEADER_LENGTH, NULL, 0); + rf_spi_exchange(NULL, 0, ptr, length); + CS_RELEASE(); + return length; +} + +static void rf_write_packet_length(uint16_t packet_length) +{ + rf_write_register(PCKTLEN1, packet_length / 256); + rf_write_register(PCKTLEN0, packet_length % 256); +} + +static uint32_t read_irq_status(void) +{ + const uint8_t tx[2] = {SPI_RD_REG, IRQ_STATUS3}; + uint8_t rx[6]; + CS_SELECT(); + rf_spi_exchange(tx, sizeof(tx), rx, sizeof(rx)); + CS_RELEASE(); + return (((uint32_t)rx[2] << 24) | ((uint32_t)rx[3] << 16) | ((uint32_t)rx[4] << 8) | rx[5]); +} + +static void rf_init_registers(void) +{ + rf_write_register_field(PCKTCTRL3, PCKT_FORMAT_FIELD, PCKT_FORMAT_802_15_4); + // Set deviation + uint8_t fdev_m, fdev_e; + rf_conf_calculate_deviation_registers(DEVIATION, &fdev_m, &fdev_e); + rf_write_register(MOD0, fdev_m); + rf_write_register_field(MOD1, FDEV_E_FIELD, fdev_e); + rf_write_register_field(MOD2, MOD_TYPE_FIELD, MOD_2FSK); + // Set datarate + uint16_t datarate_m; + uint8_t datarate_e; + rf_conf_calculate_datarate_registers(phy_subghz.datarate, &datarate_m, &datarate_e); + rf_write_register_field(MOD2, DATARATE_E_FIELD, datarate_e); + rf_write_register(MOD3, (uint8_t)datarate_m); + rf_write_register(MOD4, datarate_m >> 8); + // Set RX filter bandwidth + uint8_t chflt_m, chflt_e; + rf_conf_calculate_rx_filter_bandwidth_registers(RX_FILTER_BANDWIDTH, &chflt_m, &chflt_e); + rf_write_register_field(CHFLT, CHFLT_M_FIELD, chflt_m << 4); + rf_write_register_field(CHFLT, CHFLT_E_FIELD, chflt_e); + rf_write_register(PCKT_FLT_OPTIONS, 0); + // Set base frequency (Channel 0 center frequency) + uint8_t synt3, synt2, synt1, synt0; + rf_conf_calculate_base_frequency_registers(phy_subghz.channel_0_center_frequency, &synt3, &synt2, &synt1, &synt0); + rf_write_register_field(SYNT3, SYNT_FIELD, synt3); + rf_write_register(SYNT2, synt2); + rf_write_register(SYNT1, synt1); + rf_write_register(SYNT0, synt0); + // Set channel spacing + uint8_t ch_space; + uint8_t ch_space_divider = 1; + while (rf_conf_calculate_channel_spacing_registers(phy_subghz.channel_spacing / ch_space_divider, &ch_space)) { + ch_space_divider++; + rf_channel_multiplier++; + } + rf_write_register(CHSPACE, ch_space); + rf_write_register_field(PCKTCTRL1, PCKT_CRCMODE_FIELD, PCKT_CRCMODE_0X1021); + rf_write_register_field(PCKTCTRL1, PCKT_TXSOURCE_FIELD, PCKT_TXSOURCE_NORMAL); + rf_write_register_field(PCKTCTRL1, PCKT_WHITENING_FIELD, PCKT_WHITENING_ENABLED); + rf_write_register_field(PCKTCTRL2, PCKT_FIXVARLEN_FIELD, PCKT_VARIABLE_LEN); + rf_write_register_field(PCKTCTRL3, PCKT_RXMODE_FIELD, PCKT_RXMODE_NORMAL); + rf_write_register(PCKTCTRL5, PCKT_PREAMBLE_LEN); + rf_write_register_field(PCKTCTRL6, PCKT_SYNCLEN_FIELD, PCKT_SYNCLEN); + rf_write_register_field(QI, PQI_TH_FIELD, PQI_TH); + rf_write_register_field(QI, SQI_EN_FIELD, SQI_EN); + rf_write_register(SYNC0, SFD0); + rf_write_register(SYNC1, SFD1); + // Set RSSI threshold + uint8_t rssi_th; + rf_conf_calculate_rssi_threshold_registers(RSSI_THRESHOLD, &rssi_th); + rf_write_register(RSSI_TH, rssi_th); +} + +static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr) +{ + int8_t ret_val = 0; + switch (address_type) { + /*Set 48-bit address*/ + case PHY_MAC_48BIT: + break; + /*Set 64-bit address*/ + case PHY_MAC_64BIT: + memcpy(s2lp_MAC, address_ptr, 8); + break; + /*Set 16-bit address*/ + case PHY_MAC_16BIT: + memcpy(s2lp_short_address, address_ptr, 2); + break; + /*Set PAN Id*/ + case PHY_MAC_PANID: + memcpy(s2lp_PAN_ID, address_ptr, 2); + break; + } + return ret_val; +} + +static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr) +{ + int8_t retval = 0; + phy_csma_params_t *csma_params; + uint32_t *timer_value; + switch (extension_type) { + case PHY_EXTENSION_SET_CHANNEL: + if (rf_state == RF_IDLE || rf_state == RF_CSMA_STARTED) { + rf_receive(*data_ptr); + } else { + // Store the new channel if couldn't change it yet. + rf_new_channel = *data_ptr; + retval = -1; + } + break; + case PHY_EXTENSION_CTRL_PENDING_BIT: + break; + /*Return frame pending status*/ + case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS: + break; + case PHY_EXTENSION_ACCEPT_ANY_BEACON: + break; + case PHY_EXTENSION_SET_TX_TIME: + tx_time = common_read_32_bit(data_ptr); + break; + case PHY_EXTENSION_READ_RX_TIME: + common_write_32_bit(rx_time, data_ptr); + break; + case PHY_EXTENSION_DYNAMIC_RF_SUPPORTED: + *data_ptr = true; + break; + case PHY_EXTENSION_GET_TIMESTAMP: + timer_value = (uint32_t *)data_ptr; + *timer_value = rf_get_timestamp(); + break; + case PHY_EXTENSION_SET_CSMA_PARAMETERS: + csma_params = (phy_csma_params_t *)data_ptr; + if (csma_params->backoff_time == 0) { + rf_cca_timer_stop(); + if (rf_read_register_with_status(TX_FIFO_STATUS, NULL)) { + rf_send_command(S2LP_CMD_SABORT); + rf_poll_state_change(S2LP_STATE_READY); + rf_send_command(S2LP_CMD_FLUSHTXFIFO); + rf_poll_state_change(S2LP_STATE_READY); + } + if (rf_state == RF_TX_STARTED) { + rf_state = RF_IDLE; + rf_receive(rf_rx_channel); + } + tx_time = 0; + } else { + tx_time = csma_params->backoff_time; + cca_enabled = csma_params->cca_enabled; + } + break; + case PHY_EXTENSION_READ_TX_FINNISH_TIME: + timer_value = (uint32_t *)data_ptr; + *timer_value = tx_finnish_time; + break; + + case PHY_EXTENSION_GET_SYMBOLS_PER_SECOND: + timer_value = (uint32_t *)data_ptr; + *timer_value = symbols_in_seconds; + break; + + default: + break; + } + + return retval; +} + + +static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel) +{ + int8_t ret_val = 0; + switch (new_state) { + /*Reset PHY driver and set to idle*/ + case PHY_INTERFACE_RESET: + break; + /*Disable PHY Interface driver*/ + case PHY_INTERFACE_DOWN: + break; + /*Enable PHY Interface driver*/ + case PHY_INTERFACE_UP: + rf_receive(rf_channel); + break; + /*Enable wireless interface ED scan mode*/ + case PHY_INTERFACE_RX_ENERGY_STATE: + break; + /*Enable Sniffer state*/ + case PHY_INTERFACE_SNIFFER_STATE: + break; + } + return ret_val; +} + +static void rf_tx_sent_handler(void) +{ + rf_backup_timer_stop(); + rf_disable_interrupt(TX_DATA_SENT); + if (rf_state != RF_TX_ACK) { + tx_finnish_time = rf_get_timestamp(); + TEST_TX_DONE + rf_state = RF_IDLE; + rf_receive(rf_rx_channel); + if (device_driver.phy_tx_done_cb) { + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 0, 0); + } + } else { + TEST_ACK_TX_DONE + rf_receive(rf_rx_channel); + } +} + +static void rf_tx_threshold_handler(void) +{ + rf_disable_interrupt(TX_FIFO_ALMOST_EMPTY); + // TODO check the FIFO threshold. By default, threshold is half of the FIFO size + uint8_t written_length = rf_write_tx_fifo(tx_data_ptr, tx_data_length, FIFO_SIZE / 2); + if (written_length < tx_data_length) { + tx_data_ptr += written_length; + tx_data_length -= written_length; + rf_enable_interrupt(TX_FIFO_ALMOST_EMPTY); + } +} + +static void rf_start_tx(void) +{ + rf_disable_all_interrupts(); + // More TX data to be written in FIFO when TX threshold interrupt occurs + if (tx_data_ptr) { + rf_enable_interrupt(TX_FIFO_ALMOST_EMPTY); + } + rf_enable_interrupt(TX_DATA_SENT); + rf_enable_interrupt(TX_FIFO_UNF_OVF); + rf_state_change(S2LP_STATE_READY, false); + rf_state_change(S2LP_STATE_LOCK, true); + rf_state_change(S2LP_STATE_TX, false); + rf_backup_timer_start(MAX_PACKET_SENDING_TIME); +} + +static void rf_cca_timer_interrupt(void) +{ + if (device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_PREPARE, 0, 0) != 0) { + if (rf_read_register_with_status(TX_FIFO_STATUS, NULL)) { + rf_send_command(S2LP_CMD_FLUSHTXFIFO); + } + rf_state = RF_IDLE; + return; + } + if ((cca_enabled == true) && (rf_read_register_with_status(LINK_QUALIF1, NULL) & CARRIER_SENSE || (rf_state != RF_CSMA_STARTED && rf_state != RF_IDLE))) { + if (rf_state == RF_CSMA_STARTED) { + rf_state = RF_IDLE; + } + if (rf_read_register_with_status(TX_FIFO_STATUS, NULL)) { + rf_send_command(S2LP_CMD_FLUSHTXFIFO); + } + tx_finnish_time = rf_get_timestamp(); + if (device_driver.phy_tx_done_cb) { + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0); + } + } else { + rf_start_tx(); + rf_state = RF_TX_STARTED; + TEST_TX_STARTED + } +} + +static void rf_cca_timer_stop(void) +{ + rf->cca_timer.detach(); +} + +static void rf_cca_timer_start(uint32_t slots) +{ +#ifdef MBED_CONF_RTOS_PRESENT + rf->cca_timer.attach_us(rf_cca_timer_signal, slots); +#else //MBED_CONF_RTOS_PRESENT + rf->cca_timer.attach_us(rf_cca_timer_interrupt, slots); +#endif //MBED_CONF_RTOS_PRESENT +} + +static void rf_backup_timer_interrupt(void) +{ + tx_finnish_time = rf_get_timestamp(); + if (rf_state == RF_TX_STARTED) { + if (device_driver.phy_tx_done_cb) { + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 0, 0); + } + } + if (rf_read_register_with_status(TX_FIFO_STATUS, NULL)) { + rf_send_command(S2LP_CMD_FLUSHTXFIFO); + } + TEST_TX_DONE + TEST_RX_DONE + rf_state = RF_IDLE; + rf_receive(rf_rx_channel); +} + +static void rf_backup_timer_stop(void) +{ + rf->backup_timer.detach(); +} + +static void rf_backup_timer_start(uint32_t slots) +{ +#ifdef MBED_CONF_RTOS_PRESENT + rf->backup_timer.attach_us(rf_backup_timer_signal, slots); +#else //MBED_CONF_RTOS_PRESENT + rf->backup_timer.attach_us(rf_backup_timer_interrupt, slots); +#endif //MBED_CONF_RTOS_PRESENT +} + +static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol) +{ + rf_lock(); + if (rf_state != RF_IDLE) { + rf_unlock(); + return -1; + } + rf_state = RF_CSMA_STARTED; + uint8_t written_length = rf_write_tx_fifo(data_ptr, data_length, FIFO_SIZE); + if (written_length < data_length) { + tx_data_ptr = data_ptr + written_length; + tx_data_length = data_length - written_length; + } else { + tx_data_ptr = NULL; + } + // If Ack is requested, store the MAC sequence. This will be compared with received Ack. + uint8_t version = ((*(data_ptr + 1) & VERSION_FIELD_MASK) >> SHIFT_VERSION_FIELD); + if ((version != MAC_FRAME_VERSION_2) && (*data_ptr & FC_AR)) { + tx_sequence = *(data_ptr + 2); + } + // TODO: Define this better + rf_write_packet_length(data_length + 4); + mac_tx_handle = tx_handle; + if (tx_time) { + uint32_t backoff_time = tx_time - rf_get_timestamp(); + // Max. time to TX can be 65ms, otherwise time has passed already -> send immediately + if (backoff_time <= 65000) { + rf_cca_timer_start(backoff_time); + rf_unlock(); + return 0; + } + } + rf_cca_timer_interrupt(); + rf_unlock(); + return 0; +} + +static void rf_send_ack(uint8_t seq) +{ + // If the reception started during CCA process, the TX FIFO may already contain a data packet + if (rf_read_register_with_status(TX_FIFO_STATUS, NULL)) { + rf_send_command(S2LP_CMD_SABORT); + rf_poll_state_change(S2LP_STATE_READY); + rf_send_command(S2LP_CMD_FLUSHTXFIFO); + rf_poll_state_change(S2LP_STATE_READY); + } + rf_state = RF_TX_ACK; + uint8_t ack_frame[3] = {MAC_TYPE_ACK, 0, seq}; + rf_write_tx_fifo(ack_frame, sizeof(ack_frame), FIFO_SIZE); + rf_write_packet_length(sizeof(ack_frame) + 4); + tx_data_ptr = NULL; + rf_start_tx(); + TEST_ACK_TX_STARTED + rf_backup_timer_start(ACK_SENDING_TIME); +} + +static void rf_handle_ack(uint8_t seq_number, uint8_t pending) +{ + phy_link_tx_status_e phy_status; + if (tx_sequence == (uint16_t)seq_number) { + tx_finnish_time = rf_get_timestamp(); + if (pending) { + phy_status = PHY_LINK_TX_DONE_PENDING; + } else { + phy_status = PHY_LINK_TX_DONE; + } + // No CCA attempts done, just waited Ack + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, phy_status, 0, 0); + // Clear TX sequence when Ack is received to avoid duplicate Acks + tx_sequence = 0xffff; + } +} + +static void rf_rx_ready_handler(void) +{ + rf_backup_timer_stop(); + TEST_RX_DONE + rx_data_length += rf_read_rx_fifo(&rx_buffer[rx_data_length], rf_read_register_with_status(RX_FIFO_STATUS, NULL)); + uint8_t version = ((rx_buffer[1] & VERSION_FIELD_MASK) >> SHIFT_VERSION_FIELD); + if (((rx_buffer[0] & MAC_FRAME_TYPE_MASK) == MAC_TYPE_ACK) && (version < MAC_FRAME_VERSION_2)) { + rf_handle_ack(rx_buffer[2], rx_buffer[0] & MAC_DATA_PENDING); + } else if (rf_rx_filter(rx_buffer, s2lp_MAC, s2lp_short_address, s2lp_PAN_ID)) { + rf_state = RF_IDLE; + int8_t rssi = (rf_read_register_with_status(RSSI_LEVEL, NULL) - RSSI_OFFSET); + if (device_driver.phy_rx_cb) { + device_driver.phy_rx_cb(rx_buffer, rx_data_length, 0xf0, rssi, rf_radio_driver_id); + } + // Check Ack request + if ((version != MAC_FRAME_VERSION_2) && (rx_buffer[0] & FC_AR)) { + rf_send_ack(rx_buffer[2]); + } + } + if ((rf_state != RF_TX_ACK) && (rf_state != RF_CSMA_STARTED)) { + rf_receive(rf_rx_channel); + } +} + +static void rf_rx_threshold_handler(void) +{ + rx_data_length += rf_read_rx_fifo(&rx_buffer[rx_data_length], rf_read_register_with_status(RX_FIFO_STATUS, NULL)); +} + +static void rf_sync_detected_handler(void) +{ + rx_time = rf_get_timestamp(); + rf_state = RF_RX_STARTED; + TEST_RX_STARTED + rf_disable_interrupt(SYNC_WORD); + rf_backup_timer_start(MAX_PACKET_SENDING_TIME); +} + +static void rf_receive(uint8_t rx_channel) +{ + if (rf_state == RF_TX_STARTED) { + return; + } + rf_lock(); + rf_disable_all_interrupts(); + rf_state_change(S2LP_STATE_READY, false); + rf_send_command(S2LP_CMD_FLUSHRXFIFO); + rf_poll_state_change(S2LP_STATE_READY); + if (rx_channel != rf_rx_channel) { + rf_write_register(CHNUM, rx_channel * rf_channel_multiplier); + rf_rx_channel = rf_new_channel = rx_channel; + } + rf_state_change(S2LP_STATE_LOCK, false); + rf_state_change(S2LP_STATE_RX, false); + rf_enable_interrupt(SYNC_WORD); + rf_enable_interrupt(RX_FIFO_ALMOST_FULL); + rf_enable_interrupt(RX_DATA_READY); + rf_enable_interrupt(RX_FIFO_UNF_OVF); + rx_data_length = 0; + rf_state = RF_IDLE; + rf_unlock(); +} + +#ifdef MBED_CONF_RTOS_PRESENT +static void rf_interrupt_handler(void) +{ + rf->irq_thread.signal_set(SIG_RADIO); +} + +void RFPins::rf_irq_task(void) +{ + for (;;) { + osEvent event = irq_thread.signal_wait(0); + if (event.status != osEventSignal) { + continue; + } + rf_lock(); + if (event.value.signals & SIG_RADIO) { + rf_irq_task_process_irq(); + } + if (event.value.signals & SIG_TIMER_CCA) { + rf_cca_timer_interrupt(); + } + if (event.value.signals & SIG_TIMER_BACKUP) { + rf_backup_timer_interrupt(); + } + rf_unlock(); + } +} + +static void rf_irq_task_process_irq(void) +#else //MBED_CONF_RTOS_PRESENT +static void rf_interrupt_handler(void) +#endif //MBED_CONF_RTOS_PRESENT +{ + rf_lock(); + uint32_t irq_status = read_irq_status(); + if (rf_state == RF_TX_STARTED || rf_state == RF_TX_ACK) { + if ((irq_status & (1 << TX_DATA_SENT)) && (enabled_interrupts & (1 << TX_DATA_SENT))) { + rf_tx_sent_handler(); + } + } + if (rf_state == RF_TX_STARTED) { + if ((irq_status & (1 << TX_FIFO_ALMOST_EMPTY)) && (enabled_interrupts & (1 << TX_FIFO_ALMOST_EMPTY))) { + rf_tx_threshold_handler(); + } + } + if ((irq_status & (1 << TX_FIFO_UNF_OVF)) && (enabled_interrupts & (1 << TX_FIFO_UNF_OVF))) { + tx_finnish_time = rf_get_timestamp(); + TEST_TX_DONE + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_FAIL, 1, 0); + rf_send_command(S2LP_CMD_SABORT); + rf_poll_state_change(S2LP_STATE_READY); + rf_send_command(S2LP_CMD_FLUSHTXFIFO); + rf_poll_state_change(S2LP_STATE_READY); + rf_state = RF_IDLE; + rf_receive(rf_rx_channel); + } + if (rf_state == RF_IDLE || rf_state == RF_TX_STARTED) { + if ((irq_status & (1 << SYNC_WORD)) && (enabled_interrupts & (1 << SYNC_WORD))) { + rf_sync_detected_handler(); + } + } else if (rf_state == RF_RX_STARTED) { + if ((irq_status & (1 << RX_DATA_READY)) && (enabled_interrupts & (1 << RX_DATA_READY))) { + if (!(irq_status & (1 << CRC_ERROR))) { + rf_rx_ready_handler(); + } else { + rf_state = RF_IDLE; + // In case the channel change was called during reception, driver is responsible to change the channel if CRC failed. + rf_receive(rf_new_channel); + } + } + if ((irq_status & (1 << RX_FIFO_ALMOST_FULL)) && (enabled_interrupts & (1 << RX_FIFO_ALMOST_FULL))) { + rf_rx_threshold_handler(); + } + if ((irq_status & (1 << RX_DATA_DISCARDED)) && (enabled_interrupts & (1 << RX_DATA_DISCARDED))) { + + } + if ((irq_status & (1 << CRC_ERROR)) && (enabled_interrupts & (1 << CRC_ERROR))) { + + } + } + if ((irq_status & (1 << RX_FIFO_UNF_OVF)) && (enabled_interrupts & (1 << RX_FIFO_UNF_OVF))) { + TEST_RX_DONE + rf_send_command(S2LP_CMD_SABORT); + rf_poll_state_change(S2LP_STATE_READY); + rf_send_command(S2LP_CMD_FLUSHRXFIFO); + rf_poll_state_change(S2LP_STATE_READY); + rf_state = RF_IDLE; + rf_receive(rf_rx_channel); + } + rf_unlock(); +} + +static void rf_reset(void) +{ + // Shutdown + rf->SDN = 1; + wait_ms(10); + // Wake up + rf->SDN = 0; + // Wait until GPIO0 (RESETN) goes high + while (rf->RF_S2LP_GPIO0 == 0); +} + +static void rf_init(void) +{ +#ifdef TEST_GPIOS_ENABLED + fhss_bc_switch = test1_toggle; + fhss_uc_switch = test2_toggle; +#endif //TEST_GPIOS_ENABLED + rf_reset(); + rf->spi.frequency(10000000); + CS_RELEASE(); + if (PARTNUM != rf_read_register_with_status(DEVICE_INFO1, NULL)) { + tr_err("Invalid part number: %x", rf_read_register_with_status(DEVICE_INFO1, NULL)); + } + if (VERSION != rf_read_register_with_status(DEVICE_INFO0, NULL)) { + tr_err("Invalid version: %x", rf_read_register_with_status(DEVICE_INFO0, NULL)); + } + rf_init_registers(); + rf_enable_gpio_interrupt(); + rf_calculate_symbols_in_seconds(phy_subghz.datarate, phy_subghz.modulation); + rf->tx_timer.start(); + rf_print_registers(); +} + +static int8_t rf_device_register(const uint8_t *mac_addr) +{ + rf_init(); + /*Set pointer to MAC address*/ + device_driver.PHY_MAC = (uint8_t *)mac_addr; + device_driver.driver_description = (char *)"S2LP_MAC"; + device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE; + device_driver.phy_channel_pages = phy_channel_pages; + device_driver.phy_MTU = RF_MTU; + /*No header in PHY*/ + device_driver.phy_header_length = 0; + /*No tail in PHY*/ + device_driver.phy_tail_length = 0; + /*Set address write function*/ + device_driver.address_write = &rf_address_write; + /*Set RF extension function*/ + device_driver.extension = &rf_extension; + /*Set RF state control function*/ + device_driver.state_control = &rf_interface_state_control; + /*Set transmit function*/ + device_driver.tx = &rf_start_cca; + /*NULLIFY rx and tx_done callbacks*/ + device_driver.phy_rx_cb = NULL; + device_driver.phy_tx_done_cb = NULL; + /*Register device driver*/ + rf_radio_driver_id = arm_net_phy_register(&device_driver); + return rf_radio_driver_id; +} + +static void rf_device_unregister() +{ + if (rf_radio_driver_id >= 0) { + arm_net_phy_unregister(rf_radio_driver_id); + rf_radio_driver_id = -1; + } +} + +void NanostackRfPhys2lp::get_mac_address(uint8_t *mac) +{ + +} + +void NanostackRfPhys2lp::set_mac_address(uint8_t *mac) +{ + +} + +int8_t NanostackRfPhys2lp::rf_register() +{ + if (NULL == _rf) { + return -1; + } + rf_lock(); + if (rf != NULL) { + rf_unlock(); + error("Multiple registrations of NanostackRfPhyAtmel not supported"); + return -1; + } + rf = _rf; + int8_t radio_id = rf_device_register(_mac_addr); + if (radio_id < 0) { + rf = NULL; + } + rf_unlock(); + return radio_id; +} + +void NanostackRfPhys2lp::rf_unregister() +{ + rf_lock(); + if (NULL == rf) { + rf_unlock(); + return; + } + rf_device_unregister(); + rf = NULL; + rf_unlock(); +} + +NanostackRfPhys2lp::NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn, +#ifdef TEST_GPIOS_ENABLED + PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5, +#endif //TEST_GPIOS_ENABLED + PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3) + : _mac_addr(), _rf(NULL), _mac_set(false), + _spi_sdi(spi_sdi), _spi_sdo(spi_sdo), _spi_sclk(spi_sclk), _spi_cs(spi_cs), _spi_sdn(spi_sdn), +#ifdef TEST_GPIOS_ENABLED + _spi_test1(spi_test1), _spi_test2(spi_test2), _spi_test3(spi_test3), _spi_test4(spi_test4), _spi_test5(spi_test5), +#endif //TEST_GPIOS_ENABLED + _spi_gpio0(spi_gpio0), _spi_gpio1(spi_gpio1), _spi_gpio2(spi_gpio2), _spi_gpio3(spi_gpio3) +{ + _rf = new RFPins(_spi_sdi, _spi_sdo, _spi_sclk, _spi_cs, _spi_sdn, +#ifdef TEST_GPIOS_ENABLED + _spi_test1, _spi_test2, _spi_test3, _spi_test4, _spi_test5, +#endif //TEST_GPIOS_ENABLED + _spi_gpio0, _spi_gpio1, _spi_gpio2, _spi_gpio3); +} + +NanostackRfPhys2lp::~NanostackRfPhys2lp() +{ + delete _rf; +} + +static bool rf_panid_filter_common(uint8_t *panid_start, uint8_t *pan_id, uint8_t frame_type) +{ + // PHY driver shouldn't drop received Beacon frames as they might be used by load balancing + if (frame_type == MAC_FRAME_BEACON) { + return true; + } + bool retval = true; + uint8_t cmp_table[2] = {0xff, 0xff}; + if (!(pan_id[0] == 0xff && pan_id[1] == 0xff)) { + if (memcmp((uint8_t *)panid_start, (uint8_t *) cmp_table, 2)) { + retval = false; + } + if (!retval) { + for (uint8_t i = 0; i < 2; i++) { + cmp_table[1 - i] = panid_start[i]; + } + if (!memcmp(pan_id, cmp_table, 2)) { + retval = true; + } + } + } + return retval; +} + +static bool rf_panid_v2_filter(uint8_t *ptr, uint8_t *pan_id, uint8_t dst_mode, uint8_t src_mode, uint8_t seq_compressed, uint8_t panid_compressed, uint8_t frame_type) +{ + if ((dst_mode == FC_DST_ADDR_NONE) && (frame_type == MAC_TYPE_DATA || frame_type == MAC_TYPE_COMMAND)) { + return true; + } + if ((dst_mode == FC_DST_64_BITS) && (src_mode == FC_SRC_64_BITS) && panid_compressed) { + return true; + } + if (seq_compressed) { + ptr--; + } + return rf_panid_filter_common(ptr, pan_id, frame_type); +} + +static bool rf_panid_v1_v0_filter(uint8_t *ptr, uint8_t *pan_id, uint8_t frame_type) +{ + return rf_panid_filter_common(ptr, pan_id, frame_type); +} + +static bool rf_addr_filter_common(uint8_t *ptr, uint8_t addr_mode, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr) +{ + uint8_t cmp_table[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + bool retval = true; + switch (addr_mode) { + case FC_DST_16_BITS: + if (memcmp((uint8_t *)ptr, (uint8_t *) cmp_table, 2)) { + retval = false; + } + if (!retval) { + for (uint8_t i = 0; i < 2; i++) { + cmp_table[1 - i] = ptr[i]; + } + + if (!memcmp((uint8_t *)mac_16bit_addr, (uint8_t *) cmp_table, 2)) { + retval = true; + } + } + break; + case FC_DST_64_BITS: + if (memcmp((uint8_t *)ptr, (uint8_t *) cmp_table, 8)) { + retval = false; + } + if (!retval) { + for (uint8_t i = 0; i < 8; i++) { + cmp_table[7 - i] = ptr[i]; + } + + if (!memcmp((uint8_t *)mac_64bit_addr, (uint8_t *) cmp_table, 8)) { + retval = true; + } + } + break; + case FC_DST_ADDR_NONE: + retval = true; + break; + default: + retval = false; + break; + } + return retval; +} + +static bool rf_addr_v2_filter(uint8_t *ptr, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr, uint8_t dst_mode, uint8_t seq_compressed, uint8_t panid_compressed) +{ + if (seq_compressed) { + ptr--; + } + if (panid_compressed) { + ptr -= 2; + } + return rf_addr_filter_common(ptr, dst_mode, mac_64bit_addr, mac_16bit_addr); +} + +static bool rf_addr_v1_v0_filter(uint8_t *ptr, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr, uint8_t dst_mode) +{ + return rf_addr_filter_common(ptr, dst_mode, mac_64bit_addr, mac_16bit_addr); +} + +static bool rf_rx_filter(uint8_t *mac_header, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr, uint8_t *pan_id) +{ + uint8_t dst_mode = (mac_header[1] & FC_DST_MODE); + uint8_t src_mode = (mac_header[1] & FC_SRC_MODE); + uint8_t seq_compressed = ((mac_header[1] & FC_SEQUENCE_COMPRESSION) >> SHIFT_SEQ_COMP_FIELD); + uint8_t panid_compressed = ((mac_header[0] & FC_PAN_ID_COMPRESSION) >> SHIFT_PANID_COMP_FIELD); + uint8_t frame_type = mac_header[0] & MAC_FRAME_TYPE_MASK; + uint8_t version = ((mac_header[1] & VERSION_FIELD_MASK) >> SHIFT_VERSION_FIELD); + if (version == MAC_FRAME_VERSION_2) { + if (!rf_panid_v2_filter(mac_header + OFFSET_DST_PAN_ID, pan_id, dst_mode, src_mode, seq_compressed, panid_compressed, frame_type)) { + return false; + } + if (!rf_addr_v2_filter(mac_header + OFFSET_DST_ADDR, mac_64bit_addr, mac_16bit_addr, dst_mode, seq_compressed, panid_compressed)) { + return false; + } + } else { + if (!rf_panid_v1_v0_filter(mac_header + OFFSET_DST_PAN_ID, pan_id, frame_type)) { + return false; + } + if (!rf_addr_v1_v0_filter(mac_header + OFFSET_DST_ADDR, mac_64bit_addr, mac_16bit_addr, dst_mode)) { + return false; + } + } + return true; +} + +static void rf_print_registers(void) +{ + tr_debug("GPIO0_CONF: %x", rf_read_register_with_status(GPIO0_CONF, NULL)); + tr_debug("GPIO1_CONF: %x", rf_read_register_with_status(GPIO1_CONF, NULL)); + tr_debug("GPIO2_CONF: %x", rf_read_register_with_status(GPIO2_CONF, NULL)); + tr_debug("GPIO3_CONF: %x", rf_read_register_with_status(GPIO3_CONF, NULL)); + tr_debug("SYNT3: %x", rf_read_register_with_status(SYNT3, NULL)); + tr_debug("SYNT2: %x", rf_read_register_with_status(SYNT2, NULL)); + tr_debug("SYNT1: %x", rf_read_register_with_status(SYNT1, NULL)); + tr_debug("SYNT0: %x", rf_read_register_with_status(SYNT0, NULL)); + tr_debug("IF_OFFSET_ANA: %x", rf_read_register_with_status(IF_OFFSET_ANA, NULL)); + tr_debug("IF_OFFSET_DIG: %x", rf_read_register_with_status(IF_OFFSET_DIG, NULL)); + tr_debug("CHSPACE: %x", rf_read_register_with_status(CHSPACE, NULL)); + tr_debug("CHNUM: %x", rf_read_register_with_status(CHNUM, NULL)); + tr_debug("MOD4: %x", rf_read_register_with_status(MOD4, NULL)); + tr_debug("MOD3: %x", rf_read_register_with_status(MOD3, NULL)); + tr_debug("MOD2: %x", rf_read_register_with_status(MOD2, NULL)); + tr_debug("MOD1: %x", rf_read_register_with_status(MOD1, NULL)); + tr_debug("MOD0: %x", rf_read_register_with_status(MOD0, NULL)); + tr_debug("CHFLT: %x", rf_read_register_with_status(CHFLT, NULL)); + tr_debug("AFC2: %x", rf_read_register_with_status(AFC2, NULL)); + tr_debug("AFC1: %x", rf_read_register_with_status(AFC1, NULL)); + tr_debug("AFC0: %x", rf_read_register_with_status(AFC0, NULL)); + tr_debug("RSSI_FLT: %x", rf_read_register_with_status(RSSI_FLT, NULL)); + tr_debug("RSSI_TH: %x", rf_read_register_with_status(RSSI_TH, NULL)); + tr_debug("AGCCTRL4: %x", rf_read_register_with_status(AGCCTRL4, NULL)); + tr_debug("AGCCTRL3: %x", rf_read_register_with_status(AGCCTRL3, NULL)); + tr_debug("AGCCTRL2: %x", rf_read_register_with_status(AGCCTRL2, NULL)); + tr_debug("AGCCTRL1: %x", rf_read_register_with_status(AGCCTRL1, NULL)); + tr_debug("AGCCTRL0: %x", rf_read_register_with_status(AGCCTRL0, NULL)); + tr_debug("ANT_SELECT_CONF: %x", rf_read_register_with_status(ANT_SELECT_CONF, NULL)); + tr_debug("CLOCKREC2: %x", rf_read_register_with_status(CLOCKREC2, NULL)); + tr_debug("CLOCKREC1: %x", rf_read_register_with_status(CLOCKREC1, NULL)); + tr_debug("PCKTCTRL6: %x", rf_read_register_with_status(PCKTCTRL6, NULL)); + tr_debug("PCKTCTRL5: %x", rf_read_register_with_status(PCKTCTRL5, NULL)); + tr_debug("PCKTCTRL4: %x", rf_read_register_with_status(PCKTCTRL4, NULL)); + tr_debug("PCKTCTRL3: %x", rf_read_register_with_status(PCKTCTRL3, NULL)); + tr_debug("PCKTCTRL2: %x", rf_read_register_with_status(PCKTCTRL2, NULL)); + tr_debug("PCKTCTRL1: %x", rf_read_register_with_status(PCKTCTRL1, NULL)); + tr_debug("PCKTLEN1: %x", rf_read_register_with_status(PCKTLEN1, NULL)); + tr_debug("PCKTLEN0: %x", rf_read_register_with_status(PCKTLEN0, NULL)); + tr_debug("SYNC3: %x", rf_read_register_with_status(SYNC3, NULL)); + tr_debug("SYNC2: %x", rf_read_register_with_status(SYNC2, NULL)); + tr_debug("SYNC1: %x", rf_read_register_with_status(SYNC1, NULL)); + tr_debug("SYNC0: %x", rf_read_register_with_status(SYNC0, NULL)); + tr_debug("QI: %x", rf_read_register_with_status(QI, NULL)); + tr_debug("PCKT_PSTMBL: %x", rf_read_register_with_status(PCKT_PSTMBL, NULL)); + tr_debug("PROTOCOL2: %x", rf_read_register_with_status(PROTOCOL2, NULL)); + tr_debug("PROTOCOL1: %x", rf_read_register_with_status(PROTOCOL1, NULL)); + tr_debug("PROTOCOL0: %x", rf_read_register_with_status(PROTOCOL0, NULL)); + tr_debug("FIFO_CONFIG3: %x", rf_read_register_with_status(FIFO_CONFIG3, NULL)); + tr_debug("FIFO_CONFIG2: %x", rf_read_register_with_status(FIFO_CONFIG2, NULL)); + tr_debug("FIFO_CONFIG1: %x", rf_read_register_with_status(FIFO_CONFIG1, NULL)); + tr_debug("FIFO_CONFIG0: %x", rf_read_register_with_status(FIFO_CONFIG0, NULL)); + tr_debug("PCKT_FLT_OPTIONS: %x", rf_read_register_with_status(PCKT_FLT_OPTIONS, NULL)); + tr_debug("PCKT_FLT_GOALS4: %x", rf_read_register_with_status(PCKT_FLT_GOALS4, NULL)); + tr_debug("PCKT_FLT_GOALS3: %x", rf_read_register_with_status(PCKT_FLT_GOALS3, NULL)); + tr_debug("PCKT_FLT_GOALS2: %x", rf_read_register_with_status(PCKT_FLT_GOALS2, NULL)); + tr_debug("PCKT_FLT_GOALS1: %x", rf_read_register_with_status(PCKT_FLT_GOALS1, NULL)); + tr_debug("PCKT_FLT_GOALS0: %x", rf_read_register_with_status(PCKT_FLT_GOALS0, NULL)); + tr_debug("TIMERS5: %x", rf_read_register_with_status(TIMERS5, NULL)); + tr_debug("TIMERS4: %x", rf_read_register_with_status(TIMERS4, NULL)); + tr_debug("TIMERS3: %x", rf_read_register_with_status(TIMERS3, NULL)); + tr_debug("TIMERS2: %x", rf_read_register_with_status(TIMERS2, NULL)); + tr_debug("TIMERS1: %x", rf_read_register_with_status(TIMERS1, NULL)); + tr_debug("TIMERS0: %x", rf_read_register_with_status(TIMERS0, NULL)); + tr_debug("CSMA_CONF3: %x", rf_read_register_with_status(CSMA_CONF3, NULL)); + tr_debug("CSMA_CONF2: %x", rf_read_register_with_status(CSMA_CONF2, NULL)); + tr_debug("CSMA_CONF1: %x", rf_read_register_with_status(CSMA_CONF1, NULL)); + tr_debug("CSMA_CONF0: %x", rf_read_register_with_status(CSMA_CONF0, NULL)); + tr_debug("IRQ_MASK3: %x", rf_read_register_with_status(IRQ_MASK3, NULL)); + tr_debug("IRQ_MASK2: %x", rf_read_register_with_status(IRQ_MASK2, NULL)); + tr_debug("IRQ_MASK1: %x", rf_read_register_with_status(IRQ_MASK1, NULL)); + tr_debug("IRQ_MASK0: %x", rf_read_register_with_status(IRQ_MASK0, NULL)); + tr_debug("FAST_RX_TIMER: %x", rf_read_register_with_status(FAST_RX_TIMER, NULL)); + tr_debug("PA_POWER8: %x", rf_read_register_with_status(PA_POWER8, NULL)); + tr_debug("PA_POWER7: %x", rf_read_register_with_status(PA_POWER7, NULL)); + tr_debug("PA_POWER6: %x", rf_read_register_with_status(PA_POWER6, NULL)); + tr_debug("PA_POWER5: %x", rf_read_register_with_status(PA_POWER5, NULL)); + tr_debug("PA_POWER4: %x", rf_read_register_with_status(PA_POWER4, NULL)); + tr_debug("PA_POWER3: %x", rf_read_register_with_status(PA_POWER3, NULL)); + tr_debug("PA_POWER2: %x", rf_read_register_with_status(PA_POWER2, NULL)); + tr_debug("PA_POWER1: %x", rf_read_register_with_status(PA_POWER1, NULL)); + tr_debug("PA_POWER0: %x", rf_read_register_with_status(PA_POWER0, NULL)); + tr_debug("PA_CONFIG1: %x", rf_read_register_with_status(PA_CONFIG1, NULL)); + tr_debug("PA_CONFIG0: %x", rf_read_register_with_status(PA_CONFIG0, NULL)); + tr_debug("SYNTH_CONFIG2: %x", rf_read_register_with_status(SYNTH_CONFIG2, NULL)); + tr_debug("VCO_CONFIG: %x", rf_read_register_with_status(VCO_CONFIG, NULL)); + tr_debug("VCO_CALIBR_IN2: %x", rf_read_register_with_status(VCO_CALIBR_IN2, NULL)); + tr_debug("VCO_CALIBR_IN1: %x", rf_read_register_with_status(VCO_CALIBR_IN1, NULL)); + tr_debug("VCO_CALIBR_IN0: %x", rf_read_register_with_status(VCO_CALIBR_IN0, NULL)); + tr_debug("XO_RCO_CONF1: %x", rf_read_register_with_status(XO_RCO_CONF1, NULL)); + tr_debug("XO_RCO_CONF0: %x", rf_read_register_with_status(XO_RCO_CONF0, NULL)); + tr_debug("RCO_CALIBR_CONF3: %x", rf_read_register_with_status(RCO_CALIBR_CONF3, NULL)); + tr_debug("RCO_CALIBR_CONF2: %x", rf_read_register_with_status(RCO_CALIBR_CONF2, NULL)); + tr_debug("PM_CONF4: %x", rf_read_register_with_status(PM_CONF4, NULL)); + tr_debug("PM_CONF3: %x", rf_read_register_with_status(PM_CONF3, NULL)); + tr_debug("PM_CONF2: %x", rf_read_register_with_status(PM_CONF2, NULL)); + tr_debug("PM_CONF1: %x", rf_read_register_with_status(PM_CONF1, NULL)); + tr_debug("PM_CONF0: %x", rf_read_register_with_status(PM_CONF0, NULL)); + tr_debug("MC_STATE1: %x", rf_read_register_with_status(MC_STATE1, NULL)); + tr_debug("MC_STATE0: %x", rf_read_register_with_status(MC_STATE0, NULL)); + tr_debug("TX_FIFO_STATUS: %x", rf_read_register_with_status(TX_FIFO_STATUS, NULL)); + tr_debug("RX_FIFO_STATUS: %x", rf_read_register_with_status(RX_FIFO_STATUS, NULL)); + tr_debug("RCO_CALIBR_OUT4: %x", rf_read_register_with_status(RCO_CALIBR_OUT4, NULL)); + tr_debug("RCO_CALIBR_OUT3: %x", rf_read_register_with_status(RCO_CALIBR_OUT3, NULL)); + tr_debug("VCO_CALIBR_OUT1: %x", rf_read_register_with_status(VCO_CALIBR_OUT1, NULL)); + tr_debug("VCO_CALIBR_OUT0: %x", rf_read_register_with_status(VCO_CALIBR_OUT0, NULL)); + tr_debug("TX_PCKT_INFO: %x", rf_read_register_with_status(TX_PCKT_INFO, NULL)); + tr_debug("RX_PCKT_INFO: %x", rf_read_register_with_status(RX_PCKT_INFO, NULL)); + tr_debug("AFC_CORR: %x", rf_read_register_with_status(AFC_CORR, NULL)); + tr_debug("LINK_QUALIF2: %x", rf_read_register_with_status(LINK_QUALIF2, NULL)); + tr_debug("LINK_QUALIF1: %x", rf_read_register_with_status(LINK_QUALIF1, NULL)); + tr_debug("RSSI_LEVEL: %x", rf_read_register_with_status(RSSI_LEVEL, NULL)); + tr_debug("RX_PCKT_LEN1: %x", rf_read_register_with_status(RX_PCKT_LEN1, NULL)); + tr_debug("RX_PCKT_LEN0: %x", rf_read_register_with_status(RX_PCKT_LEN0, NULL)); + tr_debug("CRC_FIELD3: %x", rf_read_register_with_status(CRC_FIELD3, NULL)); + tr_debug("CRC_FIELD2: %x", rf_read_register_with_status(CRC_FIELD2, NULL)); + tr_debug("CRC_FIELD1: %x", rf_read_register_with_status(CRC_FIELD1, NULL)); + tr_debug("CRC_FIELD0: %x", rf_read_register_with_status(CRC_FIELD0, NULL)); + tr_debug("RX_ADDRE_FIELD1: %x", rf_read_register_with_status(RX_ADDRE_FIELD1, NULL)); + tr_debug("RX_ADDRE_FIELD0: %x", rf_read_register_with_status(RX_ADDRE_FIELD0, NULL)); + tr_debug("RSSI_LEVEL_RUN: %x", rf_read_register_with_status(RSSI_LEVEL_RUN, NULL)); + tr_debug("DEVICE_INFO1: %x", rf_read_register_with_status(DEVICE_INFO1, NULL)); + tr_debug("DEVICE_INFO0: %x", rf_read_register_with_status(DEVICE_INFO0, NULL)); + tr_debug("IRQ_STATUS3: %x", rf_read_register_with_status(IRQ_STATUS3, NULL)); + tr_debug("IRQ_STATUS2: %x", rf_read_register_with_status(IRQ_STATUS2, NULL)); + tr_debug("IRQ_STATUS1: %x", rf_read_register_with_status(IRQ_STATUS1, NULL)); + tr_debug("IRQ_STATUS0: %x", rf_read_register_with_status(IRQ_STATUS0, NULL)); +} + +#if MBED_CONF_S2LP_PROVIDE_DEFAULT +NanostackRfPhy &NanostackRfPhy::get_default_instance() +{ + static NanostackRfPhys2lp rf_phy(S2LP_SPI_SDI, S2LP_SPI_SDO, S2LP_SPI_SCLK, S2LP_SPI_CS, S2LP_SPI_SDN, +#ifdef TEST_GPIOS_ENABLED + S2LP_SPI_TEST1, S2LP_SPI_TEST2, S2LP_SPI_TEST3, S2LP_SPI_TEST4, S2LP_SPI_TEST5, +#endif //TEST_GPIOS_ENABLED + S2LP_SPI_GPIO0, S2LP_SPI_GPIO1, S2LP_SPI_GPIO2, S2LP_SPI_GPIO3); + return rf_phy; +} +#endif // MBED_CONF_S2LP_PROVIDE_DEFAULT +#endif // MBED_CONF_NANOSTACK_CONFIGURATION && DEVICE_SPI diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/source/rf_configuration.c b/components/802.15.4_RF/stm-s2lp-rf-driver/source/rf_configuration.c new file mode 100644 index 0000000000..2ccfe85bfa --- /dev/null +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/source/rf_configuration.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2018 ARM Limited. All rights reserved. + * 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. + */ +#include "ns_types.h" +#include "rf_configuration.h" +#include "mbed_trace.h" + +#define TRACE_GROUP "rfcf" + +// Note that F_XO and F_DIG depends on the used clock frequency +#define F_XO 50000000 +#define F_DIG 25000000 +// Note that reference divider depends on REFDIV field in XO_RCO_CONF0 register +#define REF_DIVIDER 1 +// Note that band selector depends on BS field in SYNT3 register +#define BAND_SELECTOR 4 +#define DEF_2EXP33 8589934592 +#define DEF_2EXP20 1048576 +#define DEF_2EXP19 524288 +#define DEF_2EXP16 65536 +#define DEF_2EXP15 32768 +// Use multiplier for better resolution +#define RESOLUTION_MULTIPLIER 1000000 + +void rf_conf_calculate_datarate_registers(uint32_t datarate, uint16_t *datarate_mantissa, uint8_t *datarate_exponent) +{ + uint64_t datarate_m = (uint64_t)datarate * DEF_2EXP33; + uint8_t datarate_e = 1; + while (datarate_m >= DEF_2EXP16) { + datarate_e++; + uint16_t var_2exp_datarate_e = (uint32_t)2 << (datarate_e - 1); + datarate_m = (uint64_t)datarate * DEF_2EXP33; + datarate_m = datarate_m / ((uint64_t)var_2exp_datarate_e * F_DIG); + datarate_m -= DEF_2EXP16; + } + *datarate_mantissa = datarate_m; + *datarate_exponent = datarate_e; +} + +void rf_conf_calculate_base_frequency_registers(uint32_t frequency, uint8_t *synt3, uint8_t *synt2, uint8_t *synt1, uint8_t *synt0) +{ + uint64_t freq_tmp = (uint64_t)frequency * RESOLUTION_MULTIPLIER; + freq_tmp = (freq_tmp / (F_XO / ((BAND_SELECTOR / 2) * REF_DIVIDER))); + freq_tmp *= DEF_2EXP20; + freq_tmp /= RESOLUTION_MULTIPLIER; + *synt3 = (uint8_t)(freq_tmp >> 24); + *synt2 = (uint8_t)(freq_tmp >> 16); + *synt1 = (uint8_t)(freq_tmp >> 8); + *synt0 = (uint8_t)freq_tmp; +} + +void rf_conf_calculate_deviation_registers(uint32_t deviation, uint8_t *fdev_m, uint8_t *fdev_e) +{ + uint64_t fdev_m_tmp = 0xffff; + uint8_t fdev_e_tmp = 1; + + while (fdev_m_tmp > 255) { + fdev_e_tmp++; + uint16_t var_2exp_datarate_e_minus_1 = (uint16_t)2 << ((fdev_e_tmp - 1) - 1); + fdev_m_tmp = (uint64_t)deviation * RESOLUTION_MULTIPLIER; + fdev_m_tmp = (((fdev_m_tmp / F_XO) * DEF_2EXP19 * BAND_SELECTOR * REF_DIVIDER * (8 / BAND_SELECTOR)) / var_2exp_datarate_e_minus_1); + fdev_m_tmp += RESOLUTION_MULTIPLIER / 2; + fdev_m_tmp /= RESOLUTION_MULTIPLIER; + fdev_m_tmp -= 256; + } + *fdev_m = (uint8_t)fdev_m_tmp; + *fdev_e = fdev_e_tmp; +} + +int rf_conf_calculate_channel_spacing_registers(uint32_t channel_spacing, uint8_t *ch_space) +{ + uint64_t ch_space_tmp = (uint64_t)channel_spacing * RESOLUTION_MULTIPLIER; + ch_space_tmp /= F_XO; + ch_space_tmp *= DEF_2EXP15; + ch_space_tmp += RESOLUTION_MULTIPLIER / 2; + ch_space_tmp /= RESOLUTION_MULTIPLIER; + // Check if channel spacing is too high + if (ch_space_tmp > 255) { + return -1; + } + *ch_space = (uint8_t)ch_space_tmp; + return 0; +} + +/* Note: This function doesn't necessarily give the optimal RX filter settings. + * When accurate chflt_m and chflt_e settings are needed they must be computed manually. + * Function uses undefined values (900000, 852000, ...) + * to find the chflt_m and chflt_e settings from the RX filter table (see. S2-LP datasheet). + */ +void rf_conf_calculate_rx_filter_bandwidth_registers(uint32_t rx_bandwidth, uint8_t *chflt_m, uint8_t *chflt_e) +{ + uint8_t chflt_e_tmp = 0; + uint8_t chflt_m_tmp = 0; + + while (rx_bandwidth < 900000 / (2 << chflt_e_tmp)) { + chflt_e_tmp++; + } + uint32_t rx_bandwidth_tmp = rx_bandwidth; + if (chflt_e_tmp > 0) { + rx_bandwidth_tmp = rx_bandwidth * (2 << (chflt_e_tmp - 1)); + } + if (852000 > rx_bandwidth_tmp) { + chflt_m_tmp++; + } + if (806000 > rx_bandwidth_tmp) { + chflt_m_tmp++; + } + if (760000 > rx_bandwidth_tmp) { + chflt_m_tmp++; + } + if (724000 > rx_bandwidth_tmp) { + chflt_m_tmp++; + } + if (682000 > rx_bandwidth_tmp) { + chflt_m_tmp++; + } + if (650000 > rx_bandwidth_tmp) { + chflt_m_tmp++; + } + if (588000 > rx_bandwidth_tmp) { + chflt_m_tmp++; + } + if (542000 > rx_bandwidth_tmp) { + chflt_m_tmp++; + } + *chflt_m = chflt_m_tmp; + *chflt_e = chflt_e_tmp; +} + +void rf_conf_calculate_rssi_threshold_registers(int16_t rssi_threshold, uint8_t *rssi_th) +{ + *rssi_th = rssi_threshold + RSSI_OFFSET; +} diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/source/rf_configuration.h b/components/802.15.4_RF/stm-s2lp-rf-driver/source/rf_configuration.h new file mode 100644 index 0000000000..e6869b2748 --- /dev/null +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/source/rf_configuration.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 ARM Limited. All rights reserved. + * 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. + */ + +#ifndef RF_CONF_H_ +#define RF_CONF_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#define RSSI_OFFSET 146 + +void rf_conf_calculate_datarate_registers(uint32_t datarate, uint16_t *datarate_mantissa, uint8_t *datarate_exponent); +void rf_conf_calculate_base_frequency_registers(uint32_t frequency, uint8_t *synt3, uint8_t *synt2, uint8_t *synt1, uint8_t *synt0); +void rf_conf_calculate_deviation_registers(uint32_t deviation, uint8_t *fdev_m, uint8_t *fdev_e); +int rf_conf_calculate_channel_spacing_registers(uint32_t channel_spacing, uint8_t *ch_space); +void rf_conf_calculate_rx_filter_bandwidth_registers(uint32_t rx_bandwidth, uint8_t *chflt_m, uint8_t *chflt_e); +void rf_conf_calculate_rssi_threshold_registers(int16_t rssi_threshold, uint8_t *rssi_th); + +#ifdef __cplusplus +} +#endif + +#endif /* RF_CONF_H_ */ diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/source/s2lpReg.h b/components/802.15.4_RF/stm-s2lp-rf-driver/source/s2lpReg.h new file mode 100644 index 0000000000..1c855d7523 --- /dev/null +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/source/s2lpReg.h @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2018 ARM Limited. All rights reserved. + * 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. + */ + +#ifndef S2LPREG_H_ +#define S2LPREG_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#define RF_MTU 2047 +#define PARTNUM 0x03 +#define VERSION 0xC1 +#define FIFO_SIZE 128 +#define SPI_HEADER_LENGTH 2 + +#define S2LP_GPIO0 0 +#define S2LP_GPIO1 1 +#define S2LP_GPIO2 2 +#define S2LP_GPIO3 3 + +// GPIO modes +#define DIG_IN 1 +#define DIG_OUT_LOW 2 +#define DIG_OUT_HIGH 3 + +// Interrupt events +#define RX_DATA_READY 0 +#define RX_DATA_DISCARDED 1 +#define TX_DATA_SENT 2 +#define MAX_RE_TX 3 +#define CRC_ERROR 4 +#define TX_FIFO_UNF_OVF 5 +#define RX_FIFO_UNF_OVF 6 +#define TX_FIFO_ALMOST_FULL 7 +#define TX_FIFO_ALMOST_EMPTY 8 +#define RX_FIFO_ALMOST_FULL 9 +#define RX_FIFO_ALMOST_EMPTY 10 +#define MAX_CCA_BACKOFFS 11 +#define VALID_PREAMBLE 12 +#define SYNC_WORD 13 +#define RSSI_ABOVE_THR 14 +#define WAKE_UP_TIMEOUT 15 +#define READY 16 +#define STANDBY_SWITCHING 17 +#define LOW_BATTERY_LVL 18 +#define POWER_ON_RESET 19 +#define RX_TIMER_TIMEOUT 28 +#define SNIFF_TIMER_TIMEOUT 29 + +// GPIO signals +#define NIRQ 0 +#define POR 1 +#define WUT_EXPIRE 2 +#define LOW_BATTERY 3 +#define TX_DATA_OUTPUT 4 +#define TX_STATE 5 +#define TXRX_FIFO_ALMOST_EMPTY 6 +#define TXRX_FIFO_ALMOST_FULL 7 +#define RX_DATA_OUTPUT 8 +#define RX_CLOCK_OUTPUT 9 +#define RX_STATE 10 +#define STATE_OTHER_THAN_SLEEP_OR_STANDBY 11 +#define STANDBY_STATE 12 +#define ANTENNA_SWITCH 13 +#define VALID_PREAMBLE_DETECTED 14 +#define SYNC_WORD_DETECTED 15 +#define RSSI_ABOVE_THRESHOLD 16 +#define TXRX_MODE_INDICATOR 18 +#define VDD 19 +#define GND 20 +#define SMPS_ENABLE 21 +#define SLEEP_STATE 22 +#define READY_STATE 23 +#define LOCK_STATE 24 +#define WAIT_LOCK_DETECTOR 25 +#define TX_DATA_OOK 26 +#define WAIT_READY 27 +#define WAIT_TIMER_EXPIRATION 28 +#define END_OF_CALIBRATION 29 +#define ENABLE_SYNTH_BLOCK 30 + +// RF registers +#define GPIO0_CONF 0x00 +#define GPIO1_CONF 0x01 +#define GPIO2_CONF 0x02 +#define GPIO3_CONF 0x03 +#define SYNT3 0x05 +#define SYNT2 0x06 +#define SYNT1 0x07 +#define SYNT0 0x08 +#define IF_OFFSET_ANA 0x09 +#define IF_OFFSET_DIG 0x0A +#define CHSPACE 0x0C +#define CHNUM 0x0D +#define MOD4 0x0E +#define MOD3 0x0F +#define MOD2 0x10 +#define MOD1 0x11 +#define MOD0 0x12 +#define CHFLT 0x13 +#define AFC2 0x14 +#define AFC1 0x15 +#define AFC0 0x16 +#define RSSI_FLT 0x17 +#define RSSI_TH 0x18 +#define AGCCTRL4 0x1A +#define AGCCTRL3 0x1B +#define AGCCTRL2 0x1C +#define AGCCTRL1 0x1D +#define AGCCTRL0 0x1E +#define ANT_SELECT_CONF 0x1F +#define CLOCKREC2 0x20 +#define CLOCKREC1 0x21 +#define PCKTCTRL6 0x2B +#define PCKTCTRL5 0x2C +#define PCKTCTRL4 0x2D +#define PCKTCTRL3 0x2E +#define PCKTCTRL2 0x2F +#define PCKTCTRL1 0x30 +#define PCKTLEN1 0x31 +#define PCKTLEN0 0x32 +#define SYNC3 0x33 +#define SYNC2 0x34 +#define SYNC1 0x35 +#define SYNC0 0x36 +#define QI 0x37 +#define PCKT_PSTMBL 0x38 +#define PROTOCOL2 0x39 +#define PROTOCOL1 0x3A +#define PROTOCOL0 0x3B +#define FIFO_CONFIG3 0x3C +#define FIFO_CONFIG2 0x3D +#define FIFO_CONFIG1 0x3E +#define FIFO_CONFIG0 0x3F +#define PCKT_FLT_OPTIONS 0x40 +#define PCKT_FLT_GOALS4 0x41 +#define PCKT_FLT_GOALS3 0x42 +#define PCKT_FLT_GOALS2 0x43 +#define PCKT_FLT_GOALS1 0x44 +#define PCKT_FLT_GOALS0 0x45 +#define TIMERS5 0x46 +#define TIMERS4 0x47 +#define TIMERS3 0x48 +#define TIMERS2 0x49 +#define TIMERS1 0x4A +#define TIMERS0 0x4B +#define CSMA_CONF3 0x4C +#define CSMA_CONF2 0x4D +#define CSMA_CONF1 0x4E +#define CSMA_CONF0 0x4F +#define IRQ_MASK3 0x50 +#define IRQ_MASK2 0x51 +#define IRQ_MASK1 0x52 +#define IRQ_MASK0 0x53 +#define FAST_RX_TIMER 0x54 +#define PA_POWER8 0x5A +#define PA_POWER7 0x5B +#define PA_POWER6 0x5C +#define PA_POWER5 0x5D +#define PA_POWER4 0x5E +#define PA_POWER3 0x5F +#define PA_POWER2 0x60 +#define PA_POWER1 0x61 +#define PA_POWER0 0x62 +#define PA_CONFIG1 0x63 +#define PA_CONFIG0 0x64 +#define SYNTH_CONFIG2 0x65 +#define VCO_CONFIG 0x68 +#define VCO_CALIBR_IN2 0x69 +#define VCO_CALIBR_IN1 0x6A +#define VCO_CALIBR_IN0 0x6B +#define XO_RCO_CONF1 0x6C +#define XO_RCO_CONF0 0x6D +#define RCO_CALIBR_CONF3 0x6E +#define RCO_CALIBR_CONF2 0x6F +#define PM_CONF4 0x75 +#define PM_CONF3 0x76 +#define PM_CONF2 0x77 +#define PM_CONF1 0x78 +#define PM_CONF0 0x79 +#define MC_STATE1 0x8D +#define MC_STATE0 0x8E +#define TX_FIFO_STATUS 0x8F +#define RX_FIFO_STATUS 0x90 +#define RCO_CALIBR_OUT4 0x94 +#define RCO_CALIBR_OUT3 0x95 +#define VCO_CALIBR_OUT1 0x99 +#define VCO_CALIBR_OUT0 0x9A +#define TX_PCKT_INFO 0x9C +#define RX_PCKT_INFO 0x9D +#define AFC_CORR 0x9E +#define LINK_QUALIF2 0x9F +#define LINK_QUALIF1 0xA0 +#define RSSI_LEVEL 0xA2 +#define RX_PCKT_LEN1 0xA4 +#define RX_PCKT_LEN0 0xA5 +#define CRC_FIELD3 0xA6 +#define CRC_FIELD2 0xA7 +#define CRC_FIELD1 0xA8 +#define CRC_FIELD0 0xA9 +#define RX_ADDRE_FIELD1 0xAA +#define RX_ADDRE_FIELD0 0xAB +#define RSSI_LEVEL_RUN 0xEF +#define DEVICE_INFO1 0xF0 +#define DEVICE_INFO0 0xF1 +#define IRQ_STATUS3 0xFA +#define IRQ_STATUS2 0xFB +#define IRQ_STATUS1 0xFC +#define IRQ_STATUS0 0xFD +#define TX_FIFO 0xFF +#define RX_FIFO 0xFF + +#define SFD0 0x90 +#define SFD1 0x4e + +#define DEVIATION 125000 +#define RX_FILTER_BANDWIDTH 540000 +#define RSSI_THRESHOLD -60 + +// PCKTCTRL6 +#define PCKT_SYNCLEN_FIELD 0xFC +#define PCKT_SYNCLEN (16 << 2) + +// PCKTCTRL5 +#define PCKT_PREAMBLE_LEN 32 + +// PCKTCTRL3 +#define PCKT_FORMAT_FIELD 0xC0 +#define PCKT_FORMAT_802_15_4 (1 << 6) +#define PCKT_RXMODE_FIELD 0x30 +#define PCKT_RXMODE_NORMAL (0 << 4) + +// PCKTCTRL2 +#define PCKT_FIXVARLEN_FIELD 0x01 +#define PCKT_VARIABLE_LEN (1 << 0) + +// PCKTCTRL1 +#define PCKT_CRCMODE_FIELD 0xE0 +#define PCKT_CRCMODE_0X1021 (3 << 5) +#define PCKT_TXSOURCE_FIELD 0x0C +#define PCKT_TXSOURCE_NORMAL (0 << 2) +#define PCKT_WHITENING_FIELD 0x10 +#define PCKT_WHITENING_ENABLED (1 << 4) + +// MOD4 +#define DATARATE_M_MSB 0x47 +// MOD3 +#define DATARATE_M_LSB 0xAE + +// MOD2 +#define MOD_TYPE_FIELD 0xF0 +#define MOD_2FSK (0 << 4) +#define MOD_2GFSK (10 << 4) +#define DATARATE_E_FIELD 0x0F +#define DATARATE_E (10 << 0) + +// MOD1 +#define FDEV_E_FIELD 0x0F + +// QI +#define PQI_TH_FIELD 0x1E +#define PQI_TH (8 << 1) +#define SQI_EN_FIELD 0x01 +#define SQI_EN (1 << 0) + +// SYNT3 +#define SYNT_FIELD 0x0F + +// CHFLT +#define CHFLT_M_FIELD 0xF0 +#define CHFLT_E_FIELD 0x0F + +// LINK_QUALIF1 +#define CARRIER_SENSE (1 << 7) + +#define SPI_WR_REG 0x00 +#define SPI_RD_REG 0x01 +#define SPI_CMD 0x80 + +typedef enum { + S2LP_STATE_STANDBY = 0x02, + S2LP_STATE_SLEEPA = 0x01, + S2LP_STATE_SLEEPB = 0x03, + S2LP_STATE_READY = 0x00, + S2LP_STATE_LOCK = 0x0C, + S2LP_STATE_RX = 0x30, + S2LP_STATE_TX = 0x5C, + S2LP_STATE_SYNTH_SETUP = 0x50 +} s2lp_states_e; + +typedef enum { + S2LP_CMD_TX = 0x60, + S2LP_CMD_RX, + S2LP_CMD_READY, + S2LP_CMD_STANDBY, + S2LP_CMD_SLEEP, + S2LP_CMD_LOCKRX, + S2LP_CMD_LOCKTX, + S2LP_CMD_SABORT, + S2LP_CMD_LDC_RELOAD, + S2LP_CMD_SRES = 0x70, + S2LP_CMD_FLUSHRXFIFO, + S2LP_CMD_FLUSHTXFIFO, + S2LP_CMD_SEQUPDATE +} s2lp_commands_e; + +typedef enum { + RF_IDLE, + RF_CSMA_STARTED, + RF_TX_STARTED, + RF_RX_STARTED, + RF_TX_ACK +} rf_states_e; + +#ifdef __cplusplus +} +#endif + +#endif /* S2LPREG_H_ */ diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver/NanostackRfPhys2lp.h b/components/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver/NanostackRfPhys2lp.h new file mode 100644 index 0000000000..4dd3568c56 --- /dev/null +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver/NanostackRfPhys2lp.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018 ARM Limited. All rights reserved. + * 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. + */ + +#ifndef NANOSTACK_PHY_S2LP_H_ +#define NANOSTACK_PHY_S2LP_H_ + +#include "mbed.h" +#if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI +#include "NanostackRfPhy.h" + +// Uncomment to use testing gpios attached to TX/RX processes +//#define TEST_GPIOS_ENABLED + +#if !defined(S2LP_SPI_SDI) +#define S2LP_SPI_SDI D11 +#endif +#if !defined(S2LP_SPI_SDO) +#define S2LP_SPI_SDO D12 +#endif +#if !defined(S2LP_SPI_SCLK) +#define S2LP_SPI_SCLK D13 +#endif +#if !defined(S2LP_SPI_CS) +#define S2LP_SPI_CS A1 +#endif +#if !defined(S2LP_SPI_SDN) +#define S2LP_SPI_SDN D7 +#endif +#if !defined(S2LP_SPI_TEST1) +#define S2LP_SPI_TEST1 D6 +#endif +#if !defined(S2LP_SPI_TEST2) +#define S2LP_SPI_TEST2 D5 +#endif +#if !defined(S2LP_SPI_TEST3) +#define S2LP_SPI_TEST3 D4 +#endif +#if !defined(S2LP_SPI_TEST4) +#define S2LP_SPI_TEST4 D2 +#endif +#if !defined(S2LP_SPI_TEST5) +#define S2LP_SPI_TEST5 D8 +#endif +#if !defined(S2LP_SPI_GPIO0) +#define S2LP_SPI_GPIO0 A0 +#endif +#if !defined(S2LP_SPI_GPIO1) +#define S2LP_SPI_GPIO1 A2 +#endif +#if !defined(S2LP_SPI_GPIO2) +#define S2LP_SPI_GPIO2 A3 +#endif +#if !defined(S2LP_SPI_GPIO3) +#define S2LP_SPI_GPIO3 A5 +#endif + +class RFPins; + +class NanostackRfPhys2lp : public NanostackRfPhy { +public: + NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, + PinName spi_sclk, PinName spi_cs, PinName spi_sdn, +#ifdef TEST_GPIOS_ENABLED + PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5, +#endif //TEST_GPIOS_ENABLED + PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3); + virtual ~NanostackRfPhys2lp(); + virtual int8_t rf_register(); + virtual void rf_unregister(); + virtual void get_mac_address(uint8_t *mac); + virtual void set_mac_address(uint8_t *mac); + +private: + uint8_t _mac_addr[8]; + RFPins *_rf; + bool _mac_set; + + const PinName _spi_sdi; + const PinName _spi_sdo; + const PinName _spi_sclk; + const PinName _spi_cs; + const PinName _spi_sdn; +#ifdef TEST_GPIOS_ENABLED + const PinName _spi_test1; + const PinName _spi_test2; + const PinName _spi_test3; + const PinName _spi_test4; + const PinName _spi_test5; +#endif //TEST_GPIOS_ENABLED + const PinName _spi_gpio0; + const PinName _spi_gpio1; + const PinName _spi_gpio2; + const PinName _spi_gpio3; +}; +#endif /* MBED_CONF_NANOSTACK_CONFIGURATION && DEVICE_SPI */ +#endif /* NANOSTACK_PHY_S2LP_H_ */ diff --git a/components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.cpp index 11ffd5bc8d..635e4fe016 100644 --- a/components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.cpp @@ -131,11 +131,11 @@ enum dummy { }; DataFlashBlockDevice::DataFlashBlockDevice(PinName mosi, - PinName miso, - PinName sclk, - PinName cs, - int freq, - PinName nwp) + PinName miso, + PinName sclk, + PinName cs, + int freq, + PinName nwp) : _spi(mosi, miso, sclk), _cs(cs, 1), _nwp(nwp), @@ -164,6 +164,7 @@ DataFlashBlockDevice::DataFlashBlockDevice(PinName mosi, int DataFlashBlockDevice::init() { + _mutex.lock(); DEBUG_PRINTF("init\r\n"); if (!_is_initialized) { @@ -173,6 +174,7 @@ int DataFlashBlockDevice::init() uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); if (val != 1) { + _mutex.unlock(); return BD_ERROR_OK; } @@ -281,33 +283,40 @@ int DataFlashBlockDevice::init() _is_initialized = true; } + _mutex.unlock(); return result; } int DataFlashBlockDevice::deinit() { + _mutex.lock(); DEBUG_PRINTF("deinit\r\n"); if (!_is_initialized) { _init_ref_count = 0; + _mutex.unlock(); return BD_ERROR_OK; } uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); if (val) { + _mutex.unlock(); return BD_ERROR_OK; } _is_initialized = false; + _mutex.unlock(); return BD_ERROR_OK; } int DataFlashBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) { + _mutex.lock(); DEBUG_PRINTF("read: %p %" PRIX64 " %" PRIX64 "\r\n", buffer, addr, size); if (!_is_initialized) { + _mutex.unlock(); return BD_ERROR_DEVICE_ERROR; } @@ -345,14 +354,17 @@ int DataFlashBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) result = BD_ERROR_OK; } + _mutex.unlock(); return result; } int DataFlashBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) { + _mutex.lock(); DEBUG_PRINTF("program: %p %" PRIX64 " %" PRIX64 "\r\n", buffer, addr, size); if (!_is_initialized) { + _mutex.unlock(); return BD_ERROR_DEVICE_ERROR; } @@ -411,14 +423,17 @@ int DataFlashBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t _write_enable(false); } + _mutex.unlock(); return result; } int DataFlashBlockDevice::erase(bd_addr_t addr, bd_size_t size) { + _mutex.lock(); DEBUG_PRINTF("erase: %" PRIX64 " %" PRIX64 "\r\n", addr, size); if (!_is_initialized) { + _mutex.unlock(); return BD_ERROR_DEVICE_ERROR; } @@ -465,6 +480,7 @@ int DataFlashBlockDevice::erase(bd_addr_t addr, bd_size_t size) _write_enable(false); } + _mutex.unlock(); return result; } @@ -484,23 +500,29 @@ bd_size_t DataFlashBlockDevice::get_program_size() const bd_size_t DataFlashBlockDevice::get_erase_size() const { + _mutex.lock(); DEBUG_PRINTF("erase size: %" PRIX16 "\r\n", _block_size); - - return _block_size; + bd_size_t block_size = _block_size; + _mutex.unlock(); + return block_size; } bd_size_t DataFlashBlockDevice::get_erase_size(bd_addr_t addr) const { + _mutex.lock(); DEBUG_PRINTF("erase size: %" PRIX16 "\r\n", _block_size); - - return _block_size; + bd_size_t block_size = _block_size; + _mutex.unlock(); + return block_size; } bd_size_t DataFlashBlockDevice::size() const { + _mutex.lock(); DEBUG_PRINTF("device size: %" PRIX32 "\r\n", _device_size); - - return _device_size; + bd_size_t device_size = _device_size; + _mutex.unlock(); + return device_size; } /** @@ -512,6 +534,7 @@ bd_size_t DataFlashBlockDevice::size() const */ uint16_t DataFlashBlockDevice::_get_register(uint8_t opcode) { + _mutex.lock(); DEBUG_PRINTF("_get_register: %" PRIX8 "\r\n", opcode); /* activate device */ @@ -527,6 +550,7 @@ uint16_t DataFlashBlockDevice::_get_register(uint8_t opcode) /* deactivate device */ _cs = 1; + _mutex.unlock(); return status; } diff --git a/components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.h b/components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.h index 52e2600e09..bd447e7439 100644 --- a/components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.h @@ -173,6 +173,9 @@ private: int _sync(void); int _write_page(const uint8_t *buffer, uint32_t addr, uint32_t offset, uint32_t size); uint32_t _translate_address(bd_addr_t addr); + + // Mutex for thread safety + mutable PlatformMutex _mutex; }; diff --git a/components/storage/blockdevice/COMPONENT_DATAFLASH/mbed_lib.json b/components/storage/blockdevice/COMPONENT_DATAFLASH/mbed_lib.json index 3846bb7457..54b5dc519b 100644 --- a/components/storage/blockdevice/COMPONENT_DATAFLASH/mbed_lib.json +++ b/components/storage/blockdevice/COMPONENT_DATAFLASH/mbed_lib.json @@ -1,10 +1,10 @@ { "name": "dataflash", "config": { - "SPI_MOSI": "NC", - "SPI_MISO": "NC", - "SPI_CLK": "NC", - "SPI_CS": "NC", + "SPI_MOSI": "SPI_MOSI", + "SPI_MISO": "SPI_MISO", + "SPI_CLK": "SPI_SCK", + "SPI_CS": "SPI_CS", "SPI_FREQ": "40000000", "binary-size": { "help": "Configure device to use binary address space.", diff --git a/components/storage/blockdevice/COMPONENT_FLASHIAP/FlashIAPBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_FLASHIAP/FlashIAPBlockDevice.cpp index a79f57f482..c0ce2ce2ba 100644 --- a/components/storage/blockdevice/COMPONENT_FLASHIAP/FlashIAPBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_FLASHIAP/FlashIAPBlockDevice.cpp @@ -36,14 +36,8 @@ #define DEBUG_PRINTF(...) #endif -FlashIAPBlockDevice::FlashIAPBlockDevice() - : _flash(), _base(0), _size(0), _is_initialized(false), _init_ref_count(0) -{ - DEBUG_PRINTF("FlashIAPBlockDevice: %" PRIX32 " %" PRIX32 "\r\n", address, size); -} - -FlashIAPBlockDevice::FlashIAPBlockDevice(uint32_t address, uint32_t) - : _flash(), _base(0), _size(0), _is_initialized(false), _init_ref_count(0) +FlashIAPBlockDevice::FlashIAPBlockDevice(uint32_t address, uint32_t size) + : _flash(), _base(address), _size(size), _is_initialized(false), _init_ref_count(0) { } @@ -70,11 +64,27 @@ int FlashIAPBlockDevice::init() int ret = _flash.init(); if (ret) { + core_util_atomic_decr_u32(&_init_ref_count, 1); return ret; } - _base = _flash.get_flash_start(); - _size = _flash.get_flash_size(); + if (_size + _base > _flash.get_flash_size() + _flash.get_flash_start()) { + core_util_atomic_decr_u32(&_init_ref_count, 1); + return BD_ERROR_DEVICE_ERROR; + } + + if (_base < _flash.get_flash_start()) { + core_util_atomic_decr_u32(&_init_ref_count, 1); + return BD_ERROR_DEVICE_ERROR; + } + + if (!_base) { + _base = _flash.get_flash_start(); + } + + if (!_size) { + _size = _flash.get_flash_size() - (_base - _flash.get_flash_start()); + } _is_initialized = true; return ret; @@ -217,6 +227,20 @@ bd_size_t FlashIAPBlockDevice::get_erase_size(bd_addr_t addr) const return erase_size; } +int FlashIAPBlockDevice::get_erase_value() const +{ + if (!_is_initialized) { + return -1; + } + + uint8_t erase_val = _flash.get_erase_value(); + + DEBUG_PRINTF("get_erase_value: %" PRIX8 "\r\n", erase_val); + + return erase_val; +} + + bd_size_t FlashIAPBlockDevice::size() const { DEBUG_PRINTF("size: %" PRIX64 "\r\n", _size); diff --git a/components/storage/blockdevice/COMPONENT_FLASHIAP/FlashIAPBlockDevice.h b/components/storage/blockdevice/COMPONENT_FLASHIAP/FlashIAPBlockDevice.h index 13865cee90..0c1213295a 100644 --- a/components/storage/blockdevice/COMPONENT_FLASHIAP/FlashIAPBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_FLASHIAP/FlashIAPBlockDevice.h @@ -28,12 +28,15 @@ */ class FlashIAPBlockDevice : public BlockDevice { public: - /** Creates a FlashIAPBlockDevice **/ - FlashIAPBlockDevice(); - - MBED_DEPRECATED("Please use default constructor instead") - FlashIAPBlockDevice(uint32_t address, uint32_t size = 0); + /** Creates a FlashIAPBlockDevice + * + * @param address Physical address where the block device start + * @param size The block device size + */ + FlashIAPBlockDevice(uint32_t address = MBED_CONF_FLASHIAP_BLOCK_DEVICE_BASE_ADDRESS, + uint32_t size = MBED_CONF_FLASHIAP_BLOCK_DEVICE_SIZE); + virtual ~FlashIAPBlockDevice(); /** Initialize a block device @@ -106,6 +109,12 @@ public: */ virtual bd_size_t get_erase_size(bd_addr_t addr) const; + /** Get the value of storage when erased + * + * @return The value of storage when erased + */ + virtual int get_erase_value() const; + /** Get the total size of the underlying device * * @return Size of the underlying device in bytes diff --git a/components/storage/blockdevice/COMPONENT_FLASHIAP/TESTS/filesystem/fopen/fopen.cpp b/components/storage/blockdevice/COMPONENT_FLASHIAP/TESTS/filesystem/fopen/fopen.cpp index debe30b28d..9c80f85dc4 100644 --- a/components/storage/blockdevice/COMPONENT_FLASHIAP/TESTS/filesystem/fopen/fopen.cpp +++ b/components/storage/blockdevice/COMPONENT_FLASHIAP/TESTS/filesystem/fopen/fopen.cpp @@ -63,7 +63,7 @@ using namespace utest::v1; * "DEVICE_SPI": 1, * "FSLITTLE_SDCARD_INSTALLED": 1 * }, - * <<< lines removed >>> + * <<< lines removed >>> */ #include "FlashIAPBlockDevice.h" @@ -123,8 +123,8 @@ static const char *sd_testfile_path = "/sd/test.txt"; /* file data for test_01 */ static fslittle_kv_data_t fslittle_fopen_test_01_kv_data[] = { - { "/sd/fopentst/hello/world/animal/wobbly/dog/foot/frontlft.txt", "missing"}, - { NULL, NULL}, + { "/sd/fopentst/hello/world/animal/wobbly/dog/foot/frontlft.txt", "missing"}, + { NULL, NULL}, }; @@ -150,14 +150,14 @@ static fslittle_kv_data_t fslittle_fopen_test_01_kv_data[] = { * * @return On success, this returns the number of components in the filepath Returns number of compoee */ -static int32_t fslittle_filepath_split(char* filepath, char* parts[], uint32_t num) +static int32_t fslittle_filepath_split(char *filepath, char *parts[], uint32_t num) { uint32_t i = 0; int32_t ret = -1; - char* z = filepath; + char *z = filepath; while (i < num && *z != '\0') { - if (*z == '/' ) { + if (*z == '/') { *z = '\0'; parts[i] = ++z; i++; @@ -180,7 +180,7 @@ static int32_t fslittle_filepath_split(char* filepath, char* parts[], uint32_t n * * @return On success, this returns 0, otherwise < 0 is returned; */ -int32_t fslittle_filepath_remove_all(char* filepath) +int32_t fslittle_filepath_remove_all(char *filepath) { int32_t ret = -1; int32_t len = 0; @@ -189,12 +189,12 @@ int32_t fslittle_filepath_remove_all(char* filepath) FSLITTLE_FENTRYLOG("%s:entered\n", __func__); len = strlen(filepath); - fpathbuf = (char*) malloc(len+1); + fpathbuf = (char *) malloc(len + 1); if (fpathbuf == NULL) { FSLITTLE_DBGLOG("%s: failed to duplicate string (out of memory)\n", __func__); return ret; } - memset(fpathbuf, 0, len+1); + memset(fpathbuf, 0, len + 1); memcpy(fpathbuf, filepath, len); /* delete the leaf node first, and then successively parent directories. */ @@ -224,7 +224,7 @@ int32_t fslittle_filepath_remove_all(char* filepath) * * @return On success, this returns 0, otherwise < 0 is returned; */ -static int32_t fslittle_filepath_make_dirs(char* filepath, bool do_asserts) +static int32_t fslittle_filepath_make_dirs(char *filepath, bool do_asserts) { int32_t i = 0; int32_t num_parts = 0; @@ -239,12 +239,12 @@ static int32_t fslittle_filepath_make_dirs(char* filepath, bool do_asserts) /* find the dirs to create*/ memset(parts, 0, sizeof(parts)); len = strlen(filepath); - fpathbuf = (char*) malloc(len+1); + fpathbuf = (char *) malloc(len + 1); if (fpathbuf == NULL) { FSLITTLE_DBGLOG("%s: failed to duplicate string (out of memory)\n", __func__); return ret; } - memset(fpathbuf, 0, len+1); + memset(fpathbuf, 0, len + 1); memcpy(fpathbuf, filepath, len); num_parts = fslittle_filepath_split(fpathbuf, parts, FSLITTLE_FOPEN_TEST_FILEPATH_MAX_DEPTH); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to split filepath (filename=\"%s\", num_parts=%d)\n", __func__, filepath, (int) num_parts); @@ -252,11 +252,11 @@ static int32_t fslittle_filepath_make_dirs(char* filepath, bool do_asserts) /* Now create the directories on the directory path. * Skip creating dir for "/sd" which must be present */ - buf = (char*) malloc(strlen(filepath)+1); - memset(buf, 0, strlen(filepath)+1); + buf = (char *) malloc(strlen(filepath) + 1); + memset(buf, 0, strlen(filepath) + 1); pos = sprintf(buf, "/%s", parts[0]); for (i = 1; i < num_parts - 1; i++) { - pos += sprintf(buf+pos, "/%s", parts[i]); + pos += sprintf(buf + pos, "/%s", parts[i]); FSLITTLE_DBGLOG("mkdir(%s)\n", buf); ret = mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if (do_asserts == true) { @@ -289,7 +289,7 @@ static int32_t fslittle_filepath_make_dirs(char* filepath, bool do_asserts) */ static control_t fslittle_fopen_test_01(const size_t call_count) { - char* read_buf; + char *read_buf; int32_t ret = 0; size_t len = 0; fslittle_kv_data_t *node; @@ -300,10 +300,10 @@ static control_t fslittle_fopen_test_01(const size_t call_count) node = fslittle_fopen_test_01_kv_data; /* remove file and directory from a previous failed test run, if present */ - fslittle_filepath_remove_all((char*) node->filename); + fslittle_filepath_remove_all((char *) node->filename); /* create dirs */ - ret = fslittle_filepath_make_dirs((char*) node->filename, true); + ret = fslittle_filepath_make_dirs((char *) node->filename, true); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dirs for filename (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); TEST_ASSERT_MESSAGE(ret == 0, fslittle_fopen_utest_msg_g); @@ -314,7 +314,7 @@ static control_t fslittle_fopen_test_01(const size_t call_count) FSLITTLE_DBGLOG("%s:length of file=%d (filename=\"%s\", data=\"%s\")\n", __func__, (int) len, node->filename, node->value); len = strlen(node->value); - ret = fwrite((const void*) node->value, len, 1, fp); + ret = fwrite((const void *) node->value, len, 1, fp); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write file (filename=\"%s\", data=\"%s\")(ret=%d)\n", __func__, node->filename, node->value, (int) ret); TEST_ASSERT_MESSAGE(ret == 1, fslittle_fopen_utest_msg_g); @@ -330,13 +330,13 @@ static control_t fslittle_fopen_test_01(const size_t call_count) TEST_ASSERT_MESSAGE(fp != NULL, fslittle_fopen_utest_msg_g); len = strlen(node->value) + 1; - read_buf = (char*) malloc(len); + read_buf = (char *) malloc(len); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to allocated read buffer \n", __func__); TEST_ASSERT_MESSAGE(read_buf != NULL, fslittle_fopen_utest_msg_g); FSLITTLE_DBGLOG("Opened file successfully (filename=\"%s\", data=\"%s\")\n", node->filename, node->value); memset(read_buf, 0, len); - ret = fread((void*) read_buf, len, 1, fp); + ret = fread((void *) read_buf, len, 1, fp); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to read file (filename=\"%s\", data=\"%s\", read_buf=\"%s\", ret=%d)\n", __func__, node->filename, node->value, read_buf, (int) ret); /* FIX ME: fread should return the number of items read, not 0 when an item is read successfully. * This indicates a problem with the implementation, as the correct data is read. The correct assert should be: @@ -349,7 +349,7 @@ static control_t fslittle_fopen_test_01(const size_t call_count) FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: read value data (%s) != expected value data (filename=\"%s\", data=\"%s\", read_buf=\"%s\", ret=%d)\n", __func__, read_buf, node->filename, node->value, read_buf, (int) ret); TEST_ASSERT_MESSAGE(strncmp(read_buf, node->value, strlen(node->value)) == 0, fslittle_fopen_utest_msg_g); - if(read_buf){ + if (read_buf) { free(read_buf); } ret = fclose(fp); @@ -359,8 +359,8 @@ static control_t fslittle_fopen_test_01(const size_t call_count) } static fslittle_kv_data_t fslittle_fopen_test_02_data[] = { - FSLITTLE_INIT_1_TABLE_MID_NODE, - { NULL, NULL}, + FSLITTLE_INIT_1_TABLE_MID_NODE, + { NULL, NULL}, }; /** @@ -385,7 +385,7 @@ control_t fslittle_fopen_test_02(const size_t call_count) FSLITTLE_FENTRYLOG("%s:entered\n", __func__); (void) call_count; len = strlen(fslittle_fopen_test_02_data[0].value); - ret = fslittle_test_create(fslittle_fopen_test_02_data[0].filename, (char*) fslittle_fopen_test_02_data[0].value, len); + ret = fslittle_test_create(fslittle_fopen_test_02_data[0].filename, (char *) fslittle_fopen_test_02_data[0].value, len); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); @@ -395,7 +395,7 @@ control_t fslittle_fopen_test_02(const size_t call_count) TEST_ASSERT_MESSAGE(fp != NULL, fslittle_fopen_utest_msg_g); len = strlen(fslittle_fopen_test_02_data[0].value); - ret = fwrite((const void*) fslittle_fopen_test_02_data[0].value, len, 1, fp); + ret = fwrite((const void *) fslittle_fopen_test_02_data[0].value, len, 1, fp); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: call to fwrite() succeeded when should have failed for read-only file (filename=\"%s\")(ret=%d).\n", __func__, fslittle_fopen_test_02_data[0].filename, (int) ret); TEST_ASSERT_MESSAGE(ret <= 0, fslittle_fopen_utest_msg_g); @@ -428,7 +428,7 @@ control_t fslittle_fopen_test_03(const size_t call_count) FSLITTLE_FENTRYLOG("%s:entered\n", __func__); (void) call_count; len = strlen(fslittle_fopen_test_02_data[0].value); - ret = fslittle_test_create(fslittle_fopen_test_02_data[0].filename, (char*) fslittle_fopen_test_02_data[0].value, len); + ret = fslittle_test_create(fslittle_fopen_test_02_data[0].filename, (char *) fslittle_fopen_test_02_data[0].value, len); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file in store (ret=%d).\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); @@ -438,7 +438,7 @@ control_t fslittle_fopen_test_03(const size_t call_count) TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); len = strlen(fslittle_fopen_test_02_data[0].value); - ret = fwrite((const void*) fslittle_fopen_test_02_data[0].value, len, 1, fp); + ret = fwrite((const void *) fslittle_fopen_test_02_data[0].value, len, 1, fp); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: call to fwrite() failed when should have succeeded (filename=\"%s\", ret=%d).\n", __func__, fslittle_fopen_test_02_data[0].filename, (int) ret); TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); @@ -461,16 +461,16 @@ control_t fslittle_fopen_test_03(const size_t call_count) */ control_t fslittle_fopen_test_04(const size_t call_count) { - char filename_good[FSLITTLE_FILENAME_MAX_LENGTH+1]; - char filename_bad[FSLITTLE_FILENAME_MAX_LENGTH+2]; + char filename_good[FSLITTLE_FILENAME_MAX_LENGTH + 1]; + char filename_bad[FSLITTLE_FILENAME_MAX_LENGTH + 2]; int32_t ret = -1; size_t len = 0; FSLITTLE_FENTRYLOG("%s:entered\n", __func__); (void) call_count; - memset(filename_good, 0, FSLITTLE_FILENAME_MAX_LENGTH+1); - memset(filename_bad, 0, FSLITTLE_FILENAME_MAX_LENGTH+2); + memset(filename_good, 0, FSLITTLE_FILENAME_MAX_LENGTH + 1); + memset(filename_bad, 0, FSLITTLE_FILENAME_MAX_LENGTH + 2); ret = fslittle_test_filename_gen(filename_good, FSLITTLE_FILENAME_MAX_LENGTH); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: unable to generate filename_good.\n", __func__); TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); @@ -478,11 +478,11 @@ control_t fslittle_fopen_test_04(const size_t call_count) FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: filename_good is not the correct length (filename_good=%s, len=%d, expected=%d).\n", __func__, filename_good, (int) strlen(filename_good), (int) FSLITTLE_FILENAME_MAX_LENGTH); TEST_ASSERT_MESSAGE(strlen(filename_good) == FSLITTLE_FILENAME_MAX_LENGTH, fslittle_fopen_utest_msg_g); - ret = fslittle_test_filename_gen(filename_bad, FSLITTLE_FILENAME_MAX_LENGTH+1); + ret = fslittle_test_filename_gen(filename_bad, FSLITTLE_FILENAME_MAX_LENGTH + 1); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: unable to generate filename_bad.\n", __func__); TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); - FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: filename_bad is not the correct length (len=%d, expected=%d).\n", __func__, (int) strlen(filename_bad), (int) FSLITTLE_FILENAME_MAX_LENGTH+1); - TEST_ASSERT_MESSAGE(strlen(filename_bad) == FSLITTLE_FILENAME_MAX_LENGTH+1, fslittle_fopen_utest_msg_g); + FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: filename_bad is not the correct length (len=%d, expected=%d).\n", __func__, (int) strlen(filename_bad), (int) FSLITTLE_FILENAME_MAX_LENGTH + 1); + TEST_ASSERT_MESSAGE(strlen(filename_bad) == FSLITTLE_FILENAME_MAX_LENGTH + 1, fslittle_fopen_utest_msg_g); len = strlen(filename_good); ret = fslittle_test_create(filename_good, filename_good, len); @@ -505,28 +505,27 @@ typedef struct fslittle_fopen_kv_name_ascii_node { static const uint32_t fslittle_fopen_kv_name_ascii_table_code_sentinel_g = 256; /*@brief table recording ascii character codes permitted in kv names */ -static fslittle_fopen_kv_name_ascii_node fslittle_fopen_kv_name_ascii_table[] = -{ - {0 , true}, /* code 0-33 allowed*/ - {34, false}, /* '"' not allowed */ - {35, true}, /* allowed */ - {42, false}, /* '*' not allowed */ - {43, true}, /* allowed */ - {47, false}, /* '/' not allowed */ - {48, true}, /* allowed */ - {58, false}, /* ':' not allowed */ - {59, true}, /* allowed */ - {60, false}, /* '<' not allowed */ - {61, true}, /* allowed */ - {62, false}, /* '?', '>' not allowed */ - {64, true}, /* allowed */ - {92, false}, /* '\' not allowed */ - {93, true}, /* allowed */ - {124, false}, /* '!' not allowed */ - {125, true}, /* allowed */ - {127, false}, /* DEL not allowed */ - {128, true}, /* allowed */ - {fslittle_fopen_kv_name_ascii_table_code_sentinel_g, false}, /* sentinel */ +static fslittle_fopen_kv_name_ascii_node fslittle_fopen_kv_name_ascii_table[] = { + {0, true}, /* code 0-33 allowed*/ + {34, false}, /* '"' not allowed */ + {35, true}, /* allowed */ + {42, false}, /* '*' not allowed */ + {43, true}, /* allowed */ + {47, false}, /* '/' not allowed */ + {48, true}, /* allowed */ + {58, false}, /* ':' not allowed */ + {59, true}, /* allowed */ + {60, false}, /* '<' not allowed */ + {61, true}, /* allowed */ + {62, false}, /* '?', '>' not allowed */ + {64, true}, /* allowed */ + {92, false}, /* '\' not allowed */ + {93, true}, /* allowed */ + {124, false}, /* '!' not allowed */ + {125, true}, /* allowed */ + {127, false}, /* DEL not allowed */ + {128, true}, /* allowed */ + {fslittle_fopen_kv_name_ascii_table_code_sentinel_g, false}, /* sentinel */ }; @@ -555,12 +554,12 @@ control_t fslittle_fopen_test_05(const size_t call_count) const char *basename = "goodfile"; const char *extname = "txt"; const size_t basename_len = strlen(basename); - const size_t filename_len = strlen(mnt_pt)+strlen(basename)+strlen(extname)+2; /* extra 2 chars for '/' and '.' in "/sd/goodfile.txt" */ + const size_t filename_len = strlen(mnt_pt) + strlen(basename) + strlen(extname) + 2; /* extra 2 chars for '/' and '.' in "/sd/goodfile.txt" */ char filename[FSLITTLE_BUF_MAX_LENGTH]; size_t len = 0; uint32_t j = 0; int32_t ret = 0; - fslittle_fopen_kv_name_ascii_node* node = NULL; + fslittle_fopen_kv_name_ascii_node *node = NULL; uint32_t pos; FSLITTLE_FENTRYLOG("%s:entered\n", __func__); @@ -568,90 +567,83 @@ control_t fslittle_fopen_test_05(const size_t call_count) #ifdef FSLITTLE_DEBUG /* symbol only used why debug is enabled */ - const char* pos_str = NULL; + const char *pos_str = NULL; #endif /* create bad keyname strings with invalid character code at start of keyname */ node = fslittle_fopen_kv_name_ascii_table; memset(filename, 0, FSLITTLE_BUF_MAX_LENGTH); - while(node->code != fslittle_fopen_kv_name_ascii_table_code_sentinel_g) - { + while (node->code != fslittle_fopen_kv_name_ascii_table_code_sentinel_g) { /* loop over range */ - for(j = node->code; j < (node+1)->code; j++) - { - if( (j >= 48 && j <= 57) || (j >= 65 && j <= 90) || (j >= 97 && j <= 122)) { + for (j = node->code; j < (node + 1)->code; j++) { + if ((j >= 48 && j <= 57) || (j >= 65 && j <= 90) || (j >= 97 && j <= 122)) { FSLITTLE_DBGLOG("%s: skipping alpha-numeric ascii character code %d (%c).\n", __func__, (int) j, (char) j); continue; } /* set the start, mid, last character of the name to the test char code */ - for(pos = (uint32_t) fslittle_fopen_kv_name_pos_start; pos < (uint32_t) fslittle_fopen_kv_name_pos_max; pos++) - { - len = snprintf(filename, filename_len+1, "%s/%s.%s", mnt_pt, basename, extname); + for (pos = (uint32_t) fslittle_fopen_kv_name_pos_start; pos < (uint32_t) fslittle_fopen_kv_name_pos_max; pos++) { + len = snprintf(filename, filename_len + 1, "%s/%s.%s", mnt_pt, basename, extname); /* overwrite a char at the pos start, mid, end of the filename with an ascii char code (both illegal and legal)*/ - switch(pos) - { - case fslittle_fopen_kv_name_pos_start: - filename[5] = (char) j; /* 5 so at to write the second basename char (bad chars as first char not accepted)*/ - break; - case fslittle_fopen_kv_name_pos_mid: - /* create bad keyname strings with invalid character code in the middle of keyname */ - filename[5+basename_len/2] = (char) j; - break; - case fslittle_fopen_kv_name_pos_end: - /* create bad keyname strings with invalid character code at end of keyname */ - filename[5+basename_len-1] = (char) j; - break; - default: - FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: unexpected value of pos (pos=%d).\n", __func__, (int) pos); - TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); - break; + switch (pos) { + case fslittle_fopen_kv_name_pos_start: + filename[5] = (char) j; /* 5 so at to write the second basename char (bad chars as first char not accepted)*/ + break; + case fslittle_fopen_kv_name_pos_mid: + /* create bad keyname strings with invalid character code in the middle of keyname */ + filename[5 + basename_len / 2] = (char) j; + break; + case fslittle_fopen_kv_name_pos_end: + /* create bad keyname strings with invalid character code at end of keyname */ + filename[5 + basename_len - 1] = (char) j; + break; + default: + FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: unexpected value of pos (pos=%d).\n", __func__, (int) pos); + TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); + break; } #ifdef FSLITTLE_DEBUG /* processing only required when debug trace enabled */ - switch(pos) - { - case fslittle_fopen_kv_name_pos_start: - pos_str = "start"; - break; - case fslittle_fopen_kv_name_pos_mid: - pos_str = "middle"; - break; - case fslittle_fopen_kv_name_pos_end: - pos_str = "end"; - break; - default: - break; + switch (pos) { + case fslittle_fopen_kv_name_pos_start: + pos_str = "start"; + break; + case fslittle_fopen_kv_name_pos_mid: + pos_str = "middle"; + break; + case fslittle_fopen_kv_name_pos_end: + pos_str = "end"; + break; + default: + break; } #endif - ret = fslittle_test_create(filename, (const char*) filename, len); + ret = fslittle_test_create(filename, (const char *) filename, len); /* special cases */ - switch(j) - { - //case 0 : - //case 46 : - // switch(pos) - // { - // /* for code = 0 (null terminator). permitted at mid and end of string */ - // /* for code = 46 ('.'). permitted at mid and end of string but not at start */ - // case fslittle_fopen_kv_name_pos_start: - // f_allowed = false; - // break; - // case fslittle_fopen_kv_name_pos_mid: - // case fslittle_fopen_kv_name_pos_end: - // default: - // f_allowed = true; - // break; - // } - // break; - default: - f_allowed = node->f_allowed; - break; + switch (j) { + //case 0 : + //case 46 : + // switch(pos) + // { + // /* for code = 0 (null terminator). permitted at mid and end of string */ + // /* for code = 46 ('.'). permitted at mid and end of string but not at start */ + // case fslittle_fopen_kv_name_pos_start: + // f_allowed = false; + // break; + // case fslittle_fopen_kv_name_pos_mid: + // case fslittle_fopen_kv_name_pos_end: + // default: + // f_allowed = true; + // break; + // } + // break; + default: + f_allowed = node->f_allowed; + break; } - if(f_allowed == true) - { + if (f_allowed == true) { FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file in store when filename contains valid characters (code=%d, ret=%d).\n", __func__, (int) j, (int) ret); TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); /* revert FSLITTLE_LOG for more trace */ @@ -661,9 +653,8 @@ control_t fslittle_fopen_test_05(const size_t call_count) ret = fslittle_test_delete(filename); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to delete file previously created (code=%d, ret=%d).\n", __func__, (int) j, (int) ret); TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); - } - else - { /*node->f_allowed == false => not allowed to create kv name with ascii code */ + } else { + /*node->f_allowed == false => not allowed to create kv name with ascii code */ FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: created file in store when filename contains an invalid character (code=%d, ret=%d).\n", __func__, (int) j, (int) ret); TEST_ASSERT_MESSAGE(ret < 0, fslittle_fopen_utest_msg_g); /* revert FSLITTLE_LOG for more trace */ @@ -680,7 +671,7 @@ control_t fslittle_fopen_test_05(const size_t call_count) } -static const char fslittle_fopen_ascii_illegal_buf_g[] = "\"�'*+,./:;<=>?[\\]|"; +static const char fslittle_fopen_ascii_illegal_buf_g[] = "\"?'*+,./:;<=>?[\\]|"; /** @brief test to call fopen() with filename that in includes * illegal characters @@ -694,7 +685,7 @@ control_t fslittle_fopen_test_06(const size_t call_count) #if 0 const char *mnt_pt = FSLITTLE_FOPEN_TEST_MOUNT_PT_PATH; const char *extname = "txt"; - const size_t filename_len = strlen(mnt_pt)+FSLITTLE_MAX_FILE_BASENAME+strlen(extname)+2; /* extra 2 chars for '/' and '.' in "/sd/goodfile.txt" */ + const size_t filename_len = strlen(mnt_pt) + FSLITTLE_MAX_FILE_BASENAME + strlen(extname) + 2; /* extra 2 chars for '/' and '.' in "/sd/goodfile.txt" */ char filename[FSLITTLE_BUF_MAX_LENGTH]; int32_t i = 0; int32_t j = 0; @@ -713,13 +704,13 @@ control_t fslittle_fopen_test_06(const size_t call_count) /* generate a number of illegal filenames */ for (j = 0; i < FSLITTLE_MAX_FILE_BASENAME; j++) { /* generate a kv name of illegal chars*/ - len = snprintf(filename, filename_len+1, "%s/", mnt_pt); + len = snprintf(filename, filename_len + 1, "%s/", mnt_pt); for (i = 0; i < FSLITTLE_MAX_FILE_BASENAME; i++) { - pos = rand() % (buf_data_max+1); - len += snprintf(filename+len, filename_len+1, "%c", fslittle_fopen_ascii_illegal_buf_g[pos]); + pos = rand() % (buf_data_max + 1); + len += snprintf(filename + len, filename_len + 1, "%c", fslittle_fopen_ascii_illegal_buf_g[pos]); } - len += snprintf(filename+len, filename_len+1, ".%s", extname); + len += snprintf(filename + len, filename_len + 1, ".%s", extname); ret = fslittle_test_create(filename, filename, len); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: created file when filename contains invalid characters (filename=%s, ret=%d).\n", __func__, filename, (int) ret); TEST_ASSERT_MESSAGE(ret < 0, fslittle_fopen_utest_msg_g); @@ -731,10 +722,10 @@ control_t fslittle_fopen_test_06(const size_t call_count) /** @brief test for errno reporting on a failed fopen()call * - * This test does the following: - * - tries to open a file that does not exist for reading, and checks that a NULL pointer is returned. - * - checks that errno is not 0 as there is an error. - * - checks that ferror() returns 1 indicating an error exists. + * This test does the following: + * - tries to open a file that does not exist for reading, and checks that a NULL pointer is returned. + * - checks that errno is not 0 as there is an error. + * - checks that ferror() returns 1 indicating an error exists. * * Note: see NOTE_1 below. * @@ -742,8 +733,8 @@ control_t fslittle_fopen_test_06(const size_t call_count) */ control_t fslittle_fopen_test_07(const size_t call_count) { - FILE *f = NULL; - int ret = -1; + FILE *f = NULL; + int ret = -1; int errno_val = 0; const char *filename = sd_badfile_path; @@ -752,7 +743,7 @@ control_t fslittle_fopen_test_07(const size_t call_count) errno = 0; /* this is expect to fail as the file doesnt exist */ - f = fopen(filename,"r"); + f = fopen(filename, "r"); /* Store errno so the current value set is not changed by new function call */ errno_val = errno; @@ -801,7 +792,7 @@ control_t fslittle_fopen_test_08(const size_t call_count) (void) call_count; errno = 0; - fp = fopen(filename,"w+"); + fp = fopen(filename, "w+"); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open file (filename=%s, f=%p).\n", __func__, filename, fp); TEST_ASSERT_MESSAGE(fp != NULL, fslittle_fopen_utest_msg_g); @@ -864,7 +855,7 @@ control_t fslittle_fopen_test_09(const size_t call_count) /* create a file of a certain length */ len = strlen(fslittle_fopen_test_02_data[0].value); - ret = fslittle_test_create(fslittle_fopen_test_02_data[0].filename, (char*) fslittle_fopen_test_02_data[0].value, len); + ret = fslittle_test_create(fslittle_fopen_test_02_data[0].filename, (char *) fslittle_fopen_test_02_data[0].value, len); errno = 0; /* Open the file for reading so the file is not truncated to 0 length. */ @@ -893,8 +884,8 @@ control_t fslittle_fopen_test_09(const size_t call_count) /* file data for test_10 */ static fslittle_kv_data_t fslittle_fopen_test_10_kv_data[] = { - { "/sd/test_10/testfile.txt", "test_data"}, - { NULL, NULL}, + { "/sd/test_10/testfile.txt", "test_data"}, + { NULL, NULL}, }; /** @brief test for operation of remove() @@ -921,16 +912,16 @@ control_t fslittle_fopen_test_10(const size_t call_count) TEST_ASSERT(strlen(node->filename) < FSLITTLE_FOPEN_TEST_WORK_BUF_SIZE_1); /* start from a known state i.e. directory to be created in not present */ - fslittle_filepath_remove_all((char*) node->filename); + fslittle_filepath_remove_all((char *) node->filename); /* (1) */ errno = 0; - ret = fslittle_filepath_make_dirs((char*) node->filename, false); + ret = fslittle_filepath_make_dirs((char *) node->filename, false); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); TEST_ASSERT_MESSAGE(ret == 0, fslittle_fopen_utest_msg_g); len = strlen(node->value); - ret = fslittle_test_create(node->filename, (char*) node->value, len); + ret = fslittle_test_create(node->filename, (char *) node->value, len); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); @@ -963,10 +954,10 @@ control_t fslittle_fopen_test_10(const size_t call_count) /* file data for test_11 */ static fslittle_kv_data_t fslittle_fopen_test_11_kv_data[] = { - { "/sd/test_11/step0.txt", "test_data"}, - { "/sd/test_11/step1.txt", "test_data"}, - { "/sd/test_11/subdir/step3.txt", "test_data"}, - { NULL, NULL}, + { "/sd/test_11/step0.txt", "test_data"}, + { "/sd/test_11/step1.txt", "test_data"}, + { "/sd/test_11/subdir/step3.txt", "test_data"}, + { NULL, NULL}, }; /** @brief test for operation of rename() @@ -989,26 +980,26 @@ control_t fslittle_fopen_test_11(const size_t call_count) TEST_ASSERT(strlen(node->filename) < FSLITTLE_FOPEN_TEST_WORK_BUF_SIZE_1); /* start from a known state i.e. directory to be created in not present, files not present */ - while(node->filename != NULL) { - fslittle_filepath_remove_all((char*) node->filename); + while (node->filename != NULL) { + fslittle_filepath_remove_all((char *) node->filename); node++; } /* create file and directories ready for rename() tests */ errno = 0; node = fslittle_fopen_test_11_kv_data; - ret = fslittle_filepath_make_dirs((char*) node->filename, false); + ret = fslittle_filepath_make_dirs((char *) node->filename, false); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); TEST_ASSERT_MESSAGE(ret == 0, fslittle_fopen_utest_msg_g); len = strlen(node->value); - ret = fslittle_test_create(node->filename, (char*) node->value, len); + ret = fslittle_test_create(node->filename, (char *) node->value, len); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); errno = 0; node = &fslittle_fopen_test_11_kv_data[2]; - ret = fslittle_filepath_make_dirs((char*) node->filename, false); + ret = fslittle_filepath_make_dirs((char *) node->filename, false); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); TEST_ASSERT_MESSAGE(ret == 0, fslittle_fopen_utest_msg_g); @@ -1028,12 +1019,12 @@ control_t fslittle_fopen_test_11(const size_t call_count) /* file data for test_12 */ static fslittle_kv_data_t fslittle_fopen_test_12_kv_data[] = { - { "/sd/test_12/subdir/testfil1.txt", "testfil1.txt"}, - { "/sd/test_12/testfil2.txt", "testfil2.txt"}, - { "/sd/test_12/testfil3.txt", "testfil3.txt"}, - { "/sd/test_12/testfil4.txt", "testfil4.txt"}, - { "/sd/test_12/testfil5.txt", "testfil5.txt"}, - { NULL, NULL}, + { "/sd/test_12/subdir/testfil1.txt", "testfil1.txt"}, + { "/sd/test_12/testfil2.txt", "testfil2.txt"}, + { "/sd/test_12/testfil3.txt", "testfil3.txt"}, + { "/sd/test_12/testfil4.txt", "testfil4.txt"}, + { "/sd/test_12/testfil5.txt", "testfil5.txt"}, + { NULL, NULL}, }; /** @brief test for operation of readdir(). @@ -1060,22 +1051,22 @@ control_t fslittle_fopen_test_12(const size_t call_count) #if ! defined(__ARMCC_VERSION) && defined(__GNUC__) /* start from a known state i.e. directory to be created in not present */ - while(node->filename != NULL) { - fslittle_filepath_remove_all((char*) node->filename); + while (node->filename != NULL) { + fslittle_filepath_remove_all((char *) node->filename); node++; } /* create a file */ node = fslittle_fopen_test_12_kv_data; errno = 0; - ret = fslittle_filepath_make_dirs((char*) node->filename, false); + ret = fslittle_filepath_make_dirs((char *) node->filename, false); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); TEST_ASSERT_MESSAGE(ret == 0, fslittle_fopen_utest_msg_g); node = fslittle_fopen_test_12_kv_data; - while(node->filename != NULL) { + while (node->filename != NULL) { len = strlen(node->value); - ret = fslittle_test_create(node->filename, (char*) node->value, len); + ret = fslittle_test_create(node->filename, (char *) node->value, len); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); node++; @@ -1108,8 +1099,8 @@ control_t fslittle_fopen_test_12(const size_t call_count) /* cleanup */ node = fslittle_fopen_test_12_kv_data; - while(node->filename != NULL) { - fslittle_filepath_remove_all((char*) node->filename); + while (node->filename != NULL) { + fslittle_filepath_remove_all((char *) node->filename); node++; } #endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ @@ -1119,10 +1110,10 @@ control_t fslittle_fopen_test_12(const size_t call_count) /* file data for test_13 */ static fslittle_kv_data_t fslittle_fopen_test_13_kv_data[] = { - /* a file is included in the filepath even though its not created by the test, - * as the fslittle_filepath_make_dirs() works with it present. */ - { "/sd/test_13/dummy.txt", "testdir"}, - { NULL, NULL}, + /* a file is included in the filepath even though its not created by the test, + * as the fslittle_filepath_make_dirs() works with it present. */ + { "/sd/test_13/dummy.txt", "testdir"}, + { NULL, NULL}, }; /** @brief test for operation of mkdir()/remove() * @@ -1141,16 +1132,16 @@ control_t fslittle_fopen_test_13(const size_t call_count) (void) call_count; /* start from a known state i.e. directory to be created in not present */ - fslittle_filepath_remove_all((char*) fslittle_fopen_test_13_kv_data[0].filename); + fslittle_filepath_remove_all((char *) fslittle_fopen_test_13_kv_data[0].filename); errno = 0; - ret = fslittle_filepath_make_dirs((char*) fslittle_fopen_test_13_kv_data[0].filename, false); + ret = fslittle_filepath_make_dirs((char *) fslittle_fopen_test_13_kv_data[0].filename, false); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, fslittle_fopen_test_13_kv_data[0].filename, (int) ret, errno); TEST_ASSERT_MESSAGE(ret == 0, fslittle_fopen_utest_msg_g); /* check that get a suitable error when try to create it again.*/ errno = 0; - ret = fslittle_filepath_make_dirs((char*) fslittle_fopen_test_13_kv_data[0].filename, false); + ret = fslittle_filepath_make_dirs((char *) fslittle_fopen_test_13_kv_data[0].filename, false); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: permitted to create directory when already exists (dirname=%s, ret=%d, errno=%d)\n", __func__, fslittle_fopen_test_13_kv_data[0].filename, (int) ret, errno); TEST_ASSERT_MESSAGE(ret != 0, fslittle_fopen_utest_msg_g); @@ -1158,7 +1149,7 @@ control_t fslittle_fopen_test_13(const size_t call_count) FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: errno != EEXIST (dirname=%s, ret=%d, errno=%d)\n", __func__, fslittle_fopen_test_13_kv_data[0].filename, (int) ret, errno); TEST_ASSERT_MESSAGE(errno == EEXIST, fslittle_fopen_utest_msg_g); - ret = fslittle_filepath_remove_all((char*) fslittle_fopen_test_13_kv_data[0].filename); + ret = fslittle_filepath_remove_all((char *) fslittle_fopen_test_13_kv_data[0].filename); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to remove directory (dirname=%s, ret=%d, errno=%d)\n", __func__, fslittle_fopen_test_13_kv_data[0].filename, (int) ret, errno); TEST_ASSERT_MESSAGE(ret == 0, fslittle_fopen_utest_msg_g); @@ -1167,10 +1158,10 @@ control_t fslittle_fopen_test_13(const size_t call_count) /* file data for test_14 */ static fslittle_kv_data_t fslittle_fopen_test_14_kv_data[] = { - /* a file is included in the filepath even though its not created by the test, - * as the fslittle_filepath_make_dirs() works with it present. */ - { "/sd/test_14/testfile.txt", "testdata"}, - { NULL, NULL}, + /* a file is included in the filepath even though its not created by the test, + * as the fslittle_filepath_make_dirs() works with it present. */ + { "/sd/test_14/testfile.txt", "testdata"}, + { NULL, NULL}, }; /** @brief test for operation of stat() @@ -1183,7 +1174,7 @@ control_t fslittle_fopen_test_14(const size_t call_count) { #if ! defined(__ARMCC_VERSION) && defined(__GNUC__) - char buf[FSLITTLE_FOPEN_TEST_WORK_BUF_SIZE_1]; + char buf[FSLITTLE_FOPEN_TEST_WORK_BUF_SIZE_1]; char *pos = NULL; int32_t ret = -1; size_t len = 0; @@ -1196,16 +1187,16 @@ control_t fslittle_fopen_test_14(const size_t call_count) TEST_ASSERT(strlen(node->filename) < FSLITTLE_FOPEN_TEST_WORK_BUF_SIZE_1); /* start from a known state i.e. directory to be created in not present */ - fslittle_filepath_remove_all((char*) node->filename); + fslittle_filepath_remove_all((char *) node->filename); /* Create file in a directory. */ errno = 0; - ret = fslittle_filepath_make_dirs((char*) node->filename, false); + ret = fslittle_filepath_make_dirs((char *) node->filename, false); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); TEST_ASSERT_MESSAGE(ret == 0, fslittle_fopen_utest_msg_g); len = strlen(node->value); - ret = fslittle_test_create(node->filename, (char*) node->value, len); + ret = fslittle_test_create(node->filename, (char *) node->value, len); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= 0, fslittle_fopen_utest_msg_g); @@ -1238,7 +1229,7 @@ control_t fslittle_fopen_test_14(const size_t call_count) TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFDIR) == S_IFDIR, fslittle_fopen_utest_msg_g); /* clean up after successful test */ - fslittle_filepath_remove_all((char*) node->filename); + fslittle_filepath_remove_all((char *) node->filename); #endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ return CaseNext; @@ -1288,7 +1279,7 @@ control_t fslittle_fopen_test_00(const size_t call_count) * @param data data to store in file * @param len number of bytes of data present in the data buffer. */ -int32_t fslittle_test_create_data_file(const char* filename, size_t len) +int32_t fslittle_test_create_data_file(const char *filename, size_t len) { int32_t ret = -1; FILE *fp = NULL; @@ -1300,26 +1291,26 @@ int32_t fslittle_test_create_data_file(const char* filename, size_t len) FSLITTLE_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len); TEST_ASSERT(len % FSLITTLE_TEST_BYTE_DATA_TABLE_SIZE == 0); fp = fopen(filename, "a"); - if(fp == NULL){ + if (fp == NULL) { return ret; } - while(written_len < len) { + while (written_len < len) { /* write fslittle_test_byte_data_table or part thereof, in 9 writes of sizes * 1, 2, 4, 8, 16, 32, 64, 128, 1, totalling 256 bytes len permitting. */ - for(exp = 0; (exp <= exp_max) && (written_len < len); exp++){ + for (exp = 0; (exp <= exp_max) && (written_len < len); exp++) { write_len = 0x1 << (exp % exp_max); write_len = len - written_len > write_len ? write_len : len - written_len; - ret = fwrite((const void*) &fslittle_test_byte_data_table[written_len % FSLITTLE_TEST_BYTE_DATA_TABLE_SIZE], write_len, 1, fp); + ret = fwrite((const void *) &fslittle_test_byte_data_table[written_len % FSLITTLE_TEST_BYTE_DATA_TABLE_SIZE], write_len, 1, fp); written_len += write_len; - if(ret != 1){ + if (ret != 1) { FSLITTLE_DBGLOG("%s:Error: fwrite() failed (ret=%d)\n", __func__, (int) ret); ret = -1; goto out0; } } } - if(written_len == len) { + if (written_len == len) { ret = 0; } else { ret = -1; @@ -1339,7 +1330,7 @@ out0: * @param data data to store in file * @param len number of bytes of data present in the data buffer. */ -int32_t fslittle_test_check_data_file(const char* filename, size_t len) +int32_t fslittle_test_check_data_file(const char *filename, size_t len) { int32_t ret = -1; FILE *fp = NULL; @@ -1349,26 +1340,26 @@ int32_t fslittle_test_check_data_file(const char* filename, size_t len) FSLITTLE_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len); TEST_ASSERT(len % FSLITTLE_TEST_BYTE_DATA_TABLE_SIZE == 0); fp = fopen(filename, "r"); - if(fp == NULL){ + if (fp == NULL) { return ret; } - while(read_len < len) { - ret = fread((void*) buf, FSLITTLE_TEST_BYTE_DATA_TABLE_SIZE, 1, fp); + while (read_len < len) { + ret = fread((void *) buf, FSLITTLE_TEST_BYTE_DATA_TABLE_SIZE, 1, fp); read_len += FSLITTLE_TEST_BYTE_DATA_TABLE_SIZE; - if(ret == 0){ + if (ret == 0) { /* end of read*/ FSLITTLE_DBGLOG("%s:unable to read data\n", __func__); break; } - if(memcmp(buf, fslittle_test_byte_data_table, FSLITTLE_TEST_BYTE_DATA_TABLE_SIZE) != 0) { + if (memcmp(buf, fslittle_test_byte_data_table, FSLITTLE_TEST_BYTE_DATA_TABLE_SIZE) != 0) { FSLITTLE_DBGLOG("%s:Error: read data not as expected (0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x\n", __func__, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]); + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]); ret = -1; goto out0; } } - if(read_len == len) { + if (read_len == len) { ret = 0; } out0: @@ -1378,20 +1369,20 @@ out0: /* file data for test_16 */ static fslittle_kv_data_t fslittle_fopen_test_15_kv_data[] = { - { "/sd/tst16_0/testfil0.txt", "dummy_data"}, - { "/sd/tst16_1/subdir0/testfil0.txt", "dummy_data"}, - { "/sd/tst16_2/subdir0/subdir1/testfil0.txt", "dummy_data"}, - { "/sd/tst16_3/subdir0/subdir1/subdir2/subdir3/testfil0.txt", "dummy_data"}, + { "/sd/tst16_0/testfil0.txt", "dummy_data"}, + { "/sd/tst16_1/subdir0/testfil0.txt", "dummy_data"}, + { "/sd/tst16_2/subdir0/subdir1/testfil0.txt", "dummy_data"}, + { "/sd/tst16_3/subdir0/subdir1/subdir2/subdir3/testfil0.txt", "dummy_data"}, #if 0 - { "/sd/tst16_4/subdir0/subdir1/subdir2/subdir3/subdir4/testfil0.txt", "dummy_data"}, - { "/sd/tst16_5/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/testfil0.txt", "dummy_data"}, - { "/sd/tst16_6/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/testfil0.txt", "dummy_data"}, - { "/sd/tst16_7/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/testfil0.txt", "dummy_data"}, - { "/sd/tst16_8/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/subdir8/testfil0.txt", "dummy_data"}, - { "/sd/tst16_9/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/subdir8/subdir9/testfil0.txt", "dummy_data"}, + { "/sd/tst16_4/subdir0/subdir1/subdir2/subdir3/subdir4/testfil0.txt", "dummy_data"}, + { "/sd/tst16_5/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/testfil0.txt", "dummy_data"}, + { "/sd/tst16_6/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/testfil0.txt", "dummy_data"}, + { "/sd/tst16_7/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/testfil0.txt", "dummy_data"}, + { "/sd/tst16_8/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/subdir8/testfil0.txt", "dummy_data"}, + { "/sd/tst16_9/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/subdir8/subdir9/testfil0.txt", "dummy_data"}, #endif - { NULL, NULL}, + { NULL, NULL}, }; @@ -1409,15 +1400,15 @@ control_t fslittle_fopen_test_15(const size_t call_count) (void) call_count; /* remove file and directory from a previous failed test run, if present */ - while(node->filename != NULL) { - fslittle_filepath_remove_all((char*) node->filename); + while (node->filename != NULL) { + fslittle_filepath_remove_all((char *) node->filename); node++; } /* create dirs */ node = fslittle_fopen_test_15_kv_data; - while(node->filename != NULL) { - ret = fslittle_filepath_make_dirs((char*) node->filename, true); + while (node->filename != NULL) { + ret = fslittle_filepath_make_dirs((char *) node->filename, true); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dirs for filename (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); TEST_ASSERT_MESSAGE(ret == 0, fslittle_fopen_utest_msg_g); node++; @@ -1425,7 +1416,7 @@ control_t fslittle_fopen_test_15(const size_t call_count) /* create the data files */ node = fslittle_fopen_test_15_kv_data; - while(node->filename != NULL) { + while (node->filename != NULL) { ret = fslittle_test_create_data_file(node->filename, num_blocks * FSLITTLE_TEST_BYTE_DATA_TABLE_SIZE); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create data file (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); TEST_ASSERT_MESSAGE(ret == 0, fslittle_fopen_utest_msg_g); @@ -1434,7 +1425,7 @@ control_t fslittle_fopen_test_15(const size_t call_count) /* read the data back and check its as expected */ node = fslittle_fopen_test_15_kv_data; - while(node->filename != NULL) { + while (node->filename != NULL) { ret = fslittle_test_check_data_file(node->filename, num_blocks * FSLITTLE_TEST_BYTE_DATA_TABLE_SIZE); FSLITTLE_TEST_UTEST_MESSAGE(fslittle_fopen_utest_msg_g, FSLITTLE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to check data file (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); TEST_ASSERT_MESSAGE(ret == 0, fslittle_fopen_utest_msg_g); @@ -1443,8 +1434,8 @@ control_t fslittle_fopen_test_15(const size_t call_count) /* clean up */ node = fslittle_fopen_test_15_kv_data; - while(node->filename != NULL) { - fslittle_filepath_remove_all((char*) node->filename); + while (node->filename != NULL) { + fslittle_filepath_remove_all((char *) node->filename); node++; } return CaseNext; @@ -1458,26 +1449,26 @@ utest::v1::status_t greentea_setup(const size_t number_of_cases) } Case cases[] = { - /* 1 2 3 4 5 6 7 */ - /* 1234567890123456789012345678901234567890123456789012345678901234567890 */ - Case("FSLITTLE_FOPEN_TEST_00: format() test.", FSLITTLE_FOPEN_TEST_00), - Case("FSLITTLE_FOPEN_TEST_01: fopen()/fwrite()/fclose() directories/file in multi-dir filepath.", FSLITTLE_FOPEN_TEST_01), - Case("FSLITTLE_FOPEN_TEST_02: fopen(r) pre-existing file try to write it.", FSLITTLE_FOPEN_TEST_02), - Case("FSLITTLE_FOPEN_TEST_03: fopen(w+) pre-existing file try to write it.", FSLITTLE_FOPEN_TEST_03), - Case("FSLITTLE_FOPEN_TEST_04: fopen() with a filename exceeding the maximum length.", FSLITTLE_FOPEN_TEST_04), + /* 1 2 3 4 5 6 7 */ + /* 1234567890123456789012345678901234567890123456789012345678901234567890 */ + Case("FSLITTLE_FOPEN_TEST_00: format() test.", FSLITTLE_FOPEN_TEST_00), + Case("FSLITTLE_FOPEN_TEST_01: fopen()/fwrite()/fclose() directories/file in multi-dir filepath.", FSLITTLE_FOPEN_TEST_01), + Case("FSLITTLE_FOPEN_TEST_02: fopen(r) pre-existing file try to write it.", FSLITTLE_FOPEN_TEST_02), + Case("FSLITTLE_FOPEN_TEST_03: fopen(w+) pre-existing file try to write it.", FSLITTLE_FOPEN_TEST_03), + Case("FSLITTLE_FOPEN_TEST_04: fopen() with a filename exceeding the maximum length.", FSLITTLE_FOPEN_TEST_04), #ifdef FOPEN_EXTENDED_TESTING - Case("FSLITTLE_FOPEN_TEST_05: fopen() with bad filenames (extended).", FSLITTLE_FOPEN_TEST_05), + Case("FSLITTLE_FOPEN_TEST_05: fopen() with bad filenames (extended).", FSLITTLE_FOPEN_TEST_05), #endif - Case("FSLITTLE_FOPEN_TEST_06: fopen() with bad filenames (minimal).", FSLITTLE_FOPEN_TEST_06), - Case("FSLITTLE_FOPEN_TEST_07: fopen()/errno handling.", FSLITTLE_FOPEN_TEST_07), - Case("FSLITTLE_FOPEN_TEST_08: ferror()/clearerr()/errno handling.", FSLITTLE_FOPEN_TEST_08), - Case("FSLITTLE_FOPEN_TEST_09: ftell() handling.", FSLITTLE_FOPEN_TEST_09), - Case("FSLITTLE_FOPEN_TEST_10: remove() test.", FSLITTLE_FOPEN_TEST_10), - Case("FSLITTLE_FOPEN_TEST_11: rename().", FSLITTLE_FOPEN_TEST_11), - Case("FSLITTLE_FOPEN_TEST_12: opendir(), readdir(), closedir() test.", FSLITTLE_FOPEN_TEST_12), - Case("FSLITTLE_FOPEN_TEST_13: mkdir() test.", FSLITTLE_FOPEN_TEST_13), - Case("FSLITTLE_FOPEN_TEST_14: stat() test.", FSLITTLE_FOPEN_TEST_14), - Case("FSLITTLE_FOPEN_TEST_15: write/check n x 25kB data files.", FSLITTLE_FOPEN_TEST_15), + Case("FSLITTLE_FOPEN_TEST_06: fopen() with bad filenames (minimal).", FSLITTLE_FOPEN_TEST_06), + Case("FSLITTLE_FOPEN_TEST_07: fopen()/errno handling.", FSLITTLE_FOPEN_TEST_07), + Case("FSLITTLE_FOPEN_TEST_08: ferror()/clearerr()/errno handling.", FSLITTLE_FOPEN_TEST_08), + Case("FSLITTLE_FOPEN_TEST_09: ftell() handling.", FSLITTLE_FOPEN_TEST_09), + Case("FSLITTLE_FOPEN_TEST_10: remove() test.", FSLITTLE_FOPEN_TEST_10), + Case("FSLITTLE_FOPEN_TEST_11: rename().", FSLITTLE_FOPEN_TEST_11), + Case("FSLITTLE_FOPEN_TEST_12: opendir(), readdir(), closedir() test.", FSLITTLE_FOPEN_TEST_12), + Case("FSLITTLE_FOPEN_TEST_13: mkdir() test.", FSLITTLE_FOPEN_TEST_13), + Case("FSLITTLE_FOPEN_TEST_14: stat() test.", FSLITTLE_FOPEN_TEST_14), + Case("FSLITTLE_FOPEN_TEST_15: write/check n x 25kB data files.", FSLITTLE_FOPEN_TEST_15), }; diff --git a/components/storage/blockdevice/COMPONENT_FLASHIAP/mbed_lib.json b/components/storage/blockdevice/COMPONENT_FLASHIAP/mbed_lib.json new file mode 100644 index 0000000000..49b4cdb7b9 --- /dev/null +++ b/components/storage/blockdevice/COMPONENT_FLASHIAP/mbed_lib.json @@ -0,0 +1,19 @@ +{ + "name": "flashiap-block-device", + "config": { + "base-address": { + "help": "Base address for the block device on the external flash.", + "value": "0xFFFFFFFF" + }, + "size": { + "help": "Memory allocated for block device.", + "value": "0" + } + }, + "target_overrides": { + "REALTEK_RTL8195AM": { + "base-address": "0x1C0000", + "size": "0x40000" + } + } +} diff --git a/components/storage/blockdevice/COMPONENT_FLASHIAP/util/fslittle_test.c b/components/storage/blockdevice/COMPONENT_FLASHIAP/util/fslittle_test.c index 0cbe005202..8c2c22fb9d 100644 --- a/components/storage/blockdevice/COMPONENT_FLASHIAP/util/fslittle_test.c +++ b/components/storage/blockdevice/COMPONENT_FLASHIAP/util/fslittle_test.c @@ -61,7 +61,7 @@ const uint8_t fslittle_test_byte_data_table[FSLITTLE_TEST_BYTE_DATA_TABLE_SIZE] /* @brief test utility function to delete the file identified by filename */ -int32_t fslittle_test_delete(const char* filename) +int32_t fslittle_test_delete(const char *filename) { FSLITTLE_FENTRYLOG("%s:entered.\r\n", __func__); return remove(filename); @@ -74,18 +74,18 @@ int32_t fslittle_test_delete(const char* filename) * @param data data to store in file * @param len number of bytes of data present in the data buffer. */ -int32_t fslittle_test_create(const char* filename, const char* data, size_t len) +int32_t fslittle_test_create(const char *filename, const char *data, size_t len) { int32_t ret = -1; FILE *fp = NULL; FSLITTLE_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len); fp = fopen(filename, "w+"); - if(fp == NULL){ + if (fp == NULL) { return ret; } - ret = fwrite((const void*) data, len, 1, fp); - if(ret < 0){ + ret = fwrite((const void *) data, len, 1, fp); + if (ret < 0) { fclose(fp); return ret; } @@ -99,16 +99,15 @@ int32_t fslittle_test_create(const char* filename, const char* data, size_t len) * @param len length of kv name to generate * */ -int32_t fslittle_test_filename_gen(char* name, const size_t len) +int32_t fslittle_test_filename_gen(char *name, const size_t len) { size_t i; uint32_t pos = 0; - const char* buf = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!$-_@"; + const char *buf = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!$-_@"; const int buf_len = strlen(buf); FSLITTLE_FENTRYLOG("%s:entered\n", __func__); - for(i = 0; i < len; i++) - { + for (i = 0; i < len; i++) { pos = rand() % (buf_len); name[i] = buf[pos]; } diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp new file mode 100644 index 0000000000..b440042496 --- /dev/null +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -0,0 +1,1405 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * 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. + */ + +#include "QSPIFBlockDevice.h" +#include +#include "mbed_wait_api.h" + +#ifndef MBED_CONF_MBED_TRACE_ENABLE +#define MBED_CONF_MBED_TRACE_ENABLE 0 +#endif + +#include "mbed_trace.h" +#define TRACE_GROUP "QSPIF" + +using namespace mbed; + +/* Default QSPIF Parameters */ +/****************************/ +#define QSPIF_DEFAULT_READ_SIZE 1 +#define QSPIF_DEFAULT_PROG_SIZE 1 +#define QSPIF_DEFAULT_PAGE_SIZE 256 +#define QSPIF_DEFAULT_SE_SIZE 4096 +#define QSPI_MAX_STATUS_REGISTER_SIZE 3 +#ifndef UINT64_MAX +#define UINT64_MAX -1 +#endif +#define QSPI_NO_ADDRESS_COMMAND UINT64_MAX +// Status Register Bits +#define QSPIF_STATUS_BIT_WIP 0x1 //Write In Progress +#define QSPIF_STATUS_BIT_WEL 0x2 // Write Enable Latch + +/* SFDP Header Parsing */ +/***********************/ +#define QSPIF_SFDP_HEADER_SIZE 8 +#define QSPIF_PARAM_HEADER_SIZE 8 + +/* Basic Parameters Table Parsing */ +/**********************************/ +#define SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES 64 /* 16 DWORDS */ +//READ Instruction support according to BUS Configuration +#define QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE 2 +#define QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE 16 +#define QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE 27 +#define QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE 9 +#define QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE 11 +#define QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23 +#define QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15 +#define QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13 +#define QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE 40 +// Quad Enable Params +#define QSPIF_BASIC_PARAM_TABLE_QER_BYTE 58 +#define QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE 56 +// Erase Types Params +#define QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE 29 +#define QSPIF_BASIC_PARAM_ERASE_TYPE_2_BYTE 31 +#define QSPIF_BASIC_PARAM_ERASE_TYPE_3_BYTE 33 +#define QSPIF_BASIC_PARAM_ERASE_TYPE_4_BYTE 35 +#define QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE 28 +#define QSPIF_BASIC_PARAM_ERASE_TYPE_2_SIZE_BYTE 30 +#define QSPIF_BASIC_PARAM_ERASE_TYPE_3_SIZE_BYTE 32 +#define QSPIF_BASIC_PARAM_ERASE_TYPE_4_SIZE_BYTE 34 +#define QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1 + +// Erase Types Per Region BitMask +#define ERASE_BITMASK_TYPE4 0x08 +#define ERASE_BITMASK_TYPE1 0x01 +#define ERASE_BITMASK_NONE 0x00 +#define ERASE_BITMASK_ALL 0x0F + +#define IS_MEM_READY_MAX_RETRIES 10000 + +enum qspif_default_instructions { + QSPIF_NOP = 0x00, // No operation + QSPIF_PP = 0x02, // Page Program data + QSPIF_READ = 0x03, // Read data + QSPIF_SE = 0x20, // 4KB Sector Erase + QSPIF_SFDP = 0x5a, // Read SFDP + QSPIF_WRSR = 0x01, // Write Status/Configuration Register + QSPIF_WRDI = 0x04, // Write Disable + QSPIF_RDSR = 0x05, // Read Status Register + QSPIF_WREN = 0x06, // Write Enable + QSPIF_RSTEN = 0x66, // Reset Enable + QSPIF_RST = 0x99, // Reset + QSPIF_RDID = 0x9f, // Read Manufacturer and JDEC Device ID +}; + +// Local Function +static int local_math_power(int base, int exp); + +/* Init function to initialize Different Devices CS static list */ +static PinName *generate_initialized_active_qspif_csel_arr(); +// Static Members for different devices csel +// _devices_mutex is used to lock csel list - only one QSPIFBlockDevice instance per csel is allowed +SingletonPtr QSPIFBlockDevice::_devices_mutex; +int QSPIFBlockDevice::_number_of_active_qspif_flash_csel = 0; +PinName *QSPIFBlockDevice::_active_qspif_flash_csel_arr = generate_initialized_active_qspif_csel_arr(); + +/********* Public API Functions *********/ +/****************************************/ +QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel, + int clock_mode, int freq) + : _qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _csel(csel), _freq(freq), _device_size_bytes(0), + _init_ref_count(0), + _is_initialized(false) +{ + _unique_device_status = add_new_csel_instance(csel); + + if (_unique_device_status == 0) { + tr_info("Adding a new QSPIFBlockDevice csel: %d\n", (int)csel); + } else if (_unique_device_status == -1) { + tr_error("QSPIFBlockDevice with the same csel(%d) already exists\n", (int)csel); + } else { + tr_error("Too many different QSPIFBlockDevice devices - max allowed: %d\n", QSPIF_MAX_ACTIVE_FLASH_DEVICES); + } +} + +int QSPIFBlockDevice::init() +{ + if (_unique_device_status == 0) { + tr_debug("QSPIFBlockDevice csel: %d", (int)_csel); + } else if (_unique_device_status == -1) { + tr_error("QSPIFBlockDevice with the same csel(%d) already exists", (int)_csel); + return QSPIF_BD_ERROR_DEVICE_NOT_UNIQE; + } else { + tr_error("Too many different QSPIFBlockDevice devices - max allowed: %d", QSPIF_MAX_ACTIVE_FLASH_DEVICES); + return QSPIF_BD_ERROR_DEVICE_MAX_EXCEED; + } + + uint8_t vendor_device_ids[4]; + size_t data_length = 3; + int status = QSPIF_BD_ERROR_OK; + uint32_t basic_table_addr = 0; + size_t basic_table_size = 0; + uint32_t sector_map_table_addr = 0; + size_t sector_map_table_size = 0; + int qspi_status = QSPI_STATUS_OK; + + _mutex.lock(); + + if (!_is_initialized) { + _init_ref_count = 0; + } + + _init_ref_count++; + + if (_init_ref_count != 1) { + goto exit_point; + } + + //Initialize parameters + _min_common_erase_size = 0; + _regions_count = 1; + _region_erase_types_bitfield[0] = ERASE_BITMASK_NONE; + + //Default Bus Setup 1_1_1 with 0 dummy and mode cycles + _inst_width = QSPI_CFG_BUS_SINGLE; + _address_width = QSPI_CFG_BUS_SINGLE; + _address_size = QSPI_CFG_ADDR_SIZE_24; + _data_width = QSPI_CFG_BUS_SINGLE; + _dummy_and_mode_cycles = 0; + _write_register_inst = QSPIF_WRSR; + _read_register_inst = QSPIF_RDSR; + + + if (QSPI_STATUS_OK != _qspi_set_frequency(_freq)) { + tr_error("QSPI Set Frequency Failed"); + status = QSPIF_BD_ERROR_DEVICE_ERROR; + goto exit_point; + } + + // Soft Reset + if ( -1 == _reset_flash_mem()) { + tr_error("Init - Unable to initialize flash memory, tests failed"); + status = QSPIF_BD_ERROR_DEVICE_ERROR; + goto exit_point; + } else { + tr_info("Initialize flash memory OK"); + } + + /* Read Manufacturer ID (1byte), and Device ID (2bytes)*/ + qspi_status = _qspi_send_general_command(QSPIF_RDID, QSPI_NO_ADDRESS_COMMAND, NULL, 0, (char *)vendor_device_ids, + data_length); + if (qspi_status != QSPI_STATUS_OK) { + tr_error("Init - Read Vendor ID Failed"); + status = QSPIF_BD_ERROR_DEVICE_ERROR; + goto exit_point; + } + + tr_debug("Vendor device ID = 0x%x 0x%x 0x%x 0x%x \n", vendor_device_ids[0], + vendor_device_ids[1], vendor_device_ids[2], vendor_device_ids[3]); + switch (vendor_device_ids[0]) { + case 0xbf: + // SST devices come preset with block protection + // enabled for some regions, issue write disable instruction to clear + _set_write_enable(); + _qspi_send_general_command(QSPIF_WRDI, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0); + break; + } + + //Synchronize Device + if ( false == _is_mem_ready()) { + tr_error("Init - _is_mem_ready Failed"); + status = QSPIF_BD_ERROR_READY_FAILED; + goto exit_point; + } + + /**************************** Parse SFDP Header ***********************************/ + if ( 0 != _sfdp_parse_sfdp_headers(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) { + tr_error("Init - Parse SFDP Headers Failed"); + status = QSPIF_BD_ERROR_PARSING_FAILED; + goto exit_point; + } + + /**************************** Parse Basic Parameters Table ***********************************/ + if ( 0 != _sfdp_parse_basic_param_table(basic_table_addr, basic_table_size) ) { + tr_error("Init - Parse Basic Param Table Failed"); + status = QSPIF_BD_ERROR_PARSING_FAILED; + goto exit_point; + } + + /**************************** Parse Sector Map Table ***********************************/ + _region_size_bytes[0] = + _device_size_bytes; // If there's no region map, we have a single region sized the entire device size + _region_high_boundary[0] = _device_size_bytes - 1; + + if ( (sector_map_table_addr != 0) && (0 != sector_map_table_size) ) { + tr_info("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", sector_map_table_addr, + sector_map_table_size); + if (0 != _sfdp_parse_sector_map_table(sector_map_table_addr, sector_map_table_size) ) { + tr_error("Init - Parse Sector Map Table Failed"); + status = QSPIF_BD_ERROR_PARSING_FAILED; + goto exit_point; + } + } + + // Configure BUS Mode to 1_1_1 for all commands other than Read + _qspi_configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, + QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0); + + _is_initialized = true; + +exit_point: + _mutex.unlock(); + + return status; +} + +int QSPIFBlockDevice::deinit() +{ + int result = QSPIF_BD_ERROR_OK; + + _mutex.lock(); + + if (!_is_initialized) { + _init_ref_count = 0; + _mutex.unlock(); + return result; + } + + _init_ref_count--; + + if (_init_ref_count) { + _mutex.unlock(); + return result; + } + + // Disable Device for Writing + qspi_status_t status = _qspi_send_general_command(QSPIF_WRDI, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0); + if (status != QSPI_STATUS_OK) { + tr_error("Write Disable failed"); + result = QSPIF_BD_ERROR_DEVICE_ERROR; + } + + _is_initialized = false; + + _mutex.unlock(); + + if (_unique_device_status == 0) { + remove_csel_instance(_csel); + } + + return result; +} + +int QSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) +{ + int status = QSPIF_BD_ERROR_OK; + tr_info("Read Inst: 0x%xh", _read_instruction); + + _mutex.lock(); + + // Configure Bus for Reading + _qspi_configure_format(_inst_width, _address_width, _address_size, QSPI_CFG_BUS_SINGLE, + QSPI_CFG_ALT_SIZE_8, _data_width, _dummy_and_mode_cycles); + + if (QSPI_STATUS_OK != _qspi_send_read_command(_read_instruction, buffer, addr, size)) { + status = QSPIF_BD_ERROR_DEVICE_ERROR; + tr_error("Read Command failed"); + } + + // All commands other than Read use default 1-1-1 Bus mode (Program/Erase are constrained by flash memory performance less than that of the bus) + _qspi_configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, + QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0); + + _mutex.unlock(); + return status; + +} + +int QSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) +{ + qspi_status_t result = QSPI_STATUS_OK; + bool program_failed = false; + int status = QSPIF_BD_ERROR_OK; + uint32_t offset = 0; + uint32_t chunk = 0; + bd_size_t written_bytes = 0; + + tr_debug("Program - Buff: 0x%lxh, addr: %llu, size: %llu", (uint32_t)buffer, addr, size); + + while (size > 0) { + // Write on _page_size_bytes boundaries (Default 256 bytes a page) + offset = addr % _page_size_bytes; + chunk = (offset + size < _page_size_bytes) ? size : (_page_size_bytes - offset); + written_bytes = chunk; + + _mutex.lock(); + + //Send WREN + if (_set_write_enable() != 0) { + tr_error("Write Enabe failed"); + program_failed = true; + status = QSPIF_BD_ERROR_WREN_FAILED; + goto exit_point; + } + + result = _qspi_send_program_command(_prog_instruction, buffer, addr, &written_bytes); + if ( (result != QSPI_STATUS_OK) || (chunk != written_bytes) ) { + tr_error("Write failed"); + program_failed = true; + status = QSPIF_BD_ERROR_DEVICE_ERROR; + goto exit_point; + } + + buffer = static_cast(buffer) + chunk; + addr += chunk; + size -= chunk; + + if ( false == _is_mem_ready()) { + tr_error("Device not ready after write, failed"); + program_failed = true; + status = QSPIF_BD_ERROR_READY_FAILED; + goto exit_point; + } + _mutex.unlock(); + } + +exit_point: + if (program_failed) { + _mutex.unlock(); + } + + return status; +} + +int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) +{ + int type = 0; + uint32_t offset = 0; + uint32_t chunk = 4096; + unsigned int cur_erase_inst = _erase_instruction; + int size = (int)in_size; + bool erase_failed = false; + int status = QSPIF_BD_ERROR_OK; + // Find region of erased address + int region = _utils_find_addr_region(addr); + // Erase Types of selected region + uint8_t bitfield = _region_erase_types_bitfield[region]; + + tr_debug("Erase - addr: %llu, in_size: %llu", addr, in_size); + + if ((addr + in_size) > _device_size_bytes) { + tr_error("Erase exceeds flash device size"); + return QSPIF_BD_ERROR_INVALID_ERASE_PARAMS; + } + + if ( ((addr % get_erase_size(addr)) != 0 ) || (((addr + in_size) % get_erase_size(addr + in_size - 1)) != 0 ) ) { + tr_error("Invalid erase - unaligned address and size"); + return QSPIF_BD_ERROR_INVALID_ERASE_PARAMS; + } + + // For each iteration erase the largest section supported by current region + while (size > 0) { + // iterate to find next Largest erase type ( a. supported by region, b. smaller than size) + // find the matching instruction and erase size chunk for that type. + type = _utils_iterate_next_largest_erase_type(bitfield, size, (int)addr, _region_high_boundary[region]); + cur_erase_inst = _erase_type_inst_arr[type]; + offset = addr % _erase_type_size_arr[type]; + chunk = ( (offset + size) < _erase_type_size_arr[type]) ? size : (_erase_type_size_arr[type] - offset); + + tr_debug("Erase - addr: %llu, size:%d, Inst: 0x%xh, chunk: %lu ", + addr, size, cur_erase_inst, chunk); + tr_debug("Erase - Region: %d, Type:%d ", + region, type); + + _mutex.lock(); + + if (_set_write_enable() != 0) { + tr_error("QSPI Erase Device not ready - failed"); + erase_failed = true; + status = QSPIF_BD_ERROR_READY_FAILED; + goto exit_point; + } + + if (QSPI_STATUS_OK != _qspi_send_erase_command(cur_erase_inst, addr, size) ) { + tr_error("QSPI Erase command failed!"); + erase_failed = true; + status = QSPIF_BD_ERROR_DEVICE_ERROR; + goto exit_point; + } + + addr += chunk; + size -= chunk; + + if ( (size > 0) && (addr > _region_high_boundary[region]) ) { + // erase crossed to next region + region++; + bitfield = _region_erase_types_bitfield[region]; + } + + if ( false == _is_mem_ready()) { + tr_error("QSPI After Erase Device not ready - failed"); + erase_failed = true; + status = QSPIF_BD_ERROR_READY_FAILED; + goto exit_point; + } + + _mutex.unlock(); + } + +exit_point: + if (erase_failed) { + _mutex.unlock(); + } + + return status; +} + +bd_size_t QSPIFBlockDevice::get_read_size() const +{ + // Assuming all devices support 1byte read granularity + return QSPIF_DEFAULT_READ_SIZE; +} + +bd_size_t QSPIFBlockDevice::get_program_size() const +{ + // Assuming all devices support 1byte program granularity + return QSPIF_DEFAULT_PROG_SIZE; +} + +bd_size_t QSPIFBlockDevice::get_erase_size() const +{ + // return minimal erase size supported by all regions (0 if none exists) + return _min_common_erase_size; +} + +// Find minimal erase size supported by the region to which the address belongs to +bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr) +{ + // Find region of current address + int region = _utils_find_addr_region(addr); + + int min_region_erase_size = _min_common_erase_size; + int8_t type_mask = ERASE_BITMASK_TYPE1; + int i_ind = 0; + + + if (region != -1) { + type_mask = 0x01; + + for (i_ind = 0; i_ind < 4; i_ind++) { + // loop through erase types bitfield supported by region + if (_region_erase_types_bitfield[region] & type_mask) { + + min_region_erase_size = _erase_type_size_arr[i_ind]; + break; + } + type_mask = type_mask << 1; + } + + if (i_ind == 4) { + tr_error("No erase type was found for region addr"); + } + } + + return (bd_size_t)min_region_erase_size; +} + +bd_size_t QSPIFBlockDevice::size() const +{ + return _device_size_bytes; +} + +int QSPIFBlockDevice::get_erase_value() const +{ + return 0xFF; +} + +/********************************/ +/* Different Device Csel Mgmt */ +/********************************/ +static PinName *generate_initialized_active_qspif_csel_arr() +{ + PinName *init_arr = new PinName[QSPIF_MAX_ACTIVE_FLASH_DEVICES]; + for ( int i_ind = 0; i_ind < QSPIF_MAX_ACTIVE_FLASH_DEVICES; i_ind++ ) { + init_arr[i_ind] = NC; + } + return init_arr; +} + +int QSPIFBlockDevice::add_new_csel_instance(PinName csel) +{ + int status = 0; + _devices_mutex->lock(); + if (_number_of_active_qspif_flash_csel >= QSPIF_MAX_ACTIVE_FLASH_DEVICES ) { + status = -2; + goto exit_point; + } + + // verify the device is unique(no identical csel already exists) + for ( int i_ind = 0; i_ind < QSPIF_MAX_ACTIVE_FLASH_DEVICES; i_ind++ ) { + if (_active_qspif_flash_csel_arr[i_ind] == csel) { + status = -1; + goto exit_point; + } + } + + // Insert new csel into existing device list + for ( int i_ind = 0; i_ind < QSPIF_MAX_ACTIVE_FLASH_DEVICES; i_ind++ ) { + if (_active_qspif_flash_csel_arr[i_ind] == NC) { + _active_qspif_flash_csel_arr[i_ind] = csel; + break; + } + } + _number_of_active_qspif_flash_csel++; + +exit_point: + _devices_mutex->unlock(); + return status; +} + +int QSPIFBlockDevice::remove_csel_instance(PinName csel) +{ + int status = -1; + _devices_mutex->lock(); + // remove the csel from existing device list + for ( int i_ind = 0; i_ind < QSPIF_MAX_ACTIVE_FLASH_DEVICES; i_ind++ ) { + if (_active_qspif_flash_csel_arr[i_ind] == csel) { + _active_qspif_flash_csel_arr[i_ind] = NC; + if (_number_of_active_qspif_flash_csel > 0) { + _number_of_active_qspif_flash_csel--; + } + status = 0; + break; + } + } + _devices_mutex->unlock(); + return status; +} + +/*********************************************************/ +/********** SFDP Parsing and Detection Functions *********/ +/*********************************************************/ +int QSPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size) +{ + uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */ + uint32_t tmp_region_size = 0; + int i_ind = 0; + int prev_boundary = 0; + // Default set to all type bits 1-4 are common + int min_common_erase_type_bits = ERASE_BITMASK_ALL; + + + qspi_status_t status = _qspi_send_read_command(QSPIF_SFDP, (char *)sector_map_table, sector_map_table_addr /*address*/, + sector_map_table_size); + if (status != QSPI_STATUS_OK) { + tr_error("Init - Read SFDP First Table Failed"); + return -1; + } + + // Currently we support only Single Map Descriptor + if (! ( (sector_map_table[0] & 0x3) == 0x03 ) && (sector_map_table[1] == 0x0) ) { + tr_error("Sector Map - Supporting Only Single! Map Descriptor (not map commands)"); + return -1; + } + + _regions_count = sector_map_table[2] + 1; + if (_regions_count > QSPIF_MAX_REGIONS) { + tr_error("Supporting up to %d regions, current setup to %d regions - fail", + QSPIF_MAX_REGIONS, _regions_count); + return -1; + } + + // Loop through Regions and set for each one: size, supported erase types, high boundary offset + // Calculate minimum Common Erase Type for all Regions + for (i_ind = 0; i_ind < _regions_count; i_ind++) { + tmp_region_size = ((*((uint32_t *)§or_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32 + _region_size_bytes[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes; + _region_erase_types_bitfield[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4 + min_common_erase_type_bits &= _region_erase_types_bitfield[i_ind]; + _region_high_boundary[i_ind] = (_region_size_bytes[i_ind] - 1) + prev_boundary; + prev_boundary = _region_high_boundary[i_ind] + 1; + } + + // Calc minimum Common Erase Size from min_common_erase_type_bits + uint8_t type_mask = ERASE_BITMASK_TYPE1; + for (i_ind = 0; i_ind < 4; i_ind++) { + if (min_common_erase_type_bits & type_mask) { + _min_common_erase_size = _erase_type_size_arr[i_ind]; + break; + } + type_mask = type_mask << 1; + } + + if (i_ind == 4) { + // No common erase type was found between regions + _min_common_erase_size = 0; + } + + return 0; +} + +int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size) +{ + uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */ + + qspi_status_t status = _qspi_send_read_command(QSPIF_SFDP, (char *)param_table, basic_table_addr /*address*/, + basic_table_size); + if (status != QSPI_STATUS_OK) { + tr_error("Init - Read SFDP First Table Failed"); + return -1; + } + + // Check address size, currently only supports 3byte addresses + if ((param_table[2] & 0x4) != 0 || (param_table[7] & 0x80) != 0) { + tr_error("Init - verify 3byte addressing Failed"); + return -1; + } + + // Get device density (stored in bits - 1) + uint32_t density_bits = ( + (param_table[7] << 24) | + (param_table[6] << 16) | + (param_table[5] << 8 ) | + param_table[4] ); + _device_size_bytes = (density_bits + 1) / 8; + + // Set Default read/program/erase Instructions + _read_instruction = QSPIF_READ; + _prog_instruction = QSPIF_PP; + _erase_instruction = QSPIF_SE; + + _erase_instruction = _erase4k_inst; + + // Set Page Size (QSPI write must be done on Page limits) + _page_size_bytes = _sfdp_detect_page_size(param_table, basic_table_size); + + // Detect and Set Erase Types + bool shouldSetQuadEnable = false; + bool is_qpi_mode = false; + + _sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _erase4k_inst, _erase_type_inst_arr, + _erase_type_size_arr); + _erase_instruction = _erase4k_inst; + + // Detect and Set fastest Bus mode (default 1-1-1) + _sfdp_detect_best_bus_read_mode(param_table, basic_table_size, shouldSetQuadEnable, is_qpi_mode, _read_instruction); + if (true == shouldSetQuadEnable) { + _enable_fast_mdoe(); + // Set Quad Enable and QPI Bus modes if Supported + tr_info("Init - Setting Quad Enable"); + if (0 != _sfdp_set_quad_enabled(param_table)) { + tr_error("Device supports Quad bus, but Quad Enable Failed"); + return -1; + } + if (true == is_qpi_mode) { + tr_info("Init - Setting QPI mode"); + _sfdp_set_qpi_enabled(param_table); + } + } + return 0; +} + +int QSPIFBlockDevice::_sfdp_parse_sfdp_headers(uint32_t& basic_table_addr, size_t& basic_table_size, + uint32_t& sector_map_table_addr, size_t& sector_map_table_size) +{ + uint8_t sfdp_header[QSPIF_SFDP_HEADER_SIZE]; + uint8_t param_header[QSPIF_PARAM_HEADER_SIZE]; + size_t data_length = QSPIF_SFDP_HEADER_SIZE; + bd_addr_t addr = 0x0; + + // Set 1-1-1 bus mode for SFDP header parsing + _qspi_configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, + QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8); + + qspi_status_t status = _qspi_send_read_command(QSPIF_SFDP, (char *)sfdp_header, addr /*address*/, data_length); + if (status != QSPI_STATUS_OK) { + tr_error("Init - Read SFDP Failed"); + return -1; + } + + // Verify SFDP signature for sanity + // Also check that major/minor version is acceptable + if (!(memcmp(&sfdp_header[0], "SFDP", 4) == 0 && sfdp_header[5] == 1)) { + tr_error("Init - _verify SFDP signature and version Failed"); + return -1; + } else { + tr_info("Init - verified SFDP Signature and version Successfully"); + } + + // Discover Number of Parameter Headers + int number_of_param_headers = (int)(sfdp_header[6]) + 1; + tr_debug("Number of Param Headers: %d", number_of_param_headers); + + + addr += QSPIF_SFDP_HEADER_SIZE; + data_length = QSPIF_PARAM_HEADER_SIZE; + + // Loop over Param Headers and parse them (currently supported Basic Param Table and Sector Region Map Table) + for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) { + + status = _qspi_send_read_command(QSPIF_SFDP, (char *)param_header, addr, data_length); + if (status != QSPI_STATUS_OK) { + tr_error("Init - Read Param Table %d Failed", i_ind + 1); + return -1; + } + + // The SFDP spec indicates the standard table is always at offset 0 + // in the parameter headers, we check just to be safe + if (param_header[2] != 1) { + tr_error("Param Table %d - Major Version should be 1!", i_ind + 1); + return -1; + } + + if ((param_header[0] == 0) && (param_header[7] == 0xFF)) { + // Found Basic Params Table: LSB=0x00, MSB=0xFF + tr_debug("Found Basic Param Table at Table: %d", i_ind + 1); + basic_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) ); + // Supporting up to 64 Bytes Table (16 DWORDS) + basic_table_size = ((param_header[3] * 4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[3] * 4) : 64; + + } else if ((param_header[0] == 81) && (param_header[7] == 0xFF)) { + // Found Sector Map Table: LSB=0x81, MSB=0xFF + tr_debug("Found Sector Map Table at Table: %d", i_ind + 1); + sector_map_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) ); + sector_map_table_size = param_header[3] * 4; + + } + addr += QSPIF_PARAM_HEADER_SIZE; + + } + return 0; +} + +int QSPIFBlockDevice::_sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr) +{ + uint8_t config_reg[1]; + + // QPI 4-4-4 Enable Procedure is specified in 5 Bits + uint8_t en_seq_444_value = ( ((basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE] & 0xF0) >> 4) | (( + basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE + 1] & 0x01) << 4 )); + + switch (en_seq_444_value) { + case 1: + case 2: + tr_debug("_sfdp_set_qpi_enabled - send command 38h"); + if (QSPI_STATUS_OK != _qspi_send_general_command(0x38, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0)) { + tr_error("_sfdp_set_qpi_enabled - send command 38h Failed"); + } + break; + + case 4: + tr_debug("_sfdp_set_qpi_enabled - send command 35h"); + if (QSPI_STATUS_OK != _qspi_send_general_command(0x35, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0)) { + tr_error("_sfdp_set_qpi_enabled - send command 35h Failed"); + } + break; + + case 8: + tr_debug("_sfdp_set_qpi_enabled - set config bit 6 and send command 71h"); + if (QSPI_STATUS_OK != _qspi_send_general_command(0x65, 0x800003, NULL, 0, (char *)config_reg, 1)) { + tr_error("_sfdp_set_qpi_enabled - set config bit 6 command 65h Failed"); + } + config_reg[0] |= 0x40; //Set Bit 6 + if (QSPI_STATUS_OK != _qspi_send_general_command(0x71, 0x800003, NULL, 0, (char *)config_reg, 1)) { + tr_error("_sfdp_set_qpi_enabled - send command 71h Failed"); + } + break; + + case 16: + tr_debug("_sfdp_set_qpi_enabled - reset config bits 0-7 and send command 61h"); + if (QSPI_STATUS_OK != _qspi_send_general_command(0x65, QSPI_NO_ADDRESS_COMMAND, NULL, 0, (char *)config_reg, 1)) { + tr_error("_sfdp_set_qpi_enabled - send command 65h Failed"); + } + config_reg[0] &= 0x7F; //Reset Bit 7 of CR + if (QSPI_STATUS_OK != _qspi_send_general_command(0x61, QSPI_NO_ADDRESS_COMMAND, NULL, 0, (char *)config_reg, 1)) { + tr_error("_sfdp_set_qpi_enabled - send command 61 Failed"); + } + break; + + default: + tr_warning("_sfdp_set_qpi_enabled - Unsuported En Seq 444 configuration"); + break; + } + return 0; +} + + + +int QSPIFBlockDevice::_sfdp_set_quad_enabled(uint8_t *basic_param_table_ptr) +{ + int sr_read_size = QSPI_MAX_STATUS_REGISTER_SIZE; + int sr_write_size = QSPI_MAX_STATUS_REGISTER_SIZE; + + char status_reg_setup[QSPI_MAX_STATUS_REGISTER_SIZE] = {0}; + char status_reg[QSPI_MAX_STATUS_REGISTER_SIZE] = {0}; + + // QUAD Enable procedure is specified by 3 bits + uint8_t qer_value = (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_QER_BYTE] & 0x70) >> 4; + + + switch (qer_value) { + case 0: + tr_debug("Device Does not Have a QE Bit, continue based on Read Inst"); + return 0; + + case 1: + case 4: + status_reg_setup[1] = 0x02; //Bit 1 of Status Reg 2 + tr_debug("Setting QE Bit, Bit 1 of Status Reg 2"); + break; + + case 2: + status_reg_setup[0] = 0x40; // Bit 6 of Status Reg 1 + sr_write_size = 1; + tr_debug("Setting QE Bit, Bit 6 of Status Reg 1"); + break; + + case 3: + status_reg_setup[0] = 0x80; // Bit 7 of Status Reg 1 + sr_write_size = 1; + _write_register_inst = 0x3E; + _read_register_inst = 0x3F; + tr_debug("Setting QE Bit, Bit 7 of Status Reg 1"); + break; + case 5: + status_reg_setup[1] = 0x2; // Bit 1 of status Reg 2 + _read_register_inst = 0x35; + sr_read_size = 1; + tr_debug("Setting QE Bit, Bit 1 of Status Reg 2 -special read command"); + break; + default: + tr_warning("_setQuadEnable - Unsuported QER configuration"); + break; + } + + // Configure BUS Mode to 1_1_1 for all commands other than Read + _qspi_configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, + QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0); + + // Read Status Register + if (QSPI_STATUS_OK == _qspi_send_general_command(_read_register_inst, QSPI_NO_ADDRESS_COMMAND, NULL, 0, + status_reg, + sr_read_size) ) { // store received values in status_value + tr_debug("Reading Status Register Success: value = 0x%x", (int)status_reg[0]); + } else { + tr_error("Reading Status Register failed"); + return -1; + } + + // Set Bits for Quad Enable + for (int i = 0; i < QSPI_MAX_STATUS_REGISTER_SIZE; i++) { + status_reg[i] |= status_reg_setup[i]; + } + + // Write new Status Register Setup + if (_set_write_enable() != 0) { + tr_error("Write Enabe failed"); + return -1; + } + + if (QSPI_STATUS_OK == _qspi_send_general_command(_write_register_inst, QSPI_NO_ADDRESS_COMMAND, (char *)status_reg, + sr_write_size, NULL, + 0) ) { // Write QE to status_register + tr_debug("_setQuadEnable - Writing Status Register Success: value = 0x%x", + (int)status_reg[0]); + } else { + tr_error("_setQuadEnable - Writing Status Register failed"); + return -1; + } + + if ( false == _is_mem_ready()) { + tr_error("Device not ready after write, failed"); + return -1; + } + + + // For Debug + memset(status_reg, 0, QSPI_MAX_STATUS_REGISTER_SIZE); + if (QSPI_STATUS_OK == _qspi_send_general_command(_read_register_inst, QSPI_NO_ADDRESS_COMMAND, NULL, 0, + (char *)status_reg, + sr_read_size) ) { // store received values in status_value + tr_debug("Reading Status Register Success: value = 0x%x", (int)status_reg[0]); + } else { + tr_error("Reading Status Register failed"); + return -1; + } + + return 0; +} + +int QSPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size) +{ + unsigned int page_size = QSPIF_DEFAULT_PAGE_SIZE; + + if (basic_param_table_size > QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE) { + // Page Size is specified by 4 Bits (N), calculated by 2^N + int page_to_power_size = ( (int)basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4; + page_size = local_math_power(2, page_to_power_size); + tr_debug("Detected Page Size: %d", page_size); + } else { + tr_debug("Using Default Page Size: %d", page_size); + } + return page_size; +} + +int QSPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, + unsigned int& erase4k_inst, + unsigned int *erase_type_inst_arr, unsigned int *erase_type_size_arr) +{ + erase4k_inst = 0xff; + bool found_4Kerase_type = false; + uint8_t bitfield = 0x01; + + // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K + erase4k_inst = basic_param_table_ptr[QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE]; + + if (basic_param_table_size > QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE) { + // Loop Erase Types 1-4 + for (int i_ind = 0; i_ind < 4; i_ind++) { + erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type + erase_type_size_arr[i_ind] = local_math_power(2, + basic_param_table_ptr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N + tr_info("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), erase_type_inst_arr[i_ind], + erase_type_size_arr[i_ind]); + if (erase_type_size_arr[i_ind] > 1) { + // if size==1 type is not supported + erase_type_inst_arr[i_ind] = basic_param_table_ptr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind]; + + if ((erase_type_size_arr[i_ind] < _min_common_erase_size) || (_min_common_erase_size == 0) ) { + //Set default minimal common erase for singal region + _min_common_erase_size = erase_type_size_arr[i_ind]; + } + + // SFDP standard requires 4K Erase type to exist and its instruction to be identical to legacy field erase instruction + if (erase_type_size_arr[i_ind] == 4096) { + found_4Kerase_type = true; + if (erase4k_inst != erase_type_inst_arr[i_ind]) { + //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table + erase4k_inst = erase_type_inst_arr[i_ind]; + tr_warning("_detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K"); + + } + } + _region_erase_types_bitfield[0] |= bitfield; // If there's no region map, set region "0" types bitfield as defualt; + } + + tr_info("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), erase_type_inst_arr[i_ind], + erase_type_size_arr[i_ind]); + bitfield = bitfield << 1; + } + } + + if (false == found_4Kerase_type) { + tr_warning("Couldn't find Erase Type for 4KB size"); + } + return 0; +} + +int QSPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, + bool& set_quad_enable, + bool& is_qpi_mode, unsigned int& read_inst) +{ + set_quad_enable = false; + is_qpi_mode = false; + uint8_t examined_byte; + + do { // compound statement is the loop body + + if (basic_param_table_size > QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE) { + examined_byte = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE]; + + if (examined_byte & 0x10) { + // QPI 4-4-4 Supported + read_inst = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE]; + set_quad_enable = true; + is_qpi_mode = true; + _dummy_and_mode_cycles = (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE - 1] >> 5) + + (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE - 1] & 0x1F); + tr_debug("Read Bus Mode set to 4-4-4, Instruction: 0x%xh", _read_instruction); + //_inst_width = QSPI_CFG_BUS_QUAD; + _address_width = QSPI_CFG_BUS_QUAD; + _data_width = QSPI_CFG_BUS_QUAD; + + break; + } + } + + + examined_byte = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE]; + if (examined_byte & 0x40) { + // Fast Read 1-4-4 Supported + read_inst = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE]; + set_quad_enable = true; + // dummy cycles + mode cycles = Dummy Cycles + _dummy_and_mode_cycles = (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE - 1] >> 5) + + (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE - 1] & 0x1F); + _address_width = QSPI_CFG_BUS_QUAD; + _data_width = QSPI_CFG_BUS_QUAD; + tr_debug("Read Bus Mode set to 1-4-4, Instruction: 0x%xh", _read_instruction); + break; + } + + if (examined_byte & 0x80) { + // Fast Read 1-1-4 Supported + read_inst = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE]; + set_quad_enable = true; + _dummy_and_mode_cycles = (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE - 1] >> 5) + + (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE - 1] & 0x1F); + _data_width = QSPI_CFG_BUS_QUAD; + tr_debug("Read Bus Mode set to 1-1-4, Instruction: 0x%xh", _read_instruction); + break; + } + examined_byte = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE]; + if (examined_byte & 0x01) { + // Fast Read 2-2-2 Supported + read_inst = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE]; + _dummy_and_mode_cycles = (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] >> 5) + + (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] & 0x1F); + _address_width = QSPI_CFG_BUS_DUAL; + _data_width = QSPI_CFG_BUS_DUAL; + tr_info("Read Bus Mode set to 2-2-2, Instruction: 0x%xh", _read_instruction); + break; + } + + examined_byte = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE]; + if (examined_byte & 0x20) { + // Fast Read 1-2-2 Supported + read_inst = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE]; + _dummy_and_mode_cycles = (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE - 1] >> 5) + + (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE - 1] & 0x1F); + _address_width = QSPI_CFG_BUS_DUAL; + _data_width = QSPI_CFG_BUS_DUAL; + tr_debug("Read Bus Mode set to 1-2-2, Instruction: 0x%xh", _read_instruction); + break; + } + if (examined_byte & 0x01) { + // Fast Read 1-1-2 Supported + read_inst = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE]; + _dummy_and_mode_cycles = (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE - 1] >> 5) + + (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE - 1] & 0x1F); + _data_width = QSPI_CFG_BUS_DUAL; + tr_debug("Read Bus Mode set to 1-1-2, Instruction: 0x%xh", _read_instruction); + break; + } + tr_debug("Read Bus Mode set to 1-1-1, Instruction: 0x%xh", _read_instruction); + } while (false); + + return 0; +} + +int QSPIFBlockDevice::_reset_flash_mem() +{ + // Perform Soft Reset of the Device prior to initialization + int status = 0; + char status_value[QSPI_MAX_STATUS_REGISTER_SIZE] = {0}; + tr_info("_reset_flash_mem:"); + //Read the Status Register from device + if (QSPI_STATUS_OK == _qspi_send_general_command(QSPIF_RDSR, QSPI_NO_ADDRESS_COMMAND, NULL, 0, status_value, + QSPI_MAX_STATUS_REGISTER_SIZE) ) { // store received values in status_value + tr_debug("Reading Status Register Success: value = 0x%x", (int)status_value[0]); + } else { + tr_error("Reading Status Register failed: value = 0x%x", (int)status_value[0]); + status = -1; + } + + if (0 == status) { + //Send Reset Enable + if (QSPI_STATUS_OK == _qspi_send_general_command(QSPIF_RSTEN, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, + 0) ) { // store received values in status_value + tr_debug("Sending RSTEN Success"); + } else { + tr_error("Sending RSTEN failed"); + status = -1; + } + + + if (0 == status) { + //Send Reset + if (QSPI_STATUS_OK == _qspi_send_general_command(QSPIF_RST, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, + 0)) { // store received values in status_value + tr_debug("Sending RST Success"); + } else { + tr_error("Sending RST failed"); + status = -1; + } + + _is_mem_ready(); + } + } + + return status; +} + +bool QSPIFBlockDevice::_is_mem_ready() +{ + // Check Status Register Busy Bit to Verify the Device isn't Busy + char status_value[QSPI_MAX_STATUS_REGISTER_SIZE]; + int retries = 0; + bool mem_ready = true; + + do { + wait_ms(1); + retries++; + //Read the Status Register from device + memset(status_value, 0xFF, QSPI_MAX_STATUS_REGISTER_SIZE); + if (QSPI_STATUS_OK != _qspi_send_general_command(QSPIF_RDSR, QSPI_NO_ADDRESS_COMMAND, NULL, 0, status_value, + QSPI_MAX_STATUS_REGISTER_SIZE)) { // store received values in status_value + tr_error("Reading Status Register failed"); + } + } while ( (status_value[0] & QSPIF_STATUS_BIT_WIP) != 0 && retries < IS_MEM_READY_MAX_RETRIES ); + + if ((status_value[0] & QSPIF_STATUS_BIT_WIP) != 0) { + tr_error("_is_mem_ready FALSE: status value = 0x%x ", (int)status_value[0]); + mem_ready = false; + } + return mem_ready; +} + +int QSPIFBlockDevice::_set_write_enable() +{ + // Check Status Register Busy Bit to Verify the Device isn't Busy + char status_value[QSPI_MAX_STATUS_REGISTER_SIZE]; + int status = -1; + + do { + if (QSPI_STATUS_OK != _qspi_send_general_command(QSPIF_WREN, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0)) { + tr_error("Sending WREN command FAILED"); + break; + } + + if ( false == _is_mem_ready()) { + tr_error("Device not ready, write failed"); + break; + } + + memset(status_value, 0, QSPI_MAX_STATUS_REGISTER_SIZE); + if (QSPI_STATUS_OK != _qspi_send_general_command(QSPIF_RDSR, QSPI_NO_ADDRESS_COMMAND, NULL, 0, status_value, + QSPI_MAX_STATUS_REGISTER_SIZE)) { // store received values in status_value + tr_error("Reading Status Register failed"); + break; + } + + if ((status_value[0] & QSPIF_STATUS_BIT_WEL) == 0) { + tr_error("_set_write_enable failed"); + break; + } + status = 0; + } while (false); + return status; +} + +int QSPIFBlockDevice::_enable_fast_mdoe() +{ + char status_reg[QSPI_MAX_STATUS_REGISTER_SIZE] = {0}; + unsigned int read_conf_register_inst = 0x15; + char status_reg_qer_setup[QSPI_MAX_STATUS_REGISTER_SIZE] = {0}; + + status_reg_qer_setup[2] = 0x2; // Bit 1 of config Reg 2 + + // Configure BUS Mode to 1_1_1 for all commands other than Read + _qspi_configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, + QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0); + + // Read Status Register + if (QSPI_STATUS_OK == _qspi_send_general_command(read_conf_register_inst, QSPI_NO_ADDRESS_COMMAND, NULL, 0, + &status_reg[1], + QSPI_MAX_STATUS_REGISTER_SIZE - 1) ) { // store received values in status_value + tr_debug("Reading Config Register Success: value = 0x%x", (int)status_reg[2]); + } else { + tr_error("Reading Config Register failed"); + return -1; + } + + // Set Bits for Quad Enable + for (int i = 0; i < QSPI_MAX_STATUS_REGISTER_SIZE; i++) { + status_reg[i] |= status_reg_qer_setup[i]; + } + + // Write new Status Register Setup + if (_set_write_enable() != 0) { + tr_error("Write Enabe failed"); + return -1; + } + + if (QSPI_STATUS_OK == _qspi_send_general_command(_write_register_inst, QSPI_NO_ADDRESS_COMMAND, status_reg, + QSPI_MAX_STATUS_REGISTER_SIZE, NULL, + 0) ) { // Write Fast mode bit to status_register + tr_debug("fast mode enable - Writing Config Register Success: value = 0x%x", + (int)status_reg[2]); + } else { + tr_error("fast mode enable - Writing Config Register failed"); + return -1; + } + + if ( false == _is_mem_ready()) { + tr_error("Device not ready after write, failed"); + return -1; + } + + // For Debug + memset(status_reg, 0, QSPI_MAX_STATUS_REGISTER_SIZE); + if (QSPI_STATUS_OK == _qspi_send_general_command(read_conf_register_inst, QSPI_NO_ADDRESS_COMMAND, NULL, 0, + &status_reg[1], + QSPI_MAX_STATUS_REGISTER_SIZE - 1) ) { // store received values in status_value + tr_debug("Verifying Config Register Success: value = 0x%x", (int)status_reg[2]); + } else { + tr_error("Verifying Config Register failed"); + return -1; + } + + return 0; +} + +/*********************************************/ +/************* Utility Functions *************/ +/*********************************************/ +int QSPIFBlockDevice::_utils_find_addr_region(bd_size_t offset) +{ + //Find the region to which the given offset belong to + if ((offset > _device_size_bytes) || (_regions_count == 0)) { + return -1; + } + + if (_regions_count == 1) { + return 0; + } + + for (int i_ind = _regions_count - 2; i_ind >= 0; i_ind--) { + + if (offset > _region_high_boundary[i_ind]) { + return (i_ind + 1); + } + } + return -1; + +} + +int QSPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t& bitfield, int size, int offset, int boundry) +{ + // Iterate on all supported Erase Types of the Region to which the offset belong to. + // Iterates from highest type to lowest + uint8_t type_mask = ERASE_BITMASK_TYPE4; + int i_ind = 0; + int largest_erase_type = 0; + for (i_ind = 3; i_ind >= 0; i_ind--) { + if (bitfield & type_mask) { + largest_erase_type = i_ind; + if ( (size > (int)(_erase_type_size_arr[largest_erase_type])) && + ((boundry - offset) > (int)(_erase_type_size_arr[largest_erase_type])) ) { + break; + } else { + bitfield &= ~type_mask; + } + } + type_mask = type_mask >> 1; + } + + if (i_ind == 4) { + tr_error("No erase type was found for current region addr"); + } + return largest_erase_type; + +} + +/***************************************************/ +/*********** QSPI Driver API Functions *************/ +/***************************************************/ +qspi_status_t QSPIFBlockDevice::_qspi_set_frequency(int freq) +{ + return _qspi.set_frequency(freq); +} + +qspi_status_t QSPIFBlockDevice::_qspi_send_read_command(unsigned int read_inst, void *buffer, bd_addr_t addr, + bd_size_t size) +{ + // Send Read command to device driver + size_t buf_len = size; + + if (_qspi.read(read_inst, -1, (unsigned int )addr, (char *)buffer, &buf_len) != QSPI_STATUS_OK ) { + tr_error("Read failed"); + return QSPI_STATUS_ERROR; + } + + return QSPI_STATUS_OK; + +} + +qspi_status_t QSPIFBlockDevice::_qspi_send_program_command(unsigned int progInst, const void *buffer, bd_addr_t addr, + bd_size_t *size) +{ + // Send Program (write) command to device driver + qspi_status_t result = QSPI_STATUS_OK; + + result = _qspi.write(progInst, -1, addr, (char *)buffer, (size_t *)size); + if (result != QSPI_STATUS_OK) { + tr_error("QSPI Write failed"); + } + + return result; +} + +qspi_status_t QSPIFBlockDevice::_qspi_send_erase_command(unsigned int erase_inst, bd_addr_t addr, bd_size_t size) +{ + // Send Erase Instruction command to driver + qspi_status_t result = QSPI_STATUS_OK; + + tr_info("Inst: 0x%xh, addr: %llu, size: %llu", erase_inst, addr, size); + + result = _qspi.command_transfer(erase_inst, // command to send + (((int)addr) & 0x00FFF000), // Align addr to 4096 + NULL, // do not transmit + 0, // do not transmit + NULL, // just receive two bytes of data + 0); // store received values in status_value + + if (QSPI_STATUS_OK != result) { + tr_error("QSPI Erase failed"); + } + + return result; + +} + +qspi_status_t QSPIFBlockDevice::_qspi_send_general_command(unsigned int instruction, bd_addr_t addr, + const char *tx_buffer, + size_t tx_length, const char *rx_buffer, size_t rx_length) +{ + // Send a general command Instruction to driver + qspi_status_t status = _qspi.command_transfer(instruction, (int)addr, tx_buffer, tx_length, rx_buffer, rx_length); + + if (QSPI_STATUS_OK != status) { + tr_error("Sending Generic command: %x", instruction); + } + + return status; +} + +qspi_status_t QSPIFBlockDevice::_qspi_configure_format(qspi_bus_width_t inst_width, qspi_bus_width_t address_width, + qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width, + int dummy_cycles) +{ + // Configure QSPI driver Bus format + qspi_status_t status = _qspi.configure_format(inst_width, address_width, address_size, alt_width, alt_size, data_width, + dummy_cycles); + + return status; +} + +/*********************************************/ +/************** Local Functions **************/ +/*********************************************/ +static int local_math_power(int base, int exp) +{ + // Integer X^Y function, used to calculate size fields given in 2^N format + int result = 1; + while (exp) { + result *= base; + exp--; + } + return result; +} diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h new file mode 100644 index 0000000000..c01bd5a859 --- /dev/null +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h @@ -0,0 +1,361 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * 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. + */ +#ifndef MBED_QSPIF_BLOCK_DEVICE_H +#define MBED_QSPIF_BLOCK_DEVICE_H + +#include "QSPI.h" +#include "BlockDevice.h" + +/** Enum qspif standard error codes + * + * @enum qspif_bd_error + */ +enum qspif_bd_error { + QSPIF_BD_ERROR_OK = 0, /*!< no error */ + QSPIF_BD_ERROR_DEVICE_ERROR = BD_ERROR_DEVICE_ERROR, /*!< device specific error -4001 */ + QSPIF_BD_ERROR_PARSING_FAILED = -4002, /* SFDP Parsing failed */ + QSPIF_BD_ERROR_READY_FAILED = -4003, /* Wait for Mem Ready failed */ + QSPIF_BD_ERROR_WREN_FAILED = -4004, /* Write Enable Failed */ + QSPIF_BD_ERROR_INVALID_ERASE_PARAMS = -4005, /* Erase command not on sector aligned addresses or exceeds device size */ + QSPIF_BD_ERROR_DEVICE_NOT_UNIQE = -4006, /* Only one instance per csel is allowed */ + QSPIF_BD_ERROR_DEVICE_MAX_EXCEED = -4007 /* Max active QSPIF devices exceeded */ +}; + +/** Enum qspif polarity mode + * + * @enum qspif_polarity_mode + */ +enum qspif_polarity_mode { + QSPIF_POLARITY_MODE_0 = 0, /* CPOL=0, CPHA=0 */ + QSPIF_POLARITY_MODE_1 /* CPOL=1, CPHA=1 */ +}; + +#define QSPIF_MAX_REGIONS 10 +#define MAX_NUM_OF_ERASE_TYPES 4 +#define QSPIF_MAX_ACTIVE_FLASH_DEVICES 10 + +/** BlockDevice for SFDP based flash devices over QSPI bus + * + * @code + * // Here's an example using QSPI flash device on DISCO_L476VG target + * #include "mbed.h" + * #include "QSPIFBlockDevice.h" + * + * QSPIFBlockDevice block_device(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3, + * QSPI_FLASH1_SCK, QSPI_FLASH1_CSN, QSPIF_POLARITY_MODE_0, MBED_CONF_QSPIF_QSPI_FREQ); + * + * int main() + * { + * printf("QSPI SFDP Flash Block Device example\n"); + * + * // Initialize the SPI flash device and print the memory layout + * block_device.init(); + * bd_size_t sector_size_at_address_0 = block_device.get_erase_size(0); + * + * printf("QSPIF BD size: %llu\n", block_device.size()); + * printf("QSPIF BD read size: %llu\n", block_device.get_read_size()); + * printf("QSPIF BD program size: %llu\n", block_device.get_program_size()); + * printf("QSPIF BD erase size (at address 0): %llu\n", sector_size_at_address_0); + * + * // Write "Hello World!" to the first block + * char *buffer = (char *) malloc(sector_size_at_address_0); + * sprintf(buffer, "Hello World!\n"); + * block_device.erase(0, sector_size_at_address_0); + * block_device.program(buffer, 0, sector_size_at_address_0); + * + * // Read back what was stored + * block_device.read(buffer, 0, sector_size_at_address_0); + * printf("%s", buffer); + * + * // Deinitialize the device + * block_device.deinit(); + * } + * @endcode + */ +class QSPIFBlockDevice : public BlockDevice { +public: + /** Create QSPIFBlockDevice - An SFDP based Flash Block Device over QSPI bus + * + * @param io0 1st IO pin used for sending/receiving data during data phase of a transaction + * @param io1 2nd IO pin used for sending/receiving data during data phase of a transaction + * @param io2 3rd IO pin used for sending/receiving data during data phase of a transaction + * @param io3 4th IO pin used for sending/receiving data during data phase of a transaction + * @param sclk QSPI Clock pin + * @param csel QSPI chip select pin + * @param clock_mode specifies the QSPI Clock Polarity mode (QSPIF_POLARITY_MODE_0/QSPIF_POLARITY_MODE_1) + * default value = 0 + * @param freq Clock frequency of the QSPI bus (defaults to 40MHz) + * + */ + QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel, + int clock_mode, int freq = MBED_CONF_QSPIF_QSPI_FREQ); + + /** Initialize a block device + * + * @return QSPIF_BD_ERROR_OK(0) - success + * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed + * QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timedout + * QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables + */ + virtual int init(); + + /** Deinitialize a block device + * + * @return QSPIF_BD_ERROR_OK(0) - success + * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed + */ + virtual int deinit(); + + /** Desctruct QSPIFBlockDevie + */ + ~QSPIFBlockDevice() {deinit();} + + /** Read blocks from a block device + * + * @param buffer Buffer to write blocks to + * @param addr Address of block to begin reading from + * @param size Size to read in bytes, must be a multiple of read block size + * @return QSPIF_BD_ERROR_OK(0) - success + * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed + */ + virtual int read(void *buffer, bd_addr_t addr, bd_size_t size); + + /** Program blocks to a block device + * + * The blocks must have been erased prior to being programmed + * + * @param buffer Buffer of data to write to blocks + * @param addr Address of block to begin writing to + * @param size Size to write in bytes, must be a multiple of program block size + * @return QSPIF_BD_ERROR_OK(0) - success + * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed + * QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out + * QSPIF_BD_ERROR_WREN_FAILED - Write Enable failed + * QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables + */ + virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size); + + /** Erase blocks on a block device + * + * The state of an erased block is undefined until it has been programmed + * + * @param addr Address of block to begin erasing + * @param size Size to erase in bytes, must be a multiple of erase block size + * @return QSPIF_BD_ERROR_OK(0) - success + * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed + * QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out + * QSPIF_BD_ERROR_WREN_FAILED - Write Enable failed + * QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables + * QSPIF_BD_ERROR_INVALID_ERASE_PARAMS - Trying to erase unaligned address or size + */ + virtual int erase(bd_addr_t addr, bd_size_t size); + + /** Get the size of a readable block + * + * @return Size of a readable block in bytes + */ + virtual bd_size_t get_read_size() const; + + /** Get the size of a programable block + * + * @return Size of a program block size in bytes + * @note Must be a multiple of the read size + */ + virtual bd_size_t get_program_size() const; + + /** Get the size of a eraseable block + * + * @return Size of a minimal erase block, common to all regions, in bytes + * @note Must be a multiple of the program size + */ + virtual bd_size_t get_erase_size() const; + + /** Get the size of minimal eraseable sector size of given address + * + * @param addr Any address within block queried for erase sector size (can be any address within flash size offset) + * @return Size of minimal erase sector size, in given address region, in bytes + * @note Must be a multiple of the program size + */ + virtual bd_size_t get_erase_size(bd_addr_t addr); + + /** Get the value of storage byte after it was erased + * + * If get_erase_value returns a non-negative byte value, the underlying + * storage is set to that value when erased, and storage containing + * that value can be programmed without another erase. + * + * @return The value of storage when erased, or -1 if you can't + * rely on the value of erased storage + */ + virtual int get_erase_value() const; + + /** Get the total size of the underlying device + * + * @return Size of the underlying device in bytes + */ + virtual bd_size_t size() const; + +private: + // Internal functions + + + /********************************/ + /* Different Device Csel Mgmt */ + /********************************/ + // Add a new QSPI device CS to existing devices list. + // Only one QSPIFBlockDevice instance per CS is allowed + int add_new_csel_instance(PinName csel); + + // Remove device CS from existing device list upon destroying object (last deinit is called) + int remove_csel_instance(PinName csel); + + /********************************/ + /* Calls to QSPI Driver APIs */ + /********************************/ + // Send Program => Write command to Driver + qspi_status_t _qspi_send_program_command(unsigned int prog_instruction, const void *buffer, bd_addr_t addr, + bd_size_t *size); + + // Send Read command to Driver + qspi_status_t _qspi_send_read_command(unsigned int read_instruction, void *buffer, bd_addr_t addr, bd_size_t size); + + // Send Erase Instruction using command_transfer command to Driver + qspi_status_t _qspi_send_erase_command(unsigned int erase_instruction, bd_addr_t addr, bd_size_t size); + + // Send Generic command_transfer command to Driver + qspi_status_t _qspi_send_general_command(unsigned int instruction_int, bd_addr_t addr, const char *tx_buffer, + size_t tx_length, const char *rx_buffer, size_t rx_length); + + // Send Bus configure_format command to Driver + qspi_status_t _qspi_configure_format(qspi_bus_width_t inst_width, qspi_bus_width_t address_width, + qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width, + int dummy_cycles); + + // Send set_frequency command to Driver + qspi_status_t _qspi_set_frequency(int freq); + + /*********************************/ + /* Flash Configuration Functions */ + /*********************************/ + // Soft Reset Flash Memory + int _reset_flash_mem(); + + // Configure Write Enable in Status Register + int _set_write_enable(); + + // Wait on status register until write not-in-progress + bool _is_mem_ready(); + + // Enable Fast Mode - for flash chips with low power default + int _enable_fast_mdoe(); + + /****************************************/ + /* SFDP Detection and Parsing Functions */ + /****************************************/ + // Parse SFDP Headers and retrieve Basic Param and Sector Map Tables (if exist) + int _sfdp_parse_sfdp_headers(uint32_t& basic_table_addr, size_t& basic_table_size, + uint32_t& sector_map_table_addr, size_t& sector_map_table_size); + + // Parse and Detect required Basic Parameters from Table + int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size); + + // Parse and read information required by Regions Secotr Map + int _sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size); + + // Detect fastest read Bus mode supported by device + int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, bool& set_quad_enable, + bool& is_qpi_mode, unsigned int& read_inst); + + // Enable Quad mode if supported (1-1-4, 1-4-4, 4-4-4 bus modes) + int _sfdp_set_quad_enabled(uint8_t *basic_param_table_ptr); + + // Enable QPI mode (4-4-4) is supported + int _sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr); + + // Set Page size for program + int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size); + + // Detect all supported erase types + int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, + unsigned int& erase4k_inst, + unsigned int *erase_type_inst_arr, unsigned int *erase_type_size_arr); + + /***********************/ + /* Utilities Functions */ + /***********************/ + // Find the region to which the given offset belong to + int _utils_find_addr_region(bd_size_t offset); + + // Iterate on all supported Erase Types of the Region to which the offset belong to. + // Iterates from highest type to lowest + int _utils_iterate_next_largest_erase_type(uint8_t& bitfield, int size, int offset, int boundry); + +private: + // Internal Members + + // QSPI Driver Object + mbed::QSPI _qspi; + + // Static List of different QSPI based Flash devices csel that already exist + // Each QSPI Flash device csel can have only 1 QSPIFBlockDevice instance + // _devices_mutex is used to lock csel list - only one QSPIFBlockDevice instance per csel is allowed + static SingletonPtr _devices_mutex; + static int _number_of_active_qspif_flash_csel; + static PinName *_active_qspif_flash_csel_arr; + + int _unique_device_status; + PinName _csel; + + // Mutex is used to protect Flash device for some QSPI Driver commands that must be done sequentially with no other commands in between + // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready + PlatformMutex _mutex; + + // Command Instructions + unsigned int _read_instruction; + unsigned int _prog_instruction; + unsigned int _erase_instruction; + unsigned int _erase4k_inst; // Legacy 4K erase instruction (default 0x20h) + unsigned int _write_register_inst; // Write status/config register instruction may vary between chips + unsigned int _read_register_inst; // Read status/config register instruction may vary between chips + + // Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size) + unsigned int _erase_type_inst_arr[MAX_NUM_OF_ERASE_TYPES]; + unsigned int _erase_type_size_arr[MAX_NUM_OF_ERASE_TYPES]; + + // Sector Regions Map + int _regions_count; //number of regions + int _region_size_bytes[QSPIF_MAX_REGIONS]; //regions size in bytes + bd_size_t _region_high_boundary[QSPIF_MAX_REGIONS]; //region high address offset boundary + //Each Region can support a bit combination of any of the 4 Erase Types + uint8_t _region_erase_types_bitfield[QSPIF_MAX_REGIONS]; + unsigned int _min_common_erase_size; // minimal common erase size for all regions (0 if none exists) + + unsigned int _page_size_bytes; // Page size - 256 Bytes default + int _freq; + bd_size_t _device_size_bytes; + + // Bus speed configuration + qspi_bus_width_t _inst_width; //Bus width for Instruction phase + qspi_bus_width_t _address_width; //Bus width for Address phase + qspi_address_size_t _address_size; // number of bytes for address + qspi_bus_width_t _data_width; //Bus width for Data phase + int _dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Current Bus Mode + + uint32_t _init_ref_count; + bool _is_initialized; +}; + +#endif diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/TESTS/block_device/qspif/main.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/TESTS/block_device/qspif/main.cpp new file mode 100644 index 0000000000..dba0d77658 --- /dev/null +++ b/components/storage/blockdevice/COMPONENT_QSPIF/TESTS/block_device/qspif/main.cpp @@ -0,0 +1,292 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * 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. + */ +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "QSPIFBlockDevice.h" +#include "mbed_trace.h" +#include "rtos/Thread.h" +#include + +using namespace utest::v1; + +#define TEST_BLOCK_COUNT 10 +#define TEST_ERROR_MASK 16 +#define QSPIF_TEST_NUM_OF_THREADS 5 + +const struct { + const char *name; + bd_size_t (BlockDevice::*method)() const; +} ATTRS[] = { + {"read size", &BlockDevice::get_read_size}, + {"program size", &BlockDevice::get_program_size}, + {"erase size", &BlockDevice::get_erase_size}, + {"total size", &BlockDevice::size}, +}; + +static SingletonPtr _mutex; + + +// Mutex is protecting rand() per srand for buffer writing and verification. +// Mutex is also protecting printouts for clear logs. +// Mutex is NOT protecting Block Device actions: erase/program/read - which is the purpose of the multithreaded test! +void basic_erase_program_read_test(QSPIFBlockDevice& blockD, bd_size_t block_size, uint8_t *write_block, + uint8_t *read_block, unsigned addrwidth) +{ + int err = 0; + _mutex->lock(); + // Find a random block + bd_addr_t block = (rand() * block_size) % blockD.size(); + + // Use next random number as temporary seed to keep + // the address progressing in the pseudorandom sequence + unsigned seed = rand(); + + // Fill with random sequence + srand(seed); + for (bd_size_t i_ind = 0; i_ind < block_size; i_ind++) { + write_block[i_ind] = 0xff & rand(); + } + // Write, sync, and read the block + utest_printf("\ntest %0*llx:%llu...", addrwidth, block, block_size); + _mutex->unlock(); + + err = blockD.erase(block, block_size); + TEST_ASSERT_EQUAL(0, err); + + err = blockD.program(write_block, block, block_size); + TEST_ASSERT_EQUAL(0, err); + + err = blockD.read(read_block, block, block_size); + TEST_ASSERT_EQUAL(0, err); + + _mutex->lock(); + // Check that the data was unmodified + srand(seed); + int val_rand; + for (bd_size_t i_ind = 0; i_ind < block_size; i_ind++) { + val_rand = rand(); + if ( (0xff & val_rand) != read_block[i_ind] ) { + utest_printf("\n Assert Failed Buf Read - block:size: %llx:%llu \n", block, block_size); + utest_printf("\n pos: %llu, exp: %02x, act: %02x, wrt: %02x \n", i_ind, (0xff & val_rand), read_block[i_ind], + write_block[i_ind] ); + } + TEST_ASSERT_EQUAL(0xff & val_rand, read_block[i_ind]); + } + _mutex->unlock(); +} + +void test_qspif_random_program_read_erase() +{ + utest_printf("\nTest Random Program Read Erase Starts..\n"); + + QSPIFBlockDevice blockD(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3, + QSPI_FLASH1_SCK, QSPI_FLASH1_CSN, QSPIF_POLARITY_MODE_0, MBED_CONF_QSPIF_QSPI_FREQ); + + int err = blockD.init(); + TEST_ASSERT_EQUAL(0, err); + + for (unsigned atr = 0; atr < sizeof(ATTRS) / sizeof(ATTRS[0]); atr++) { + static const char *prefixes[] = {"", "k", "M", "G"}; + for (int i_ind = 3; i_ind >= 0; i_ind--) { + bd_size_t size = (blockD.*ATTRS[atr].method)(); + if (size >= (1ULL << 10 * i_ind)) { + utest_printf("%s: %llu%sbytes (%llubytes)\n", + ATTRS[atr].name, size >> 10 * i_ind, prefixes[i_ind], size); + break; + } + } + } + + bd_size_t block_size = blockD.get_erase_size(); + unsigned addrwidth = ceil(log(float(blockD.size() - 1)) / log(float(16))) + 1; + + uint8_t *write_block = new (std::nothrow) uint8_t[block_size]; + uint8_t *read_block = new (std::nothrow) uint8_t[block_size]; + if (!write_block || !read_block) { + utest_printf("\n Not enough memory for test"); + goto end; + } + + for (int b = 0; b < TEST_BLOCK_COUNT; b++) { + basic_erase_program_read_test(blockD, block_size, write_block, read_block, addrwidth); + } + + err = blockD.deinit(); + TEST_ASSERT_EQUAL(0, err); + +end: + delete[] write_block; + delete[] read_block; +} + +void test_qspif_unaligned_erase() +{ + + utest_printf("\nTest Unaligned Erase Starts..\n"); + + QSPIFBlockDevice blockD(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3, + QSPI_FLASH1_SCK, QSPI_FLASH1_CSN, QSPIF_POLARITY_MODE_0, MBED_CONF_QSPIF_QSPI_FREQ); + + int err = blockD.init(); + TEST_ASSERT_EQUAL(0, err); + + for (unsigned atr = 0; atr < sizeof(ATTRS) / sizeof(ATTRS[0]); atr++) { + static const char *prefixes[] = {"", "k", "M", "G"}; + for (int i_ind = 3; i_ind >= 0; i_ind--) { + bd_size_t size = (blockD.*ATTRS[atr].method)(); + if (size >= (1ULL << 10 * i_ind)) { + utest_printf("%s: %llu%sbytes (%llubytes)\n", + ATTRS[atr].name, size >> 10 * i_ind, prefixes[i_ind], size); + break; + } + } + } + + bd_addr_t addr = 0; + bd_size_t sector_erase_size = blockD.get_erase_size(addr); + unsigned addrwidth = ceil(log(float(blockD.size() - 1)) / log(float(16))) + 1; + + utest_printf("\ntest %0*llx:%llu...", addrwidth, addr, sector_erase_size); + + //unaligned start address + addr += 1; + err = blockD.erase(addr, sector_erase_size - 1); + TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_INVALID_ERASE_PARAMS, err); + + err = blockD.erase(addr, sector_erase_size); + TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_INVALID_ERASE_PARAMS, err); + + err = blockD.erase(addr, 1); + TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_INVALID_ERASE_PARAMS, err); + + //unaligned end address + addr = 0; + + err = blockD.erase(addr, 1); + TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_INVALID_ERASE_PARAMS, err); + + err = blockD.erase(addr, sector_erase_size + 1); + TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_INVALID_ERASE_PARAMS, err); + + //erase size exceeds flash device size + err = blockD.erase(addr, blockD.size() + 1); + TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_INVALID_ERASE_PARAMS, err); + + // Valid erase + err = blockD.erase(addr, sector_erase_size); + TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_OK, err); + + err = blockD.deinit(); + TEST_ASSERT_EQUAL(0, err); +} + + + +static void test_qspif_thread_job(void *vBlockD/*, int thread_num*/) +{ + static int thread_num = 0; + thread_num++; + QSPIFBlockDevice *blockD = (QSPIFBlockDevice *)vBlockD; + utest_printf("\n Thread %d Started \n", thread_num); + + bd_size_t block_size = blockD->get_erase_size(); + unsigned addrwidth = ceil(log(float(blockD->size() - 1)) / log(float(16))) + 1; + + uint8_t *write_block = new (std::nothrow) uint8_t[block_size]; + uint8_t *read_block = new (std::nothrow) uint8_t[block_size]; + if (!write_block || !read_block ) { + utest_printf("\n Not enough memory for test"); + goto end; + } + + for (int b = 0; b < TEST_BLOCK_COUNT; b++) { + basic_erase_program_read_test((*blockD), block_size, write_block, read_block, addrwidth); + } + +end: + delete[] write_block; + delete[] read_block; +} + +void test_qspif_multi_threads() +{ + + utest_printf("\nTest Multi Threaded Erase/Program/Read Starts..\n"); + + QSPIFBlockDevice blockD(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3, + QSPI_FLASH1_SCK, QSPI_FLASH1_CSN, QSPIF_POLARITY_MODE_0, MBED_CONF_QSPIF_QSPI_FREQ); + + int err = blockD.init(); + TEST_ASSERT_EQUAL(0, err); + + for (unsigned atr = 0; atr < sizeof(ATTRS) / sizeof(ATTRS[0]); atr++) { + static const char *prefixes[] = {"", "k", "M", "G"}; + for (int i_ind = 3; i_ind >= 0; i_ind--) { + bd_size_t size = (blockD.*ATTRS[atr].method)(); + if (size >= (1ULL << 10 * i_ind)) { + utest_printf("%s: %llu%sbytes (%llubytes)\n", + ATTRS[atr].name, size >> 10 * i_ind, prefixes[i_ind], size); + break; + } + } + } + + rtos::Thread qspif_bd_thread[QSPIF_TEST_NUM_OF_THREADS]; + + osStatus threadStatus; + int i_ind; + + for (i_ind = 0; i_ind < QSPIF_TEST_NUM_OF_THREADS; i_ind++) { + threadStatus = qspif_bd_thread[i_ind].start(test_qspif_thread_job, (void *)&blockD); + if (threadStatus != 0) { + utest_printf("\n Thread %d Start Failed!", i_ind + 1); + } + } + + for (i_ind = 0; i_ind < QSPIF_TEST_NUM_OF_THREADS; i_ind++) { + qspif_bd_thread[i_ind].join(); + } + + err = blockD.deinit(); + TEST_ASSERT_EQUAL(0, err); +} + + + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(60, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Testing unaligned erase blocks", test_qspif_unaligned_erase), + Case("Testing read write random blocks", test_qspif_random_program_read_erase), + Case("Testing Multi Threads Erase Program Read", test_qspif_multi_threads) +}; + +Specification specification(test_setup, cases); + + +int main() +{ + mbed_trace_init(); + utest_printf("MAIN STARTS\n"); + return !Harness::run(specification); +} diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/mbed_lib.json b/components/storage/blockdevice/COMPONENT_QSPIF/mbed_lib.json new file mode 100644 index 0000000000..b611268a5a --- /dev/null +++ b/components/storage/blockdevice/COMPONENT_QSPIF/mbed_lib.json @@ -0,0 +1,30 @@ +{ +"name": "qspif", + "config": { + "QSPI_IO0": "QSPI_FLASH1_IO0", + "QSPI_IO1": "QSPI_FLASH1_IO1", + "QSPI_IO2": "QSPI_FLASH1_IO2", + "QSPI_IO3": "QSPI_FLASH1_IO3", + "QSPI_SCK": "QSPI_FLASH1_SCK", + "QSPI_CSN": "QSPI_FLASH1_CSN", + "QSPI_POLARITY_MODE": 0, + "QSPI_FREQ": "40000000" + }, + "target_overrides": { + "DISCO_F413ZH": { + "QSPI_FREQ": "80000000" + }, + "DISCO_L475VG_IOT01A": { + "QSPI_FREQ": "8000000" + }, + "DISCO_L476VG": { + "QSPI_FREQ": "80000000" + }, + "DISCO_F469NI": { + "QSPI_FREQ": "80000000" + }, + "NRF52840_DK": { + "QSPI_FREQ": "32000000" + } + } +} diff --git a/components/storage/blockdevice/COMPONENT_RSPIF/SPIFReducedBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_RSPIF/SPIFReducedBlockDevice.cpp new file mode 100644 index 0000000000..5f0eb2d369 --- /dev/null +++ b/components/storage/blockdevice/COMPONENT_RSPIF/SPIFReducedBlockDevice.cpp @@ -0,0 +1,344 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * 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. + */ +#include "SPIFReducedBlockDevice.h" +#include "mbed_wait_api.h" + +// Read/write/erase sizes +#define SPIF_READ_SIZE 1 +#define SPIF_PROG_SIZE 1 +#define SPIF_SE_SIZE 4096 +#define SPIF_TIMEOUT 10000 + +// Debug available +#define SPIF_DEBUG 0 + +// Legacy SFDP Instruction Table. +enum ops { + SPIF_NOP = 0x00, // No operation + SPIF_READ = 0x03, // Read data + SPIF_PROG = 0x02, // Program data + SPIF_SE = 0x20, // 4KB Sector Erase + SPIF_CE = 0xc7, // Chip Erase + SPIF_SFDP = 0x5a, // Read SFDP + SPIF_WREN = 0x06, // Write Enable + SPIF_WRDI = 0x04, // Write Disable + SPIF_RDSR = 0x05, // Read Status Register + SPIF_RDID = 0x9f, // Read Manufacturer and JDEC Device ID +}; + +// Status register from RDSR +// [---------| wel | wip ] +// [- 6 -| 1 | 1 ] +#define SPIF_WEL 0x2 +#define SPIF_WIP 0x1 + + +SPIFReducedBlockDevice::SPIFReducedBlockDevice( + PinName mosi, PinName miso, PinName sclk, PinName cs, int freq) + : _spi(mosi, miso, sclk), _cs(cs), _size(0) +{ + _cs = 1; + _spi.frequency(freq); +} + +int SPIFReducedBlockDevice::init() +{ + // Check for vendor specific hacks, these should move into more general + // handling when possible. RDID is not used to verify a device is attached. + uint8_t id[3]; + _cmdread(SPIF_RDID, 0, 3, 0x0, id); + + switch (id[0]) { + case 0xbf: + // SST devices come preset with block protection + // enabled for some regions, issue gbpu instruction to clear + _wren(); + _cmdwrite(0x98, 0, 0, 0x0, NULL); + break; + } + + // Check that device is doing ok + int err = _sync(); + if (err) { + return BD_ERROR_DEVICE_ERROR; + } + + // Check JEDEC serial flash discoverable parameters for device + // specific info + uint8_t header[16]; + _cmdread(SPIF_SFDP, 4, 16, 0x0, header); + + // Verify SFDP signature for sanity + // Also check that major/minor version is acceptable + if (!(memcmp(&header[0], "SFDP", 4) == 0 && header[5] == 1)) { + return BD_ERROR_DEVICE_ERROR; + } + + // The SFDP spec indicates the standard table is always at offset 0 + // in the parameter headers, we check just to be safe + if (!(header[8] == 0 && header[10] == 1)) { + return BD_ERROR_DEVICE_ERROR; + } + + // Parameter table pointer, spi commands are BE, SFDP is LE, + // also sfdp command expects extra read wait byte + // header 12-14 3 bytes building the parameter table address + uint32_t table_addr = ( + (header[14] << 24) | + (header[13] << 16) | + (header[12] << 8 )); + + uint8_t table[8]; + _cmdread(SPIF_SFDP, 4, 8, table_addr, table); + + // Check erase size, currently only supports 4kbytes + if ((table[0] & 0x3) != 0x1 || table[1] != SPIF_SE) { + // First byte of table, bits 0 and 1 = 0x1 indicating 4 KB Erase is supported + // Second Byte of table = Sector Erase Command (0x20) + return BD_ERROR_DEVICE_ERROR; + } + + // Check address size, currently only supports 3byte addresses + if ((table[2] & 0x4) != 0 || (table[7] & 0x80) != 0) { + return BD_ERROR_DEVICE_ERROR; + } + + // Get device density, stored as size in bits - 1 + uint32_t density = ( + (table[7] << 24) | + (table[6] << 16) | + (table[5] << 8 ) | + (table[4] << 0 )); + // Table bytes 5-8 : Bits 0|30 indicate Flash Density (size) in bits (divide by 8 for Bytes) + _size = (density / 8) + 1; + + return 0; +} + +int SPIFReducedBlockDevice::deinit() +{ + // Latch write disable just to keep noise + // from changing the device + _cmdwrite(SPIF_WRDI, 0, 0, 0x0, NULL); + + return 0; +} + +void SPIFReducedBlockDevice::_cmdread( + uint8_t op, uint32_t addrc, uint32_t retc, + uint32_t addr, uint8_t *rets) +{ + _cs = 0; + _spi.write(op); + + for (uint32_t i = 0; i < addrc; i++) { + _spi.write(0xff & (addr >> 8 * (addrc - 1 - i))); + } + + for (uint32_t i = 0; i < retc; i++) { + rets[i] = _spi.write(0); + } + _cs = 1; + + if (SPIF_DEBUG) { + printf("spif <- %02x", op); + for (uint32_t i = 0; i < addrc; i++) { + if (i < addrc) { + printf("%02lx", 0xff & (addr >> 8 * (addrc - 1 - i))); + } else { + printf(" "); + } + } + printf(" "); + for (uint32_t i = 0; i < 16 && i < retc; i++) { + printf("%02x", rets[i]); + } + if (retc > 16) { + printf("..."); + } + printf("\n"); + } +} + +void SPIFReducedBlockDevice::_cmdwrite( + uint8_t op, uint32_t addrc, uint32_t argc, + uint32_t addr, const uint8_t *args) +{ + _cs = 0; + _spi.write(op); + + for (uint32_t i = 0; i < addrc; i++) { + _spi.write(0xff & (addr >> 8 * (addrc - 1 - i))); + } + + for (uint32_t i = 0; i < argc; i++) { + _spi.write(args[i]); + } + _cs = 1; + + if (SPIF_DEBUG) { + printf("spif -> %02x", op); + for (uint32_t i = 0; i < addrc; i++) { + if (i < addrc) { + printf("%02lx", 0xff & (addr >> 8 * (addrc - 1 - i))); + } else { + printf(" "); + } + } + printf(" "); + for (uint32_t i = 0; i < 16 && i < argc; i++) { + printf("%02x", args[i]); + } + if (argc > 16) { + printf("..."); + } + printf("\n"); + } +} + +int SPIFReducedBlockDevice::_sync() +{ + for (int i = 0; i < SPIF_TIMEOUT; i++) { + // Read status register until write not-in-progress + uint8_t status; + _cmdread(SPIF_RDSR, 0, 1, 0x0, &status); + + // Check WIP bit + if (!(status & SPIF_WIP)) { + return 0; + } + + wait_ms(1); + } + + return BD_ERROR_DEVICE_ERROR; +} + +int SPIFReducedBlockDevice::_wren() +{ + _cmdwrite(SPIF_WREN, 0, 0, 0x0, NULL); + + for (int i = 0; i < SPIF_TIMEOUT; i++) { + // Read status register until write latch is enabled + uint8_t status; + _cmdread(SPIF_RDSR, 0, 1, 0x0, &status); + + // Check WEL bit + if (status & SPIF_WEL) { + return 0; + } + + wait_ms(1); + } + + return BD_ERROR_DEVICE_ERROR; +} + +int SPIFReducedBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) +{ + // Check the address and size fit onto the chip. + MBED_ASSERT(is_valid_read(addr, size)); + + _cmdread(SPIF_READ, 3, size, addr, static_cast(buffer)); + return 0; +} + +int SPIFReducedBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) +{ + // Check the address and size fit onto the chip. + MBED_ASSERT(is_valid_program(addr, size)); + + while (size > 0) { + int err = _wren(); + if (err) { + return err; + } + + // Write up to 256 bytes a page + uint32_t off = addr % 256; + uint32_t chunk = (off + size < 256) ? size : (256 - off); + _cmdwrite(SPIF_PROG, 3, chunk, addr, static_cast(buffer)); + buffer = static_cast(buffer) + chunk; + addr += chunk; + size -= chunk; + + wait_ms(1); + + err = _sync(); + if (err) { + return err; + } + } + + return 0; +} + +int SPIFReducedBlockDevice::erase(bd_addr_t addr, bd_size_t size) +{ + // Check the address and size fit onto the chip. + MBED_ASSERT(is_valid_erase(addr, size)); + + while (size > 0) { + int err = _wren(); + if (err) { + return err; + } + + // Erase 4kbyte sectors + uint32_t chunk = 4096; + _cmdwrite(SPIF_SE, 3, 0, addr, NULL); + addr += chunk; + size -= chunk; + + err = _sync(); + if (err) { + return err; + } + } + + return 0; +} + +bd_size_t SPIFReducedBlockDevice::get_read_size() const +{ + return SPIF_READ_SIZE; +} + +bd_size_t SPIFReducedBlockDevice::get_program_size() const +{ + return SPIF_PROG_SIZE; +} + +bd_size_t SPIFReducedBlockDevice::get_erase_size() const +{ + return SPIF_SE_SIZE; +} + +bd_size_t SPIFReducedBlockDevice::get_erase_size(bd_addr_t addr) const +{ + return SPIF_SE_SIZE; +} + +int SPIFReducedBlockDevice::get_erase_value() const +{ + return 0xFF; +} + +bd_size_t SPIFReducedBlockDevice::size() const +{ + return _size; +} diff --git a/components/storage/blockdevice/COMPONENT_RSPIF/SPIFReducedBlockDevice.h b/components/storage/blockdevice/COMPONENT_RSPIF/SPIFReducedBlockDevice.h new file mode 100644 index 0000000000..2b83680672 --- /dev/null +++ b/components/storage/blockdevice/COMPONENT_RSPIF/SPIFReducedBlockDevice.h @@ -0,0 +1,174 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * 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. + */ +#ifndef MBED_RSPIF_BLOCK_DEVICE_H +#define MBED_RSPIF_BLOCK_DEVICE_H + +#include "SPI.h" +#include "DigitalOut.h" +#include "BlockDevice.h" + +/** Reduced BlockDevice for SPI based flash devices + * *Should only be used by Boot Loader* + * + * @code + * // Here's an example using the SPI flash device on K82F + * #include "mbed.h" + * #include "SPIFReducedBlockDevice.h" + * + * // Create flash device on SPI bus with PTE5 as chip select + * SPIFReducedBlockDevice rspif(PTE2, PTE4, PTE1, PTE5); + * + * int main() { + * printf("reduced spif test\n"); + * + * // Initialize the Reduced SPI flash device and print the memory layout + * rspif.init(); + * printf("rspif size: %llu\n", rspif.size()); + * printf("rspif read size: %llu\n", rspif.get_read_size()); + * printf("rspif program size: %llu\n", rspif.get_program_size()); + * printf("rspif erase size: %llu\n", rspif.get_erase_size()); + * + * // Write "Hello World!" to the first block + * char *buffer = (char*)malloc(rspif.get_erase_size()); + * sprintf(buffer, "Hello World!\n"); + * rspif.erase(0, rspif.get_erase_size()); + * rspif.program(buffer, 0, rspif.get_erase_size()); + * + * // Read back what was stored + * rspif.read(buffer, 0, rspif.get_erase_size()); + * printf("%s", buffer); + * + * // Deinitialize the device + * rspif.deinit(); + * } + * @endcode + */ +class SPIFReducedBlockDevice : public BlockDevice { +public: + /** Creates a SPIFReducedBlockDevice on a SPI bus specified by pins + * + * @param mosi SPI master out, slave in pin + * @param miso SPI master in, slave out pin + * @param sclk SPI clock pin + * @param csel SPI chip select pin + * @param freq Clock speed of the SPI bus (defaults to 40MHz) + */ + SPIFReducedBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName csel, int freq = 40000000); + + /** Initialize a block device + * + * @return 0 on success or a negative error code on failure + */ + virtual int init(); + + /** Deinitialize a block device + * + * @return 0 on success or a negative error code on failure + */ + virtual int deinit(); + + /** Read blocks from a block device + * + * @param buffer Buffer to write blocks to + * @param addr Address of block to begin reading from + * @param size Size to read in bytes, must be a multiple of read block size + * @return 0 on success, negative error code on failure + */ + virtual int read(void *buffer, bd_addr_t addr, bd_size_t size); + + /** Program blocks to a block device + * + * The blocks must have been erased prior to being programmed + * + * @param buffer Buffer of data to write to blocks + * @param addr Address of block to begin writing to + * @param size Size to write in bytes, must be a multiple of program block size + * @return 0 on success, negative error code on failure + */ + virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size); + + /** Erase blocks on a block device + * + * The state of an erased block is undefined until it has been programmed + * + * @param addr Address of block to begin erasing + * @param size Size to erase in bytes, must be a multiple of erase block size + * @return 0 on success, negative error code on failure + */ + virtual int erase(bd_addr_t addr, bd_size_t size); + + /** Get the size of a readable block + * + * @return Size of a readable block in bytes + */ + virtual bd_size_t get_read_size() const; + + /** Get the size of a programable block + * + * @return Size of a programable block in bytes + * @note Must be a multiple of the read size + */ + virtual bd_size_t get_program_size() const; + + /** Get the size of a eraseable block + * + * @return Size of a eraseable block in bytes + * @note Must be a multiple of the program size + */ + virtual bd_size_t get_erase_size() const; + + /** Get the size of a eraseable block + * + * @param addr Address of block to query erase size + * @return Size of a eraseable block in bytes + * @note Must be a multiple of the program size + */ + virtual bd_size_t get_erase_size(bd_addr_t addr) const; + + /** Get the value of storage byte after it was erased + * + * If get_erase_value returns a non-negative byte value, the underlying + * storage is set to that value when erased, and storage containing + * that value can be programmed without another erase. + * + * @return The value of storage when erased, or -1 if you can't + * rely on the value of erased storage + */ + virtual int get_erase_value() const; + + /** Get the total size of the underlying device + * + * @return Size of the underlying device in bytes + */ + virtual bd_size_t size() const; + +private: + // Master side hardware + mbed::SPI _spi; + mbed::DigitalOut _cs; + + // Device configuration discovered through sfdp + bd_size_t _size; + + // Internal functions + int _wren(); + int _sync(); + void _cmdread(uint8_t op, uint32_t addrc, uint32_t retc, + uint32_t addr, uint8_t *rets); + void _cmdwrite(uint8_t op, uint32_t addrc, uint32_t argc, + uint32_t addr, const uint8_t *args); +}; +#endif diff --git a/components/storage/blockdevice/COMPONENT_RSPIF/mbed_lib.json b/components/storage/blockdevice/COMPONENT_RSPIF/mbed_lib.json new file mode 100644 index 0000000000..11b5f7c53c --- /dev/null +++ b/components/storage/blockdevice/COMPONENT_RSPIF/mbed_lib.json @@ -0,0 +1,66 @@ +{ + "name": "rspif-driver", + "config": { + "SPI_MOSI": "NC", + "SPI_MISO": "NC", + "SPI_CLK": "NC", + "SPI_CS": "NC", + "SPI_FREQ": "40000000" + }, + "target_overrides": { + "K82F": { + "SPI_MOSI": "PTE2", + "SPI_MISO": "PTE4", + "SPI_CLK": "PTE1", + "SPI_CS": "PTE5" + }, + "LPC54114": { + "SPI_MOSI": "P0_20", + "SPI_MISO": "P0_18", + "SPI_CLK": "P0_19", + "SPI_CS": "P1_2" + }, + "NRF52840_DK": { + "SPI_MOSI": "p20", + "SPI_MISO": "p21", + "SPI_CLK": "p19", + "SPI_CS": "p17" + }, + "HEXIWEAR": { + "SPI_MOSI": "PTD6", + "SPI_MISO": "PTD7", + "SPI_CLK": "PTD5", + "SPI_CS": "PTD4" + }, + "MTB_UBLOX_ODIN_W2": { + "SPI_MOSI": "PE_14", + "SPI_MISO": "PE_13", + "SPI_CLK": "PE_12", + "SPI_CS": "PE_11" + }, + "MTB_ADV_WISE_1530": { + "SPI_MOSI": "PC_3", + "SPI_MISO": "PC_2", + "SPI_CLK": "PB_13", + "SPI_CS": "PC_12" + }, + "MTB_MXCHIP_EMW3166": { + "SPI_MOSI": "PB_15", + "SPI_MISO": "PB_14", + "SPI_CLK": "PB_13", + "SPI_CS": "PA_10" + }, + "MTB_USI_WM_BN_BM_22": { + "SPI_MOSI": "PC_3", + "SPI_MISO": "PC_2", + "SPI_CLK": "PB_13", + "SPI_CS": "PA_6" + }, + "MTB_ADV_WISE_1570": { + "SPI_MOSI": "PA_7", + "SPI_MISO": "PA_6", + "SPI_CLK": "PA_5", + "SPI_CS": "PB_12" + } + } +} diff --git a/components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.cpp index 18759dcc79..1bd5a773bb 100644 --- a/components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.cpp @@ -141,6 +141,10 @@ #include "SDBlockDevice.h" #include "platform/mbed_debug.h" #include "platform/mbed_wait_api.h" +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#include #include #ifndef MBED_CONF_SD_CMD_TIMEOUT @@ -240,9 +244,18 @@ #define SPI_READ_ERROR_ECC_C (0x1 << 2) /*!< Card ECC failed */ #define SPI_READ_ERROR_OFR (0x1 << 3) /*!< Out of Range */ +// Only HC block size is supported. Making this a static constant reduces code size. +const uint32_t SDBlockDevice::_block_size = BLOCK_SIZE_HC; + +#if MBED_CONF_SD_CRC_ENABLED SDBlockDevice::SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName cs, uint64_t hz, bool crc_on) : _sectors(0), _spi(mosi, miso, sclk), _cs(cs), _is_initialized(0), - _crc_on(crc_on), _init_ref_count(0), _crc16(0, 0, false, false) + _init_ref_count(0), _crc_on(crc_on), _crc16(0, 0, false, false) +#else +SDBlockDevice::SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName cs, uint64_t hz, bool crc_on) + : _sectors(0), _spi(mosi, miso, sclk), _cs(cs), _is_initialized(0), + _init_ref_count(0) +#endif { _cs = 1; _card_type = SDCARD_NONE; @@ -253,8 +266,6 @@ SDBlockDevice::SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName c _init_sck = MBED_CONF_SD_INIT_FREQUENCY; _transfer_sck = hz; - // Only HC block size is supported. - _block_size = BLOCK_SIZE_HC; _erase_size = BLOCK_SIZE_HC; } @@ -288,10 +299,12 @@ int SDBlockDevice::_initialise_card() return status; } +#if MBED_CONF_SD_CRC_ENABLED if (_crc_on) { // Enable CRC status = _cmd(CMD59_CRC_ON_OFF, _crc_on); } +#endif // Read OCR - CMD58 Response contains OCR register if (BD_ERROR_OK != (status = _cmd(CMD58_READ_OCR, 0x0, 0x0, &response))) { @@ -345,10 +358,15 @@ int SDBlockDevice::_initialise_card() debug_if(SD_DBG, "Card Initialized: Version 1.x Card\n"); } +#if MBED_CONF_SD_CRC_ENABLED if (!_crc_on) { // Disable CRC status = _cmd(CMD59_CRC_ON_OFF, _crc_on); } +#else + status = _cmd(CMD59_CRC_ON_OFF, 0); +#endif + return status; } @@ -386,7 +404,7 @@ int SDBlockDevice::init() // Set block length to 512 (CMD16) if (_cmd(CMD16_SET_BLOCKLEN, _block_size) != 0) { - debug_if(SD_DBG, "Set %d-byte block timed out\n", _block_size); + debug_if(SD_DBG, "Set %" PRIu32 "-byte block timed out\n", _block_size); unlock(); return BD_ERROR_DEVICE_ERROR; } @@ -444,7 +462,7 @@ int SDBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) uint8_t response; // Get block count - bd_addr_t blockCnt = size / _block_size; + size_t blockCnt = size / _block_size; // SDSC Card (CCS=0) uses byte unit address // SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit) @@ -514,7 +532,7 @@ int SDBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) uint8_t *buffer = static_cast(b); int status = BD_ERROR_OK; - bd_addr_t blockCnt = size / _block_size; + size_t blockCnt = size / _block_size; // SDSC Card (CCS=0) uses byte unit address // SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit) @@ -644,7 +662,6 @@ uint8_t SDBlockDevice::_cmd_spi(SDBlockDevice::cmdSupported cmd, uint32_t arg) { uint8_t response; char cmdPacket[PACKET_SIZE]; - uint32_t crc; // Prepare the command packet cmdPacket[0] = SPI_CMD(cmd); @@ -653,10 +670,14 @@ uint8_t SDBlockDevice::_cmd_spi(SDBlockDevice::cmdSupported cmd, uint32_t arg) cmdPacket[3] = (arg >> 8); cmdPacket[4] = (arg >> 0); +#if MBED_CONF_SD_CRC_ENABLED + uint32_t crc; if (_crc_on) { _crc7.compute((void *)cmdPacket, 5, &crc); cmdPacket[5] = (char)(crc | 0x01); - } else { + } else +#endif + { // CMD0 is executed in SD mode, hence should have correct CRC // CMD8 CRC verification is always enabled switch (cmd) { @@ -738,24 +759,24 @@ int SDBlockDevice::_cmd(SDBlockDevice::cmdSupported cmd, uint32_t arg, bool isAc // Process the response R1 : Exit on CRC/Illegal command error/No response if (R1_NO_RESPONSE == response) { _deselect(); - debug_if(SD_DBG, "No response CMD:%d response: 0x%x\n", cmd, response); + debug_if(SD_DBG, "No response CMD:%d response: 0x%" PRIx32 "\n", cmd, response); return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; // No device } if (response & R1_COM_CRC_ERROR) { _deselect(); - debug_if(SD_DBG, "CRC error CMD:%d response 0x%x \n", cmd, response); + debug_if(SD_DBG, "CRC error CMD:%d response 0x%" PRIx32 "\n", cmd, response); return SD_BLOCK_DEVICE_ERROR_CRC; // CRC error } if (response & R1_ILLEGAL_COMMAND) { _deselect(); - debug_if(SD_DBG, "Illegal command CMD:%d response 0x%x\n", cmd, response); + debug_if(SD_DBG, "Illegal command CMD:%d response 0x%" PRIx32 "\n", cmd, response); if (CMD8_SEND_IF_COND == cmd) { // Illegal command is for Ver1 or not SD Card _card_type = CARD_UNKNOWN; } return SD_BLOCK_DEVICE_ERROR_UNSUPPORTED; // Command not supported } - debug_if(_dbg, "CMD:%d \t arg:0x%x \t Response:0x%x \n", cmd, arg, response); + debug_if(_dbg, "CMD:%d \t arg:0x%" PRIx32 " \t Response:0x%" PRIx32 "\n", cmd, arg, response); // Set status for other errors if ((response & R1_ERASE_RESET) || (response & R1_ERASE_SEQUENCE_ERROR)) { status = SD_BLOCK_DEVICE_ERROR_ERASE; // Erase error @@ -775,7 +796,7 @@ int SDBlockDevice::_cmd(SDBlockDevice::cmdSupported cmd, uint32_t arg, bool isAc response |= (_spi.write(SPI_FILL_CHAR) << 16); response |= (_spi.write(SPI_FILL_CHAR) << 8); response |= _spi.write(SPI_FILL_CHAR); - debug_if(_dbg, "R3/R7: 0x%x \n", response); + debug_if(_dbg, "R3/R7: 0x%" PRIx32 "\n", response); break; case CMD12_STOP_TRANSMISSION: // Response R1b @@ -785,7 +806,7 @@ int SDBlockDevice::_cmd(SDBlockDevice::cmdSupported cmd, uint32_t arg, bool isAc case ACMD13_SD_STATUS: // Response R2 response = _spi.write(SPI_FILL_CHAR); - debug_if(_dbg, "R2: 0x%x \n", response); + debug_if(_dbg, "R2: 0x%" PRIx32 "\n", response); break; default: // Response R1 @@ -822,7 +843,7 @@ int SDBlockDevice::_cmd8() if ((BD_ERROR_OK == status) && (SDCARD_V2 == _card_type)) { // If check pattern is not matched, CMD8 communication is not valid if ((response & 0xFFF) != arg) { - debug_if(SD_DBG, "CMD8 Pattern mismatch 0x%x : 0x%x\n", arg, response); + debug_if(SD_DBG, "CMD8 Pattern mismatch 0x%" PRIx32 " : 0x%" PRIx32 "\n", arg, response); _card_type = CARD_UNKNOWN; status = SD_BLOCK_DEVICE_ERROR_UNUSABLE; } @@ -869,17 +890,19 @@ int SDBlockDevice::_read_bytes(uint8_t *buffer, uint32_t length) crc = (_spi.write(SPI_FILL_CHAR) << 8); crc |= _spi.write(SPI_FILL_CHAR); +#if MBED_CONF_SD_CRC_ENABLED if (_crc_on) { uint32_t crc_result; // Compute and verify checksum _crc16.compute((void *)buffer, length, &crc_result); if ((uint16_t)crc_result != crc) { - debug_if(SD_DBG, "_read_bytes: Invalid CRC received 0x%x result of computation 0x%x\n", - crc, crc_result); + debug_if(SD_DBG, "_read_bytes: Invalid CRC received 0x%" PRIx16 " result of computation 0x%" PRIx16 "\n", + crc, (uint16_t)crc_result); _deselect(); return SD_BLOCK_DEVICE_ERROR_CRC; } } +#endif _deselect(); return 0; @@ -892,7 +915,6 @@ int SDBlockDevice::_read(uint8_t *buffer, uint32_t length) // read until start byte (0xFE) if (false == _wait_token(SPI_START_BLOCK)) { debug_if(SD_DBG, "Read timeout\n"); - _deselect(); return SD_BLOCK_DEVICE_ERROR_NO_RESPONSE; } @@ -903,16 +925,18 @@ int SDBlockDevice::_read(uint8_t *buffer, uint32_t length) crc = (_spi.write(SPI_FILL_CHAR) << 8); crc |= _spi.write(SPI_FILL_CHAR); +#if MBED_CONF_SD_CRC_ENABLED if (_crc_on) { uint32_t crc_result; // Compute and verify checksum _crc16.compute((void *)buffer, length, &crc_result); if ((uint16_t)crc_result != crc) { - debug_if(SD_DBG, "_read_bytes: Invalid CRC received 0x%x result of computation 0x%x\n", - crc, crc_result); + debug_if(SD_DBG, "_read_bytes: Invalid CRC received 0x%" PRIx16 " result of computation 0x%" PRIx16 "\n", + crc, (uint16_t)crc_result); return SD_BLOCK_DEVICE_ERROR_CRC; } } +#endif return 0; } @@ -929,10 +953,12 @@ uint8_t SDBlockDevice::_write(const uint8_t *buffer, uint8_t token, uint32_t len // write the data _spi.write((char *)buffer, length, NULL, 0); +#if MBED_CONF_SD_CRC_ENABLED if (_crc_on) { // Compute CRC _crc16.compute((void *)buffer, length, &crc); } +#endif // write the checksum CRC16 _spi.write(crc >> 8); @@ -992,11 +1018,11 @@ bd_size_t SDBlockDevice::_sd_sectors() block_len = 1 << read_bl_len; // BLOCK_LEN = 2^READ_BL_LEN mult = 1 << (c_size_mult + 2); // MULT = 2^C_SIZE_MULT+2 (C_SIZE_MULT < 8) blocknr = (c_size + 1) * mult; // BLOCKNR = (C_SIZE+1) * MULT - capacity = blocknr * block_len; // memory capacity = BLOCKNR * BLOCK_LEN + capacity = (bd_size_t) blocknr * block_len; // memory capacity = BLOCKNR * BLOCK_LEN blocks = capacity / _block_size; - debug_if(SD_DBG, "Standard Capacity: c_size: %d \n", c_size); - debug_if(SD_DBG, "Sectors: 0x%x : %llu\n", blocks, blocks); - debug_if(SD_DBG, "Capacity: 0x%x : %llu MB\n", capacity, (capacity / (1024U * 1024U))); + debug_if(SD_DBG, "Standard Capacity: c_size: %" PRIu32 " \n", c_size); + debug_if(SD_DBG, "Sectors: 0x%" PRIx64 " : %" PRIu64 "\n", blocks, blocks); + debug_if(SD_DBG, "Capacity: 0x%" PRIx64 " : %" PRIu64 " MB\n", capacity, (capacity / (1024U * 1024U))); // ERASE_BLK_EN = 1: Erase in multiple of 512 bytes supported if (ext_bits(csd, 46, 46)) { @@ -1010,9 +1036,9 @@ bd_size_t SDBlockDevice::_sd_sectors() case 1: hc_c_size = ext_bits(csd, 69, 48); // device size : C_SIZE : [69:48] blocks = (hc_c_size + 1) << 10; // block count = C_SIZE+1) * 1K byte (512B is block size) - debug_if(SD_DBG, "SDHC/SDXC Card: hc_c_size: %d \n", hc_c_size); - debug_if(SD_DBG, "Sectors: 0x%x : %llu\n", blocks, blocks); - debug_if(SD_DBG, "Capacity: %llu MB\n", (blocks / (2048U))); + debug_if(SD_DBG, "SDHC/SDXC Card: hc_c_size: %" PRIu32 " \n", hc_c_size); + debug_if(SD_DBG, "Sectors: 0x%" PRIx64 "x : %" PRIu64 "\n", blocks, blocks); + debug_if(SD_DBG, "Capacity: %" PRIu64 " MB\n", (blocks / (2048U))); // ERASE_BLK_EN is fixed to 1, which means host can erase one or multiple of 512 bytes. _erase_size = BLOCK_SIZE_HC; break; diff --git a/components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.h b/components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.h index 352ab634dc..9b4db1c54f 100644 --- a/components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.h @@ -214,15 +214,17 @@ private: } PlatformMutex _mutex; - bd_size_t _block_size; - bd_size_t _erase_size; + static const uint32_t _block_size; + uint32_t _erase_size; bool _is_initialized; bool _dbg; - bool _crc_on; uint32_t _init_ref_count; +#if MBED_CONF_SD_CRC_ENABLED + bool _crc_on; mbed::MbedCRC _crc7; mbed::MbedCRC _crc16; +#endif }; #endif /* DEVICE_SPI */ diff --git a/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/dirs/main.cpp b/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/dirs/main.cpp index 3e7e6e895d..412a3379df 100644 --- a/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/dirs/main.cpp +++ b/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/dirs/main.cpp @@ -171,7 +171,7 @@ void dir_file_check(char *list[], uint32_t elements) TEST_ASSERT(1); } break; - } else if ( i == elements) { + } else if (i == elements) { TEST_ASSERT_EQUAL(0, res); } } diff --git a/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/files/main.cpp b/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/files/main.cpp index 78c3faa262..fcbdb15d19 100644 --- a/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/files/main.cpp +++ b/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/files/main.cpp @@ -294,7 +294,7 @@ void test_dir_check() TEST_ASSERT(1); } break; - } else if ( i == numFiles) { + } else if (i == numFiles) { TEST_ASSERT_EQUAL(0, res); } } diff --git a/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/fopen/fopen.cpp b/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/fopen/fopen.cpp index 05638f92b3..b1d64d9a87 100644 --- a/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/fopen/fopen.cpp +++ b/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/fopen/fopen.cpp @@ -65,7 +65,7 @@ using namespace utest::v1; * "DEVICE_SPI": 1, * "FSFAT_SDCARD_INSTALLED": 1 * }, - * <<< lines removed >>> + * <<< lines removed >>> */ #if defined(DEVICE_SPI) && ( defined(MBED_CONF_APP_FSFAT_SDCARD_INSTALLED) || (MBED_CONF_SD_FSFAT_SDCARD_INSTALLED)) @@ -155,7 +155,7 @@ static int32_t fsfat_filepath_split(char *filepath, char *parts[], uint32_t num) char *z = filepath; while (i < num && *z != '\0') { - if (*z == '/' ) { + if (*z == '/') { *z = '\0'; parts[i] = ++z; i++; @@ -200,7 +200,7 @@ int32_t fsfat_filepath_remove_all(char *filepath) while (pos != fpathbuf) { /* If the remaining file path is the mount point path then finish as the mount point cannot be removed */ if (strlen(fpathbuf) == strlen(FSFAT_FOPEN_TEST_MOUNT_PT_PATH)) { - if ( strncmp(fpathbuf, FSFAT_FOPEN_TEST_MOUNT_PT_PATH, strlen(fpathbuf)) == 0) { + if (strncmp(fpathbuf, FSFAT_FOPEN_TEST_MOUNT_PT_PATH, strlen(fpathbuf)) == 0) { break; } } @@ -621,7 +621,7 @@ control_t fsfat_fopen_test_05(const size_t call_count) while (node->code != fsfat_fopen_kv_name_ascii_table_code_sentinel_g) { /* loop over range */ for (j = node->code; j < (node + 1)->code; j++) { - if ( (j >= 48 && j <= 57) || (j >= 65 && j <= 90) || (j >= 97 && j <= 122)) { + if ((j >= 48 && j <= 57) || (j >= 65 && j <= 90) || (j >= 97 && j <= 122)) { FSFAT_DBGLOG("%s: skipping alpha-numeric ascii character code %d (%c).\n", __func__, (int) j, (char) j); continue; } @@ -775,10 +775,10 @@ control_t fsfat_fopen_test_06(const size_t call_count) /** @brief test for errno reporting on a failed fopen()call * - * This test does the following: - * - tries to open a file that does not exist for reading, and checks that a NULL pointer is returned. - * - checks that errno is not 0 as there is an error. - * - checks that ferror() returns 1 indicating an error exists. + * This test does the following: + * - tries to open a file that does not exist for reading, and checks that a NULL pointer is returned. + * - checks that errno is not 0 as there is an error. + * - checks that ferror() returns 1 indicating an error exists. * * Note: see NOTE_1 below. * diff --git a/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/parallel/main.cpp b/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/parallel/main.cpp index 0edb10b05a..39e1aa4476 100644 --- a/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/parallel/main.cpp +++ b/components/storage/blockdevice/COMPONENT_SD/TESTS/filesystem/parallel/main.cpp @@ -97,7 +97,7 @@ void test_file_tests() TEST_ASSERT_EQUAL(0, res); } -void write_file_data (char count) +void write_file_data(char count) { char filename[10]; @@ -125,7 +125,7 @@ void write_file_data (char count) TEST_ASSERT_EQUAL(0, res); } -void read_file_data (char count) +void read_file_data(char count) { char filename[10]; uint8_t rbuffer[MBED_TEST_BUFFER]; @@ -154,6 +154,9 @@ void read_file_data (char count) void test_thread_access_test() { + char *dummy = new (std::nothrow) char[OS_STACK_SIZE * MBED_THREAD_COUNT]; + delete[] dummy; + TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test"); Thread *data[MBED_THREAD_COUNT]; int res = bd.init(); diff --git a/components/storage/blockdevice/COMPONENT_SD/config/mbed_lib.json b/components/storage/blockdevice/COMPONENT_SD/config/mbed_lib.json index 3a37d4a9c7..1c9d7fe2ce 100644 --- a/components/storage/blockdevice/COMPONENT_SD/config/mbed_lib.json +++ b/components/storage/blockdevice/COMPONENT_SD/config/mbed_lib.json @@ -1,15 +1,15 @@ { "name": "sd", "config": { - "SPI_CS": "NC", - "SPI_MOSI": "NC", - "SPI_MISO": "NC", - "SPI_CLK": "NC", - "DEVICE_SPI": 1, + "SPI_CS": "SPI_CS", + "SPI_MOSI": "SPI_MOSI", + "SPI_MISO": "SPI_MISO", + "SPI_CLK": "SPI_SCK", "FSFAT_SDCARD_INSTALLED": 1, "CMD_TIMEOUT": 10000, "CMD0_IDLE_STATE_RETRIES": 5, - "SD_INIT_FREQUENCY": 100000 + "INIT_FREQUENCY": 100000, + "CRC_ENABLED": 1 }, "target_overrides": { "DISCO_F051R8": { @@ -60,12 +60,6 @@ "SPI_CLK": "PTD5", "SPI_CS": "PTD4" }, - "K64F": { - "SPI_MOSI": "PTE3", - "SPI_MISO": "PTE1", - "SPI_CLK": "PTE2", - "SPI_CS": "PTE4" - }, "K66F": { "SPI_MOSI": "PTE3", "SPI_MISO": "PTE1", @@ -150,7 +144,7 @@ "SPI_CLK": "p15", "SPI_CS": "p14" }, - "UBLOX_C030_U201": { + "UBLOX_C030": { "SPI_MOSI": "D11", "SPI_MISO": "D12", "SPI_CLK": "D13", @@ -216,5 +210,6 @@ "SPI_CLK": "PC_10", "SPI_CS": "PA_15" } + } } diff --git a/components/storage/blockdevice/COMPONENT_SD/util/fsfat_test.c b/components/storage/blockdevice/COMPONENT_SD/util/fsfat_test.c index 98d13d9919..4a52c3703a 100644 --- a/components/storage/blockdevice/COMPONENT_SD/util/fsfat_test.c +++ b/components/storage/blockdevice/COMPONENT_SD/util/fsfat_test.c @@ -61,7 +61,7 @@ const uint8_t fsfat_test_byte_data_table[FSFAT_TEST_BYTE_DATA_TABLE_SIZE] = { /* @brief test utility function to delete the file identified by filename */ -int32_t fsfat_test_delete(const char* filename) +int32_t fsfat_test_delete(const char *filename) { FSFAT_FENTRYLOG("%s:entered.\r\n", __func__); return remove(filename); @@ -74,18 +74,18 @@ int32_t fsfat_test_delete(const char* filename) * @param data data to store in file * @param len number of bytes of data present in the data buffer. */ -int32_t fsfat_test_create(const char* filename, const char* data, size_t len) +int32_t fsfat_test_create(const char *filename, const char *data, size_t len) { int32_t ret = -1; FILE *fp = NULL; FSFAT_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len); fp = fopen(filename, "w+"); - if(fp == NULL){ + if (fp == NULL) { return ret; } - ret = fwrite((const void*) data, len, 1, fp); - if(ret < 0){ + ret = fwrite((const void *) data, len, 1, fp); + if (ret < 0) { fclose(fp); return ret; } @@ -99,16 +99,15 @@ int32_t fsfat_test_create(const char* filename, const char* data, size_t len) * @param len length of kv name to generate * */ -int32_t fsfat_test_filename_gen(char* name, const size_t len) +int32_t fsfat_test_filename_gen(char *name, const size_t len) { size_t i; uint32_t pos = 0; - const char* buf = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!$-_@"; + const char *buf = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!$-_@"; const int buf_len = strlen(buf); FSFAT_FENTRYLOG("%s:entered\n", __func__); - for(i = 0; i < len; i++) - { + for (i = 0; i < len; i++) { pos = rand() % (buf_len); name[i] = buf[pos]; } diff --git a/components/storage/blockdevice/COMPONENT_SD/util/fsfat_test.h b/components/storage/blockdevice/COMPONENT_SD/util/fsfat_test.h index a4a6fd12fc..421c6a2105 100644 --- a/components/storage/blockdevice/COMPONENT_SD/util/fsfat_test.h +++ b/components/storage/blockdevice/COMPONENT_SD/util/fsfat_test.h @@ -57,16 +57,16 @@ extern "C" { /* kv data for test */ typedef struct fsfat_kv_data_t { - const char* filename; - const char* value; + const char *filename; + const char *value; } fsfat_kv_data_t; extern const uint8_t fsfat_test_byte_data_table[FSFAT_TEST_BYTE_DATA_TABLE_SIZE]; -int32_t fsfat_test_create(const char* filename, const char* data, size_t len); -int32_t fsfat_test_delete(const char* key_name); -int32_t fsfat_test_filename_gen(char* name, const size_t len); +int32_t fsfat_test_create(const char *filename, const char *data, size_t len); +int32_t fsfat_test_delete(const char *key_name); +int32_t fsfat_test_filename_gen(char *name, const size_t len); #ifdef __cplusplus } #endif diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp index 4b65a5a249..fbe36020f8 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp @@ -36,8 +36,8 @@ using namespace mbed; #endif #define SPI_NO_ADDRESS_COMMAND UINT64_MAX // Status Register Bits -#define SPIF_STATUS_BIT_WIP 0x1 //Write In Progress -#define SPIF_STATUS_BIT_WEL 0x2 // Write Enable Latch +#define SPIF_STATUS_BIT_WIP 0x1 //Write In Progress +#define SPIF_STATUS_BIT_WEL 0x2 // Write Enable Latch /* SFDP Header Parsing */ /***********************/ @@ -146,7 +146,7 @@ int SPIFBlockDevice::init() } // Soft Reset - if ( -1 == _reset_flash_mem()) { + if (-1 == _reset_flash_mem()) { tr_error("ERROR: init - Unable to initialize flash memory, tests failed\n"); status = SPIF_BD_ERROR_DEVICE_ERROR; goto exit_point; @@ -174,14 +174,14 @@ int SPIFBlockDevice::init() } //Synchronize Device - if ( false == _is_mem_ready()) { + if (false == _is_mem_ready()) { tr_error("ERROR: init - _is_mem_ready Failed"); status = SPIF_BD_ERROR_READY_FAILED; goto exit_point; } /**************************** Parse SFDP Header ***********************************/ - if ( 0 != _sfdp_parse_sfdp_headers(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) { + if (0 != _sfdp_parse_sfdp_headers(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) { tr_error("ERROR: init - Parse SFDP Headers Failed"); status = SPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -189,7 +189,7 @@ int SPIFBlockDevice::init() /**************************** Parse Basic Parameters Table ***********************************/ - if ( 0 != _sfdp_parse_basic_param_table(basic_table_addr, basic_table_size) ) { + if (0 != _sfdp_parse_basic_param_table(basic_table_addr, basic_table_size)) { tr_error("ERROR: init - Parse Basic Param Table Failed"); status = SPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -200,10 +200,10 @@ int SPIFBlockDevice::init() _device_size_bytes; // If there's no region map, we have a single region sized the entire device size _region_high_boundary[0] = _device_size_bytes - 1; - if ( (sector_map_table_addr != 0) && (0 != sector_map_table_size) ) { + if ((sector_map_table_addr != 0) && (0 != sector_map_table_size)) { tr_info("INFO: init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", sector_map_table_addr, sector_map_table_size); - if (0 != _sfdp_parse_sector_map_table(sector_map_table_addr, sector_map_table_size) ) { + if (0 != _sfdp_parse_sector_map_table(sector_map_table_addr, sector_map_table_size)) { tr_error("ERROR: init - Parse Sector Map Table Failed"); status = SPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -309,7 +309,7 @@ int SPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) addr += chunk; size -= chunk; - if ( false == _is_mem_ready()) { + if (false == _is_mem_ready()) { tr_error("ERROR: Device not ready after write, failed\n"); program_failed = true; status = SPIF_BD_ERROR_READY_FAILED; @@ -351,7 +351,7 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) return SPIF_BD_ERROR_INVALID_ERASE_PARAMS; } - if ( ((addr % get_erase_size(addr)) != 0 ) || (((addr + in_size) % get_erase_size(addr + in_size - 1)) != 0 ) ) { + if (((addr % get_erase_size(addr)) != 0) || (((addr + in_size) % get_erase_size(addr + in_size - 1)) != 0)) { tr_error("ERROR: invalid erase - unaligned address and size"); return SPIF_BD_ERROR_INVALID_ERASE_PARAMS; } @@ -364,7 +364,7 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) type = _utils_iterate_next_largest_erase_type(bitfield, size, (unsigned int)addr, _region_high_boundary[region]); cur_erase_inst = _erase_type_inst_arr[type]; offset = addr % _erase_type_size_arr[type]; - chunk = ( (offset + size) < _erase_type_size_arr[type]) ? size : (_erase_type_size_arr[type] - offset); + chunk = ((offset + size) < _erase_type_size_arr[type]) ? size : (_erase_type_size_arr[type] - offset); tr_debug("DEBUG: erase - addr: %llu, size:%d, Inst: 0x%xh, chunk: %lu , ", addr, size, cur_erase_inst, chunk); @@ -385,13 +385,13 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) addr += chunk; size -= chunk; - if ( (size > 0) && (addr > _region_high_boundary[region]) ) { + if ((size > 0) && (addr > _region_high_boundary[region])) { // erase crossed to next region region++; bitfield = _region_erase_types_bitfield[region]; } - if ( false == _is_mem_ready()) { + if (false == _is_mem_ready()) { tr_error("ERROR: SPI After Erase Device not ready - failed\n"); erase_failed = true; status = SPIF_BD_ERROR_READY_FAILED; @@ -461,7 +461,7 @@ bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr) bd_size_t SPIFBlockDevice::size() const { if (!_is_initialized) { - return SPIF_BD_ERROR_DEVICE_ERROR; + return 0; } return _device_size_bytes; @@ -513,7 +513,7 @@ spif_bd_error SPIFBlockDevice::_spi_send_read_command(int read_inst, uint8_t *bu } spif_bd_error SPIFBlockDevice::_spi_send_program_command(int prog_inst, const void *buffer, bd_addr_t addr, - bd_size_t size) + bd_size_t size) { // Send Program (write) command to device driver uint32_t dummy_bytes = _dummy_and_mode_cycles / 8; @@ -556,7 +556,7 @@ spif_bd_error SPIFBlockDevice::_spi_send_erase_command(int erase_inst, bd_addr_t } spif_bd_error SPIFBlockDevice::_spi_send_general_command(int instruction, bd_addr_t addr, char *tx_buffer, - size_t tx_length, char *rx_buffer, size_t rx_length) + size_t tx_length, char *rx_buffer, size_t rx_length) { // Send a general command Instruction to driver uint32_t dummy_bytes = _dummy_and_mode_cycles / 8; @@ -604,14 +604,14 @@ int SPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_addr spif_bd_error status = _spi_send_read_command(SPIF_SFDP, sector_map_table, sector_map_table_addr /*address*/, - sector_map_table_size); + sector_map_table_size); if (status != SPIF_BD_ERROR_OK) { tr_error("ERROR: init - Read SFDP First Table Failed"); return -1; } // Currently we support only Single Map Descriptor - if (! ( (sector_map_table[0] & 0x3) == 0x03 ) && (sector_map_table[1] == 0x0) ) { + if (!((sector_map_table[0] & 0x3) == 0x03) && (sector_map_table[1] == 0x0)) { tr_error("ERROR: Sector Map - Supporting Only Single! Map Descriptor (not map commands)"); return -1; } @@ -658,7 +658,7 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, si //memset(param_table, 0, SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES); spif_bd_error status = _spi_send_read_command(SPIF_SFDP, param_table, basic_table_addr /*address*/, - basic_table_size); + basic_table_size); if (status != SPIF_BD_ERROR_OK) { tr_error("ERROR: init - Read SFDP First Table Failed"); return -1; @@ -674,8 +674,8 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, si uint32_t density_bits = ( (param_table[7] << 24) | (param_table[6] << 16) | - (param_table[5] << 8 ) | - param_table[4] ); + (param_table[5] << 8) | + param_table[4]); _device_size_bytes = (density_bits + 1) / 8; // Set Default read/program/erase Instructions @@ -697,8 +697,8 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, si return 0; } -int SPIFBlockDevice::_sfdp_parse_sfdp_headers(uint32_t& basic_table_addr, size_t& basic_table_size, - uint32_t& sector_map_table_addr, size_t& sector_map_table_size) +int SPIFBlockDevice::_sfdp_parse_sfdp_headers(uint32_t &basic_table_addr, size_t &basic_table_size, + uint32_t §or_map_table_addr, size_t §or_map_table_size) { uint8_t sfdp_header[16]; uint8_t param_header[SPIF_SFDP_HEADER_SIZE]; @@ -752,14 +752,14 @@ int SPIFBlockDevice::_sfdp_parse_sfdp_headers(uint32_t& basic_table_addr, size_t if ((param_header[0] == 0) && (param_header[7] == 0xFF)) { // Found Basic Params Table: LSB=0x00, MSB=0xFF tr_debug("DEBUG: Found Basic Param Table at Table: %d", i_ind + 1); - basic_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) ); + basic_table_addr = ((param_header[6] << 16) | (param_header[5] << 8) | (param_header[4])); // Supporting up to 64 Bytes Table (16 DWORDS) basic_table_size = ((param_header[3] * 4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[3] * 4) : 64; } else if ((param_header[0] == 81) && (param_header[7] == 0xFF)) { // Found Sector Map Table: LSB=0x81, MSB=0xFF tr_debug("DEBUG: Found Sector Map Table at Table: %d", i_ind + 1); - sector_map_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) ); + sector_map_table_addr = ((param_header[6] << 16) | (param_header[5] << 8) | (param_header[4])); sector_map_table_size = param_header[3] * 4; } @@ -775,7 +775,7 @@ unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ if (basic_param_table_size > SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE) { // Page Size is specified by 4 Bits (N), calculated by 2^N - int page_to_power_size = ( (int)basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4; + int page_to_power_size = ((int)basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4; page_size = local_math_power(2, page_to_power_size); tr_debug("DEBUG: Detected Page Size: %d", page_size); } else { @@ -785,8 +785,8 @@ unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ } int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, - int& erase4k_inst, - int *erase_type_inst_arr, unsigned int *erase_type_size_arr) + int &erase4k_inst, + int *erase_type_inst_arr, unsigned int *erase_type_size_arr) { erase4k_inst = 0xff; bool found_4Kerase_type = false; @@ -800,14 +800,14 @@ int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param for (int i_ind = 0; i_ind < 4; i_ind++) { erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type erase_type_size_arr[i_ind] = local_math_power(2, - basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N + basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N tr_info("DEBUG: Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), erase_type_inst_arr[i_ind], erase_type_size_arr[i_ind]); if (erase_type_size_arr[i_ind] > 1) { // if size==1 type is not supported erase_type_inst_arr[i_ind] = basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind]; - if ((erase_type_size_arr[i_ind] < _min_common_erase_size) || (_min_common_erase_size == 0) ) { + if ((erase_type_size_arr[i_ind] < _min_common_erase_size) || (_min_common_erase_size == 0)) { //Set default minimal common erase for singal region _min_common_erase_size = erase_type_size_arr[i_ind]; } @@ -838,7 +838,7 @@ int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param } int SPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, - int& read_inst) + int &read_inst) { do { @@ -847,15 +847,15 @@ int SPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ uint8_t examined_byte; if (basic_param_table_size > SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE) { - examined_byte = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE]; - if (examined_byte & 0x01) { - // Fast Read 2-2-2 Supported - read_inst = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE]; - _read_dummy_and_mode_cycles = (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] >> 5) - + (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] & 0x1F); - tr_info("\nDEBUG: Read Bus Mode set to 2-2-2, Instruction: 0x%xh", read_inst); - break; - } + examined_byte = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE]; + if (examined_byte & 0x01) { + // Fast Read 2-2-2 Supported + read_inst = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE]; + _read_dummy_and_mode_cycles = (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] >> 5) + + (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] & 0x1F); + tr_info("\nDEBUG: Read Bus Mode set to 2-2-2, Instruction: 0x%xh", read_inst); + break; + } } examined_byte = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE]; if (examined_byte & 0x20) { @@ -889,7 +889,7 @@ int SPIFBlockDevice::_reset_flash_mem() char status_value[2] = {0}; tr_info("INFO: _reset_flash_mem:\n"); //Read the Status Register from device - if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value, 1) ) { + if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value, 1)) { // store received values in status_value tr_debug("DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_value[0]); } else { @@ -899,7 +899,7 @@ int SPIFBlockDevice::_reset_flash_mem() if (0 == status) { //Send Reset Enable - if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RSTEN, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0) ) { + if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RSTEN, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0)) { // store received values in status_value tr_debug("DEBUG: Sending RSTEN Success\n"); } else { @@ -935,10 +935,10 @@ bool SPIFBlockDevice::_is_mem_ready() retries++; //Read the Status Register from device if (SPIF_BD_ERROR_OK != _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value, - 1)) { // store received values in status_value + 1)) { // store received values in status_value tr_error("ERROR: Reading Status Register failed\n"); } - } while ( (status_value[0] & SPIF_STATUS_BIT_WIP) != 0 && retries < IS_MEM_READY_MAX_RETRIES ); + } while ((status_value[0] & SPIF_STATUS_BIT_WIP) != 0 && retries < IS_MEM_READY_MAX_RETRIES); if ((status_value[0] & SPIF_STATUS_BIT_WIP) != 0) { tr_error("ERROR: _is_mem_ready FALSE\n"); @@ -959,14 +959,14 @@ int SPIFBlockDevice::_set_write_enable() break; } - if ( false == _is_mem_ready()) { + if (false == _is_mem_ready()) { tr_error("ERROR: Device not ready, write failed"); break; } memset(status_value, 0, 2); if (SPIF_BD_ERROR_OK != _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value, - 1)) { // store received values in status_value + 1)) { // store received values in status_value tr_error("ERROR: Reading Status Register failed\n"); break; } @@ -1004,7 +1004,7 @@ int SPIFBlockDevice::_utils_find_addr_region(bd_size_t offset) } -int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t& bitfield, int size, int offset, int boundry) +int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry) { // Iterate on all supported Erase Types of the Region to which the offset belong to. // Iterates from highest type to lowest @@ -1014,8 +1014,8 @@ int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t& bitfield, i for (i_ind = 3; i_ind >= 0; i_ind--) { if (bitfield & type_mask) { largest_erase_type = i_ind; - if ( (size > (int)(_erase_type_size_arr[largest_erase_type])) && - ((boundry - offset) > (int)(_erase_type_size_arr[largest_erase_type])) ) { + if ((size > (int)(_erase_type_size_arr[largest_erase_type])) && + ((boundry - offset) > (int)(_erase_type_size_arr[largest_erase_type]))) { break; } else { bitfield &= ~type_mask; diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h index 5cd672f90d..af85fe0094 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h @@ -34,7 +34,7 @@ enum spif_bd_error { }; -#define SPIF_MAX_REGIONS 10 +#define SPIF_MAX_REGIONS 10 #define MAX_NUM_OF_ERASE_TYPES 4 /** BlockDevice for SFDP based flash devices over SPI bus @@ -86,7 +86,7 @@ public: /** Initialize a block device * - * @return SPIF_BD_ERROR_OK(0) - success + * @return SPIF_BD_ERROR_OK(0) - success * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed * SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timedout * SPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables @@ -101,7 +101,10 @@ public: /** Desctruct SPIFBlockDevie */ - ~SPIFBlockDevice() {deinit();} + ~SPIFBlockDevice() + { + deinit(); + } /** Read blocks from a block device * @@ -194,8 +197,8 @@ private: /* SFDP Detection and Parsing Functions */ /****************************************/ // Parse SFDP Headers and retrieve Basic Param and Sector Map Tables (if exist) - int _sfdp_parse_sfdp_headers(uint32_t& basic_table_addr, size_t& basic_table_size, - uint32_t& sector_map_table_addr, size_t& sector_map_table_size); + int _sfdp_parse_sfdp_headers(uint32_t &basic_table_addr, size_t &basic_table_size, + uint32_t §or_map_table_addr, size_t §or_map_table_size); // Parse and Detect required Basic Parameters from Table int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size); @@ -204,15 +207,15 @@ private: int _sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size); // Detect fastest read Bus mode supported by device - int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int& read_inst); + int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &read_inst); // Set Page size for program unsigned int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size); // Detect all supported erase types int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, - int& erase4k_inst, - int *erase_type_inst_arr, unsigned int *erase_type_size_arr); + int &erase4k_inst, + int *erase_type_inst_arr, unsigned int *erase_type_size_arr); /***********************/ /* Utilities Functions */ @@ -222,7 +225,7 @@ private: // Iterate on all supported Erase Types of the Region to which the offset belong to. // Iterates from highest type to lowest - int _utils_iterate_next_largest_erase_type(uint8_t& bitfield, int size, int offset, int boundry); + int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry); /********************************/ /* Calls to SPI Driver APIs */ diff --git a/components/storage/blockdevice/COMPONENT_SPIF/TESTS/block_device/spif/main.cpp b/components/storage/blockdevice/COMPONENT_SPIF/TESTS/block_device/spif/main.cpp index f27ec184fa..c012c4a6e9 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/TESTS/block_device/spif/main.cpp +++ b/components/storage/blockdevice/COMPONENT_SPIF/TESTS/block_device/spif/main.cpp @@ -18,6 +18,7 @@ #include "utest.h" #include "SPIFBlockDevice.h" #include "mbed_trace.h" +#include "rtos/Thread.h" #include using namespace utest::v1; @@ -41,7 +42,7 @@ static SingletonPtr _mutex; // Mutex is protecting rand() per srand for buffer writing and verification. // Mutex is also protecting printouts for clear logs. // Mutex is NOT protecting Block Device actions: erase/program/read - which is the purpose of the multithreaded test! -void basic_erase_program_read_test(SPIFBlockDevice& block_device, bd_size_t block_size, uint8_t *write_block, +void basic_erase_program_read_test(SPIFBlockDevice &block_device, bd_size_t block_size, uint8_t *write_block, uint8_t *read_block, unsigned addrwidth) { int err = 0; @@ -77,10 +78,10 @@ void basic_erase_program_read_test(SPIFBlockDevice& block_device, bd_size_t bloc int val_rand; for (bd_size_t i_ind = 0; i_ind < block_size; i_ind++) { val_rand = rand(); - if ( (0xff & val_rand) != read_block[i_ind] ) { + if ((0xff & val_rand) != read_block[i_ind]) { utest_printf("\n Assert Failed Buf Read - block:size: %llx:%llu \n", block, block_size); utest_printf("\n pos: %llu, exp: %02x, act: %02x, wrt: %02x \n", i_ind, (0xff & val_rand), read_block[i_ind], - write_block[i_ind] ); + write_block[i_ind]); } TEST_ASSERT_EQUAL(0xff & val_rand, read_block[i_ind]); } @@ -205,7 +206,7 @@ static void test_spif_thread_job(void *block_device_ptr/*, int thread_num*/) uint8_t *write_block = new (std::nothrow) uint8_t[block_size]; uint8_t *read_block = new (std::nothrow) uint8_t[block_size]; - if (!write_block || !read_block ) { + if (!write_block || !read_block) { utest_printf("\n Not enough memory for test"); goto end; } diff --git a/components/storage/blockdevice/COMPONENT_SPIF/mbed_lib.json b/components/storage/blockdevice/COMPONENT_SPIF/mbed_lib.json index 07fc85b1a4..4d6651ef14 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/mbed_lib.json +++ b/components/storage/blockdevice/COMPONENT_SPIF/mbed_lib.json @@ -1,19 +1,13 @@ { "name": "spif-driver", "config": { - "SPI_MOSI": "NC", - "SPI_MISO": "NC", - "SPI_CLK": "NC", - "SPI_CS": "NC", + "SPI_MOSI": "SPI_MOSI", + "SPI_MISO": "SPI_MISO", + "SPI_CLK": "SPI_SCK", + "SPI_CS": "SPI_CS", "SPI_FREQ": "40000000" }, "target_overrides": { - "K82F": { - "SPI_MOSI": "PTE2", - "SPI_MISO": "PTE4", - "SPI_CLK": "PTE1", - "SPI_CS": "PTE5" - }, "LPC54114": { "SPI_MOSI": "P0_20", "SPI_MISO": "P0_18", diff --git a/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp b/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp index e1652cbddf..e142e51faa 100644 --- a/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp +++ b/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp @@ -20,6 +20,8 @@ #include +using namespace mbed; + #define ESP8266_DEFAULT_BAUD_RATE 115200 #define ESP8266_ALL_SOCKET_IDS -1 diff --git a/components/wifi/esp8266-driver/ESP8266/ESP8266.h b/components/wifi/esp8266-driver/ESP8266/ESP8266.h index 60f85242b1..7d4ee052f9 100644 --- a/components/wifi/esp8266-driver/ESP8266/ESP8266.h +++ b/components/wifi/esp8266-driver/ESP8266/ESP8266.h @@ -227,7 +227,7 @@ public: * * @param func A pointer to a void function, or 0 to set as none */ - void sigio(Callback func); + void sigio(mbed::Callback func); /** * Attach a function to call whenever sigio happens in the serial @@ -237,7 +237,7 @@ public: */ template void sigio(T *obj, M method) { - sigio(Callback(obj, method)); + sigio(mbed::Callback(obj, method)); } /** @@ -271,9 +271,9 @@ public: static const int8_t SOCKET_COUNT = 5; private: - UARTSerial _serial; - ATCmdParser _parser; - Mutex _smutex; // Protect serial port access + mbed::UARTSerial _serial; + mbed::ATCmdParser _parser; + rtos::Mutex _smutex; // Protect serial port access struct packet { struct packet *next; @@ -303,7 +303,7 @@ private: bool _closed; int _socket_open[SOCKET_COUNT]; nsapi_connection_status_t _connection_status; - Callback _connection_status_cb; + mbed::Callback _connection_status_cb; }; #endif diff --git a/components/wifi/esp8266-driver/ESP8266Interface.h b/components/wifi/esp8266-driver/ESP8266Interface.h index 4d19dd60e7..a8dae7bb98 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.h +++ b/components/wifi/esp8266-driver/ESP8266Interface.h @@ -153,36 +153,12 @@ public: */ using NetworkInterface::add_dns_server; - /** Set socket options - * - * The setsockopt allow an application to pass stack-specific hints - * to the underlying stack. For unsupported options, - * NSAPI_ERROR_UNSUPPORTED is returned and the socket is unmodified. - * - * @param handle Socket handle - * @param level Stack-specific protocol level - * @param optname Stack-specific option identifier - * @param optval Option value - * @param optlen Length of the option value - * @return 0 on success, negative error code on failure + /** @copydoc NetworkStack::setsockopt */ virtual nsapi_error_t setsockopt(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen); - /** Get socket options - * - * getsockopt allows an application to retrieve stack-specific options - * from the underlying stack using stack-specific level and option names, - * or to request generic options using levels from nsapi_socket_level_t. - * - * For unsupported options, NSAPI_ERROR_UNSUPPORTED is returned - * and the socket is unmodified. - * - * @param level Stack-specific protocol level or nsapi_socket_level_t - * @param optname Level-specific option name - * @param optval Destination for option value - * @param optlen Length of the option value - * @return 0 on success, negative error code on failure + /** @copydoc NetworkStack::getsockopt */ virtual nsapi_error_t getsockopt(nsapi_socket_t handle, int level, int optname, void *optval, unsigned *optlen); diff --git a/docs/design-documents/features/connectivity/TLSSocket - Design document.md b/docs/design-documents/features/connectivity/TLSSocket - Design document.md new file mode 100644 index 0000000000..0b56fc2aa1 --- /dev/null +++ b/docs/design-documents/features/connectivity/TLSSocket - Design document.md @@ -0,0 +1,275 @@ +# TLSSocket - Design document +## Overview and Background + +This document describes design of TLSSocket class that provides simple interface for Mbed OS +user to create TLS connections over TCP socket. + +This class greatly simplifies the usage of TLS but limits itself to only one use case. +This design limitation is accepted as other users can continue using Mbed TLS API +directly. TLSSocket also exposes internal Mbed TLS structures allowing use of Mbed TLS API to configure the underlying library. + +High level goal is to demonstrate Mbed OS users that secure connections are not hard to do. + +## Design Limitations + +Following design limitations exist in the current design of TLSSocket + +* `TLSSocket::connect()` is always blocking +* Can only use server and client certificates through `set_root_ca_cert()` and `set_client_cert_key()` methods. For other use cases, internal Mbed TLS structures are exposed. +* No PSK mode + +# System Architecture and High-Level Design + +Secure socket consist of two classes: + +* `TLSocketWrapper`
+ Which handles initialization of TLS library and does TLS handsake. Takes any Socket as a + trasport. +* `TLSSocket`
+ Which inherits TLSocketWrapper and has TCP socket as a transport. + Adds `connect(char *hostname)` + for initiating the TCP and TLS handshakes at one call. + +``` + ,--------------. + |Socket | + |--------------| + |--------------| + |int connect();| + |int recv(); | + |int send(); | + `--------------' + | + | +,----------------------------. +|TLSocketWrapper | +|----------------------------| +|Socket *transport; | +|----------------------------| +|TLSocketWrapper(*transport);| +|int set_root_ca_cert(...); | +|void set_hostname(...); | +|int do_handshake(); | +`----------------------------' + | +,----------------------------. +|TLSSocket | +|----------------------------| +|TCPSocket transport | +|----------------------------| +|int connect(char *hostname);| +`----------------------------' +``` + +## High Level Design Goal 1: Abstract socket API + +Secure socket both uses `Socket` interface as its transport layer and implements it. This makes it transport independent and there is no direct dependency to IP stack. + +When TLSSocket implements Socket API it is able to be used instead of TCP connection in +any Mbed OS library. For example MQTT library is made secure without any code changes: +https://github.com/coisme/Mbed-to-Azure-IoT-Hub/tree/new-TLSSocket + +## High Level Design Goal 2: Only certificate based authentication + +Aim is to first support only certificate based authentication, so we implement only `set_root_ca_cert()` and `set_client_cert_key()` functions. For later on, different types of authentication methods can be added. + +## High Level Design Goal 3: Support both blocking and non-blocking operations + +As the Mbed TLS is already work with both socket types, we are able to `TLSocketWrapper` +that can handle both types as well. + +Functions `set_blocking()` and `set_timeout()` just pass the information for underlying +transport socket. Extra handling on the TLS state machine is not required. + +## High Level Design Goal 4: Expose Mbed TLS structures + +Exposing Mbed TLS configuration structures allows user to configure the underlying TLS instance using Mbed TLS API. This allows greater usability as TLSSocket is not limited to only one use case. + +Also configuration structures can be shared between sockets which leads to RAM saving then two or more TLSSockets are used with same parameters. + +## System Architecture and Component Interaction +*Description and diagrams showing overall architecture of how the above-mentioned components/resources interface with each other.* + +# Detailed Design +*This section provides detailed design on implementation of components/modules mentioned in High Level Design section.* + +## Detailed Design for Abstract socket API + +Mbed OS [Socket interface](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/Socket.h) is a abstract C++ inteface that follows POSIX socket API. + +### Receiving and sending data from Mbed TLS + +`TLSSocketWrapper` contains static wrappers `ssl_recv()` and `ssl_send()` functions which are +registered to Mbed TLS library in `mbedtls_ssl_set_bio()` call. + +There functions then call the transport socket's `Socket::send()` and `Socket::recv()` calls +respectively. Error coded are passed through, except `NSAPI_ERROR_WOULD_BLOCK` which is translated to `MBEDTLS_ERR_SSL_WANT_WRITE` or `MBEDTLS_ERR_SSL_WANT_READ`. + +### Providing Socket API + +``` +virtual nsapi_error_t close(); +``` + +Destroys the memory allocated by TLS library. +Alternatively also closes the transport socket, unless `TLSSocketWrapper::keep_transport_open()` has been called earlier. + + +``` +virtual nsapi_error_t connect(const SocketAddress &address); +``` + +Initiates the TCP connection and continues to TLS hanshake. +This is currently forced to blocking mode. + +``` +virtual nsapi_size_or_error_t send(const void *data, nsapi_size_t size); +virtual nsapi_size_or_error_t recv(void *data, nsapi_size_t size); +virtual nsapi_size_or_error_t sendto(const SocketAddress &address, const void *data, nsapi_size_t size); +virtual nsapi_size_or_error_t recvfrom(SocketAddress *address, void *data, nsapi_size_t size); +``` +These work as expected, but `SocketAddress` parameters are ignored. TLS connection cannot +change the peer. Also `recvfrom()` call does not set the peer address. + +Mbed TLS error codes `MBEDTLS_ERR_SSL_WANT_READ` and `MBEDTLS_ERR_SSL_WANT_WRITE` are +translated to `NSAPI_ERROR_WOULD_BLOCK` before passing to user. + +`MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY` is ignored and zero is returned to user (connection closed). Other error codes are passed through. + +``` +virtual nsapi_error_t bind(const SocketAddress &address); +virtual void set_blocking(bool blocking); +virtual void set_timeout(int timeout); +virtual void sigio(mbed::Callback func); +virtual nsapi_error_t setsockopt(int level, int optname, const void *optval, unsigned optlen); +virtual nsapi_error_t getsockopt(int level, int optname, void *optval, unsigned *optlen); +``` +These are passed through to transport socket. + + +``` +virtual Socket *accept(nsapi_error_t *error = NULL); +virtual nsapi_error_t listen(int backlog = 1); +``` +These are returning `NSAPI_ERROR_UNSUPPORTED` as TLS socket cannot be set to listening mode. + +## Detailed Design for certificate based authentication + +`TLSSocketWrapper` provides following API to set server certificate. You can use either BASE64 formatted PEM certificate, or binary DER certificates. Later form just assumes `root_ca_pem` or `client_cert_pem` to be standard C string and counts its lenght and passes to method which takes just `void*` and `len`. + +``` +/** Sets the certification of Root CA. + * + * @param root_ca Root CA Certificate in any mbed-TLS supported format. + * @param len Length of certificate (including terminating 0 for PEM). + */ +nsapi_error_t TLSSocketWrapper::set_root_ca_cert(const void *root_ca, size_t len); + +/** Sets the certification of Root CA. + * + * @param root_ca_pem Root CA Certificate in PEM format + */ +nsapi_error_t TLSSocketWrapper::set_root_ca_cert(const char *root_ca_pem); +``` + +If client authentication is required, following API allows you to set the client certificate and private key: + +``` +/** Sets client certificate, and client private key. + * + * @param client_cert Client certification in any mbed-TLS supported format. + * @param client_private_key Client private key in PEM format. + */ +nsapi_error_t TLSSocketWrapper::set_client_cert_key(const void *client_cert_pem, size_t client_cert_len, + const void *client_private_key_pem, size_t client_private_key_len); + +/** Sets client certificate, and client private key. + * + * @param client_cert_pem Client certification in PEM format. + * @param client_private_key Client private key in PEM format. + */ +nsapi_error_t TLSSocketWrapper::set_client_cert_key(const char *client_cert_pem, const char *client_private_key_pem); +``` + +Certificate is then passed unmodified to `mbedtls_x509_crt_parse()` function. + +## Detailed Design for Support both blocking and non-blocking operations + +`send()` and `receive()` methods do not need to know whether underlying socket is in +blocking mode as Mbed OS return values are enough to tell that. + +Data path when application send data to TLS socket: + +1. Application call `TLSSocketWrapper::send()` function. +1. Which calls `mbedtls_ssl_write()` function +1. Which calls `TLSSocketWrapper::ssl_send()` +1. Which calls transport socket's `Socket::send()` which either blocks or returns `NSAPI_ERROR_WOULD_BLOCK` + +When this `NSAPI_ERROR_WOULD_BLOCK` is returned: + +1. `TLSSocketWrapper::ssl_send()` translates error to `MBEDTLS_ERR_SSL_WANT_WRITE` +1. returned to `mbedtls_ssl_write()` which return the same error +1. `TLSSocketWrapper::send()` gets the `MBEDTLS_ERR_SSL_WANT_WRITE` and translates that to `NSAPI_ERROR_WOULD_BLOCK` +1. Application gets `NSAPI_ERROR_WOULD_BLOCK` and back off. + +When transport socket is in blocking mode, it never returns `NSAPI_ERROR_WOULD_BLOCK` and therefore `mbedtls_ssl_write()` never gets `MBEDTLS_ERR_SSL_WANT_WRITE`, so any translation does not happen, but code path stays unchanged. + +## Detailed Design for exposing Mbed TLS structures + +TLSSocket exposes following API to provide access to internal Mbed TLS data structures: +``` +mbedtls_x509_crt *get_own_cert(); +int set_own_cert(mbedtls_x509_crt *); +mbedtls_x509_crt *get_ca_chain(); +void set_ca_chain(mbedtls_x509_crt *); +mbedtls_ssl_config *get_ssl_config(); +void set_ssl_config(mbedtls_ssl_config *); +``` + +This allows sockets to share same configuration and allow user to fine tune TLS configuration, for example: + +``` +TLSSocket a; +TLSSocket b; +a.set_root_ca_cert(); +b.set_ssl_config(a.get_ssl_config()); +``` + +# Usage Scenarios and Examples + +## Scenario 1: Connecting to secure server: + +``` +NetworkInterface *net = NetworkInterface::get_default_instance(); + +TLSSocket sock(net); +sock.add_root_CA(...); + +sock.connect("my_server.mbed.com", 8080); // Connect & handle TLS handshake + +// Now Socket is connected and can be used as any socket +sock.send("hello", 5); +``` + +Example user: https://github.com/coisme/Mbed-to-Azure-IoT-Hub/blob/new-TLSSocket/MQTTNetwork.h + +# Tools and Configuration Changes + +No tool changes required + +# Other Information + +## Reusability + +Parts of the state machine are probably relevant when implementing DTLS socket. + +TLSSocketWrapper is entirely reusable when doing TLS handshake using any socket type. +It does not have tight bindings to TCP. + +## Assumptions + +We are assuming that server certificate is given from the application to `TLSSocket::set_root_ca_cert()` interface in a format that is understood by Mbed TLS. + +## Deprecations + +No deprecations diff --git a/doxyfile_options b/doxyfile_options index fb869454fa..c257118719 100644 --- a/doxyfile_options +++ b/doxyfile_options @@ -484,14 +484,14 @@ HIDE_UNDOC_MEMBERS = YES # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. -HIDE_UNDOC_CLASSES = YES +HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. -HIDE_FRIEND_COMPOUNDS = NO +HIDE_FRIEND_COMPOUNDS = YES # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these @@ -514,7 +514,7 @@ INTERNAL_DOCS = NO # and Mac users are advised to set this option to NO. # The default value is: system dependent. -CASE_SENSE_NAMES = YES +CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the @@ -805,7 +805,7 @@ INPUT_ENCODING = UTF-8 # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, # *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. -FILE_PATTERNS = *.h +FILE_PATTERNS = *.h DOXYGEN_FRONTPAGE.md # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. @@ -849,6 +849,7 @@ EXCLUDE_PATTERNS = */tools/* \ */features/lwipstack/* \ */features/nanostack/sal-stack-nanostack/* \ */features/nanostack/coap-service/* \ + */features/netsocket/emac-drivers/* \ */mbed-trace/* \ */mbed-coap/* \ */nanostack-libservice/* \ @@ -951,7 +952,7 @@ FILTER_SOURCE_PATTERNS = # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = +USE_MDFILE_AS_MAINPAGE = DOXYGEN_FRONTPAGE.md #--------------------------------------------------------------------------- # Configuration options related to source browsing @@ -1430,7 +1431,7 @@ ECLIPSE_DOC_ID = org.doxygen.Project # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -DISABLE_INDEX = YES +DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag @@ -1561,7 +1562,7 @@ MATHJAX_CODEFILE = # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. -SEARCHENGINE = NO +SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using Javascript. There @@ -1915,7 +1916,7 @@ MAN_LINKS = NO # captures the structure of the code including all documentation. # The default value is: NO. -GENERATE_XML = YES +GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of @@ -1923,7 +1924,7 @@ GENERATE_XML = YES # The default directory is: xml. # This tag requires that the tag GENERATE_XML is set to YES. -XML_OUTPUT = BUILD/xml +XML_OUTPUT = xml # If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program # listings (including syntax highlighting and cross-referencing information) to @@ -2075,7 +2076,6 @@ PREDEFINED = DOXYGEN_ONLY \ DEVICE_CRC \ DEVICE_ETHERNET \ DEVICE_EMAC \ - DEVICE_ETH \ DEVICE_FLASH \ DEVICE_I2C \ DEVICE_I2CSLAVE \ @@ -2184,7 +2184,7 @@ PERL_PATH = /usr/bin/perl # powerful graphs. # The default value is: YES. -CLASS_DIAGRAMS = NO +CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see: diff --git a/doxygen_options.json b/doxygen_options.json index 1362e6b4c3..5cb33a4612 100644 --- a/doxygen_options.json +++ b/doxygen_options.json @@ -1,5 +1,5 @@ { - "PROJECT_NAME": "Mbed OS Reference", + "PROJECT_NAME": "\"Mbed OS Reference\"", "ENABLE_PREPROCESSING": "YES", "MACRO_EXPANSION": "YES", "EXPAND_ONLY_PREDEF": "NO", @@ -10,5 +10,38 @@ "EXPAND_AS_DEFINED": "", "SKIP_FUNCTION_MACROS": "NO", "STRIP_CODE_COMMENTS": "NO", - "EXCLUDE_PATTERNS": "*/tools/* */targets/* */features/mbedtls/* */features/storage/cfstore/* */features/storage/FEATURE_STORAGE/* */features/unsupported/* */BUILD/* */rtos/TARGET_CORTEX/rtx*/* */cmsis/* */features/lwipstack/* */nanostack/sal-stack-nanostack/* */nanostack/coap-service/* */ble/generic/* */ble/pal/* */mbed-trace/* */mbed-coap/* */nanostack-libservice/* */mbed-client-randlib/* */nanostack/sal-stack-nanostack-eventloop/* */components/802.15.4_RF/* */components/wifi/* */features/nfc/stack/* */UNITTESTS/*" + "EXCLUDE_PATTERNS": "*/tools/* */targets/* */features/mbedtls/* */features/storage/cfstore/* */features/storage/FEATURE_STORAGE/* */features/unsupported/* */BUILD/* */rtos/TARGET_CORTEX/rtx*/* */cmsis/* */features/lwipstack/* */nanostack/sal-stack-nanostack/* */nanostack/coap-service/* */ble/generic/* */ble/pal/* */mbed-trace/* */mbed-coap/* */nanostack-libservice/* */mbed-client-randlib/* */nanostack/sal-stack-nanostack-eventloop/* */components/802.15.4_RF/* */components/wifi/* */features/nfc/stack/* */UNITTESTS/* */features/cryptocell/*", + "ALPHABETICAL_INDEX": "NO", + "CASE_SENSE_NAMES": "NO", + "DOT_MULTI_TARGETS": "YES", + "EXCLUDE_SYMLINKS": "YES", + "EXTRACT_ANON_NSPACES": "YES", + "EXTRACT_LOCAL_CLASSES": "NO", + "EXTRACT_STATIC": "YES", + "FILE_PATTERNS": "*.h DOXYGEN_FRONTPAGE.md", + "FULL_PATH_NAMES": "NO", + "GENERATE_BUGLIST": "NO", + "GENERATE_LATEX": "NO", + "GENERATE_TESTLIST": "NO", + "GENERATE_TODOLIST": "NO", + "HIDE_SCOPE_NAMES": "YES", + "HIDE_UNDOC_MEMBERS": "YES", + "HIDE_FRIEND_COMPOUNDS": "YES", + "INLINE_INFO": "NO", + "INLINE_INHERITED_MEMB": "YES", + "JAVADOC_AUTOBRIEF": "YES", + "PAPER_TYPE": "a4wide", + "QUIET": "YES", + "REFERENCES_LINK_SOURCE": "NO", + "SHOW_USED_FILES": "NO", + "SOURCE_BROWSER": "YES", + "ALWAYS_DETAILED_SEC": "YES", + + "INPUT": "mbed-os", + "HTML_OUTPUT": "html", + + "RECURSIVE": "YES", + "OPTIMIZE_OUTPUT_FOR_C": "YES", + "USE_MDFILE_AS_MAINPAGE": "DOXYGEN_FRONTPAGE.md", + "SEARCHENGINE": "YES" } diff --git a/drivers/AnalogIn.h b/drivers/AnalogIn.h index c9ccfa25a1..6e1cc5bc76 100644 --- a/drivers/AnalogIn.h +++ b/drivers/AnalogIn.h @@ -79,7 +79,7 @@ public: /** Read the input voltage, represented as an unsigned short in the range [0x0, 0xFFFF] * * @returns - * 16-bit unsigned short representing the current input voltage, normalised to a 16-bit value + * 16-bit unsigned short representing the current input voltage, normalized to a 16-bit value */ unsigned short read_u16() { @@ -114,7 +114,7 @@ public: } protected: - + #if !defined(DOXYGEN_ONLY) virtual void lock() { _mutex->lock(); @@ -127,6 +127,7 @@ protected: analogin_t _adc; static SingletonPtr _mutex; + #endif //!defined(DOXYGEN_ONLY) }; } // namespace mbed diff --git a/drivers/AnalogOut.h b/drivers/AnalogOut.h index 3945c580c4..8057723a5a 100644 --- a/drivers/AnalogOut.h +++ b/drivers/AnalogOut.h @@ -79,7 +79,7 @@ public: /** Set the output voltage, represented as an unsigned short in the range [0x0, 0xFFFF] * * @param value 16-bit unsigned short representing the output voltage, - * normalised to a 16-bit value (0x0000 = 0v, 0xFFFF = 3.3v) + * normalized to a 16-bit value (0x0000 = 0v, 0xFFFF = 3.3v) */ void write_u16(unsigned short value) { @@ -141,7 +141,7 @@ public: } protected: - + #if !defined(DOXYGEN_ONLY) virtual void lock() { _mutex.lock(); @@ -154,6 +154,7 @@ protected: dac_t _dac; PlatformMutex _mutex; + #endif //!defined(DOXYGEN_ONLY) }; } // namespace mbed diff --git a/drivers/BusIn.cpp b/drivers/BusIn.cpp index f6cc933e7e..c14351f3fe 100644 --- a/drivers/BusIn.cpp +++ b/drivers/BusIn.cpp @@ -97,7 +97,7 @@ BusIn::operator int() DigitalIn &BusIn::operator[](int index) { // No lock needed since _pin is not modified outside the constructor - MBED_ASSERT(index >= 0 && index <= 16); + MBED_ASSERT(index >= 0 && index < 16); MBED_ASSERT(_pin[index]); return *_pin[index]; } diff --git a/drivers/BusIn.h b/drivers/BusIn.h index 80b20d72a1..da3f44545f 100644 --- a/drivers/BusIn.h +++ b/drivers/BusIn.h @@ -106,6 +106,7 @@ public: */ DigitalIn &operator[](int index); +#if !defined(DOXYGEN_ONLY) protected: DigitalIn *_pin[16]; @@ -120,6 +121,7 @@ protected: private: virtual void lock(); virtual void unlock(); +#endif }; } // namespace mbed diff --git a/drivers/BusInOut.cpp b/drivers/BusInOut.cpp index 950cbb5d58..170e035b96 100644 --- a/drivers/BusInOut.cpp +++ b/drivers/BusInOut.cpp @@ -128,7 +128,7 @@ BusInOut &BusInOut::operator= (BusInOut &rhs) DigitalInOut &BusInOut::operator[](int index) { // No lock needed since _pin is not modified outside the constructor - MBED_ASSERT(index >= 0 && index <= 16); + MBED_ASSERT(index >= 0 && index < 16); MBED_ASSERT(_pin[index]); return *_pin[index]; } diff --git a/drivers/BusInOut.h b/drivers/BusInOut.h index 9bb4e995ae..02f62fbf3f 100644 --- a/drivers/BusInOut.h +++ b/drivers/BusInOut.h @@ -83,15 +83,15 @@ public: */ int read(); - /** Set as an output + /** Set all the pins in bus as output */ void output(); - /** Set as an input + /** Set all the pins in bus as an input */ void input(); - /** Set the input pin mode + /** Set the input pin mode for all the pins in bus * * @param pull PullUp, PullDown, PullNone */ @@ -124,7 +124,7 @@ public: * \sa BusInOut::read() */ operator int(); - +#if !defined(DOXYGEN_ONLY) protected: virtual void lock(); virtual void unlock(); @@ -137,6 +137,7 @@ protected: int _nc_mask; PlatformMutex _mutex; +#endif }; } // namespace mbed diff --git a/drivers/BusOut.cpp b/drivers/BusOut.cpp index 913ba19750..769d2e6891 100644 --- a/drivers/BusOut.cpp +++ b/drivers/BusOut.cpp @@ -95,7 +95,7 @@ BusOut &BusOut::operator= (BusOut &rhs) DigitalOut &BusOut::operator[](int index) { // No lock needed since _pin is not modified outside the constructor - MBED_ASSERT(index >= 0 && index <= 16); + MBED_ASSERT(index >= 0 && index < 16); MBED_ASSERT(_pin[index]); return *_pin[index]; } diff --git a/drivers/BusOut.h b/drivers/BusOut.h index 2f908b65d8..46e21240a7 100644 --- a/drivers/BusOut.h +++ b/drivers/BusOut.h @@ -108,7 +108,7 @@ public: * \sa BusOut::read() */ operator int(); - +#if !defined(DOXYGEN_ONLY) protected: virtual void lock(); virtual void unlock(); @@ -121,6 +121,7 @@ protected: int _nc_mask; PlatformMutex _mutex; +#endif }; } // namespace mbed diff --git a/drivers/CAN.h b/drivers/CAN.h index c1aae5c771..8dd81446ee 100644 --- a/drivers/CAN.h +++ b/drivers/CAN.h @@ -85,7 +85,7 @@ public: class CAN : private NonCopyable { public: - /** Creates an CAN interface connected to specific pins. + /** Creates a CAN interface connected to specific pins. * * @param rd read from transmitter * @param td transmit to transmitter @@ -94,11 +94,14 @@ public: * @code * #include "mbed.h" * + * * Ticker ticker; * DigitalOut led1(LED1); * DigitalOut led2(LED2); - * CAN can1(p9, p10); - * CAN can2(p30, p29); + * //The constructor takes in RX, and TX pin respectively. + * //These pins, for this example, are defined in mbed_app.json + * CAN can1(MBED_CONF_APP_CAN1_RD, MBED_CONF_APP_CAN1_TD); + * CAN can2(MBED_CONF_APP_CAN2_RD, MBED_CONF_APP_CAN2_TD); * * char counter = 0; * @@ -121,14 +124,15 @@ public: * wait(0.2); * } * } + * * @endcode */ CAN(PinName rd, PinName td); /** Initialize CAN interface and set the frequency * - * @param rd the rd pin - * @param td the td pin + * @param rd the read pin + * @param td the transmit pin * @param hz the bus frequency in hertz */ CAN(PinName rd, PinName td, int hz); @@ -197,7 +201,7 @@ public: */ int mode(Mode mode); - /** Filter out incomming messages + /** Filter out incoming messages * * @param id the id to filter on * @param mask the mask applied to the id @@ -288,12 +292,14 @@ public: static void _irq_handler(uint32_t id, CanIrqType type); +#if !defined(DOXYGEN_ONLY) protected: virtual void lock(); virtual void unlock(); can_t _can; Callback _irq[IrqCnt]; PlatformMutex _mutex; +#endif }; } // namespace mbed diff --git a/drivers/DigitalIn.h b/drivers/DigitalIn.h index 1a2af01fa3..a5679b1225 100644 --- a/drivers/DigitalIn.h +++ b/drivers/DigitalIn.h @@ -108,6 +108,11 @@ public: /** An operator shorthand for read() * \sa DigitalIn::read() + * @code + * DigitalIn button(BUTTON1); + * DigitalOut led(LED1); + * led = button; // Equivalent to led.write(button.read()) + * @endcode */ operator int() { @@ -116,7 +121,9 @@ public: } protected: + #if !defined(DOXYGEN_ONLY) gpio_t gpio; + #endif //!defined(DOXYGEN_ONLY) }; } // namespace mbed diff --git a/drivers/DigitalInOut.h b/drivers/DigitalInOut.h index a11fcad2c0..74a5747f20 100644 --- a/drivers/DigitalInOut.h +++ b/drivers/DigitalInOut.h @@ -121,6 +121,13 @@ public: /** A shorthand for write() * \sa DigitalInOut::write() + * @code + * DigitalInOut inout(PIN); + * DigitalIn button(BUTTON1); + * inout.output(); + * + * inout = button; // Equivalent to inout.write(button.read()) + * @endcode */ DigitalInOut &operator= (int value) { @@ -129,7 +136,8 @@ public: return *this; } - /** A shorthand for write() + /**A shorthand for write() using the assignment operator which copies the + * state from the DigitalInOut argument. * \sa DigitalInOut::write() */ DigitalInOut &operator= (DigitalInOut &rhs) @@ -142,6 +150,13 @@ public: /** A shorthand for read() * \sa DigitalInOut::read() + * @code + * DigitalInOut inout(PIN); + * DigitalOut led(LED1); + * + * inout.input(); + * led = inout; // Equivalent to led.write(inout.read()) + * @endcode */ operator int() { @@ -150,7 +165,9 @@ public: } protected: + #if !defined(DOXYGEN_ONLY) gpio_t gpio; + #endif //!defined(DOXYGEN_ONLY) }; } // namespace mbed diff --git a/drivers/DigitalOut.h b/drivers/DigitalOut.h index fb6d1be6c2..5758c2658c 100644 --- a/drivers/DigitalOut.h +++ b/drivers/DigitalOut.h @@ -104,6 +104,11 @@ public: /** A shorthand for write() * \sa DigitalOut::write() + * @code + * DigitalIn button(BUTTON1); + * DigitalOut led(LED1); + * led = button; // Equivalent to led.write(button.read()) + * @endcode */ DigitalOut &operator= (int value) { @@ -112,7 +117,8 @@ public: return *this; } - /** A shorthand for write() + /** A shorthand for write() using the assignment operator which copies the + * state from the DigitalOut argument. * \sa DigitalOut::write() */ DigitalOut &operator= (DigitalOut &rhs) @@ -125,6 +131,11 @@ public: /** A shorthand for read() * \sa DigitalOut::read() + * @code + * DigitalIn button(BUTTON1); + * DigitalOut led(LED1); + * led = button; // Equivalent to led.write(button.read()) + * @endcode */ operator int() { @@ -133,7 +144,9 @@ public: } protected: + #if !defined(DOXYGEN_ONLY) gpio_t gpio; + #endif //!defined(DOXYGEN_ONLY) }; } // namespace mbed diff --git a/drivers/Ethernet.h b/drivers/Ethernet.h index 06aa99a76a..a9b7c2c1db 100644 --- a/drivers/Ethernet.h +++ b/drivers/Ethernet.h @@ -59,7 +59,7 @@ class Ethernet : private NonCopyable { public: - /** Initialise the ethernet interface. + /** Initialize the ethernet interface. */ Ethernet(); diff --git a/drivers/FlashIAP.cpp b/drivers/FlashIAP.cpp index 879a74f3c8..b6b1c2377d 100644 --- a/drivers/FlashIAP.cpp +++ b/drivers/FlashIAP.cpp @@ -203,6 +203,11 @@ uint32_t FlashIAP::get_flash_size() const return flash_get_size(&_flash); } +uint8_t FlashIAP::get_erase_value() const +{ + return flash_get_erase_value(&_flash); +} + } #endif diff --git a/drivers/FlashIAP.h b/drivers/FlashIAP.h index 1699b69245..befb45ac23 100644 --- a/drivers/FlashIAP.h +++ b/drivers/FlashIAP.h @@ -131,6 +131,14 @@ public: */ uint32_t get_page_size() const; + /** Get the flash erase value + * + * Get the value we read after erase operation + * @return flash erase value + */ + uint8_t get_erase_value() const; + +#if !defined(DOXYGEN_ONLY) private: /* Check if address and size are aligned to a sector @@ -144,6 +152,7 @@ private: flash_t _flash; uint8_t *_page_buf; static SingletonPtr _mutex; +#endif }; } /* namespace mbed */ diff --git a/drivers/I2C.cpp b/drivers/I2C.cpp index 08d8d2320f..2cdcc49d8c 100644 --- a/drivers/I2C.cpp +++ b/drivers/I2C.cpp @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "drivers/I2C.h" +#include "drivers/DigitalInOut.h" +#include "platform/mbed_wait_api.h" #if DEVICE_I2C @@ -32,13 +35,15 @@ I2C::I2C(PinName sda, PinName scl) : #endif _i2c(), _hz(100000) { - // No lock needed in the constructor - + lock(); // The init function also set the frequency to 100000 - i2c_init(&_i2c, sda, scl); - + _sda = sda; + _scl = scl; + recover(sda, scl); + i2c_init(&_i2c, _sda, _scl); // Used to avoid unnecessary frequency updates _owner = this; + unlock(); } void I2C::frequency(int hz) @@ -135,6 +140,52 @@ void I2C::unlock() _mutex->unlock(); } +int I2C::recover(PinName sda, PinName scl) +{ + DigitalInOut pin_sda(sda, PIN_INPUT, PullNone, 1); + DigitalInOut pin_scl(scl, PIN_INPUT, PullNone, 1); + + // Return as SCL is low and no access to become master. + if (pin_scl == 0) { + return I2C_ERROR_BUS_BUSY; + } + + // Return successfully as SDA and SCL is high + if (pin_sda == 1) { + return 0; + } + + // Send clock pulses, for device to recover 9 + pin_scl.mode(PullNone); + pin_scl.output(); + for (int count = 0; count < 10; count++) { + pin_scl.mode(PullNone); + pin_scl = 0; + wait_us(5); + pin_scl.mode(PullUp); + pin_scl = 1; + wait_us(5); + } + + // Send Stop + pin_sda.output(); + pin_sda = 0; + wait_us(5); + pin_scl = 1; + wait_us(5); + pin_sda = 1; + wait_us(5); + + pin_sda.input(); + pin_scl.input(); + if ((pin_scl == 0) || (pin_sda == 0)) { + // Return as SCL is low and no access to become master. + return I2C_ERROR_BUS_BUSY; + } + + return 0; +} + #if DEVICE_I2C_ASYNCH int I2C::transfer(int address, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, const event_callback_t &callback, int event, bool repeated) @@ -169,10 +220,10 @@ void I2C::irq_handler_asynch(void) if (_callback && event) { _callback.call(event); } + if (event) { unlock_deep_sleep(); } - } void I2C::lock_deep_sleep() diff --git a/drivers/I2C.h b/drivers/I2C.h index 13f43186d6..daca532ef5 100644 --- a/drivers/I2C.h +++ b/drivers/I2C.h @@ -17,6 +17,7 @@ #define MBED_I2C_H #include "platform/platform.h" +#include "hal/gpio_api.h" #if defined (DEVICE_I2C) || defined(DOXYGEN_ONLY) @@ -40,16 +41,32 @@ namespace mbed { * * Example: * @code - * // Read from I2C slave at address 0x62 - * + * Read temperature from LM75BD * #include "mbed.h" - * - * I2C i2c(p28, p27); + * I2C i2c(I2C_SDA , I2C_SCL); + * const int addr7bit = 0x48; // 7-bit I2C address + * const int addr8bit = 0x48 << 1; // 8-bit I2C address, 0x90 * * int main() { - * int address = 0x62; - * char data[2]; - * i2c.read(address, data, 2); + * char cmd[2]; + * while (1) { + * cmd[0] = 0x01; + * cmd[1] = 0x00; + * + * // read and write takes the 8-bit version of the address. + * // set up configuration register (at 0x01) + * i2c.write(addr8bit, cmd, 2); + * + * wait(0.5); + * + * // read temperature register + * cmd[0] = 0x00; + * i2c.write(addr8bit, cmd, 1); + * i2c.read( addr8bit, cmd, 2); + * + * float tmp = (float((cmd[0]<<8)|cmd[1]) / 256.0); + * printf("Temp = %.2f\n", tmp); + * } * } * @endcode * @ingroup drivers @@ -91,10 +108,11 @@ public: * @param data Pointer to the byte-array to read data in to * @param length Number of bytes to read * @param repeated Repeated start, true - don't send stop at end + * default value is false. * * @returns * 0 on success (ack), - * non-0 on failure (nack) + * nonzero on failure (nack) */ int read(int address, char *data, int length, bool repeated = false); @@ -116,10 +134,11 @@ public: * @param data Pointer to the byte-array data to send * @param length Number of bytes to send * @param repeated Repeated start, true - do not send stop at end + * default value is false. * * @returns * 0 on success (ack), - * non-0 on failure (nack) + * nonzero on failure (nack) */ int write(int address, const char *data, int length, bool repeated = false); @@ -136,7 +155,6 @@ public: /** Creates a start condition on the I2C bus */ - void start(void); /** Creates a stop condition on the I2C bus @@ -158,26 +176,29 @@ public: #if DEVICE_I2C_ASYNCH - /** Start non-blocking I2C transfer. + /** Start nonblocking I2C transfer. * * This function locks the deep sleep until any event has occurred * * @param address 8/10 bit I2C slave address - * @param tx_buffer The TX buffer with data to be transfered + * @param tx_buffer The TX buffer with data to be transferred * @param tx_length The length of TX buffer in bytes - * @param rx_buffer The RX buffer which is used for received data + * @param rx_buffer The RX buffer, which is used for received data * @param rx_length The length of RX buffer in bytes * @param event The logical OR of events to modify * @param callback The event callback function * @param repeated Repeated start, true - do not send stop at end - * @return Zero if the transfer has started, or -1 if I2C peripheral is busy + * default value is false. + * + * @returns Zero if the transfer has started, or -1 if I2C peripheral is busy */ int transfer(int address, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, const event_callback_t &callback, int event = I2C_EVENT_TRANSFER_COMPLETE, bool repeated = false); - /** Abort the on-going I2C transfer + /** Abort the ongoing I2C transfer */ void abort_transfer(); +#if !defined(DOXYGEN_ONLY) protected: /** Lock deep sleep only if it is not yet locked */ void lock_deep_sleep(); @@ -191,14 +212,33 @@ protected: DMAUsage _usage; bool _deep_sleep_locked; #endif +#endif +#if !defined(DOXYGEN_ONLY) protected: void aquire(); i2c_t _i2c; static I2C *_owner; - int _hz; + int _hz; static SingletonPtr _mutex; + PinName _sda; + PinName _scl; + +private: + /** Recover I2C bus, when stuck with SDA low + * @note : Initialization of I2C bus is required after this API. + * + * @param sda I2C data line pin + * @param scl I2C clock line pin + * + * @returns + * '0' - Successfully recovered + * 'I2C_ERROR_BUS_BUSY' - In case of failure + * + */ + int recover(PinName sda, PinName scl); +#endif }; } // namespace mbed diff --git a/drivers/I2CSlave.h b/drivers/I2CSlave.h index 047ef77ea4..12d9ce08c7 100644 --- a/drivers/I2CSlave.h +++ b/drivers/I2CSlave.h @@ -25,38 +25,41 @@ namespace mbed { /** \addtogroup drivers */ -/** An I2C Slave, used for communicating with an I2C Master device +/** An I2C Slave, used for communicating with an I2C Master device. * * @note Synchronization level: Not protected * - * Example: + * Example Simple I2C responder: * @code - * // Simple I2C responder * #include * - * I2CSlave slave(p9, p10); + * const int SLAVE_ADDRESS = 0xA0; + * const char message[] = "Slave!"; + * + * I2CSlave slave(I2C_SDA, I2C_SCL); * * int main() { - * char buf[10]; - * char msg[] = "Slave!"; - * - * slave.address(0xA0); + * slave.address(SLAVE_ADDRESS); * while (1) { - * int i = slave.receive(); - * switch (i) { + * int operation = slave.receive(); + * switch (operation) { * case I2CSlave::ReadAddressed: - * slave.write(msg, strlen(msg) + 1); // Includes null char + * int status = slave.write(message, sizeof(message)); + * if (status == 0) { + * printf("Written message: %s\n", message); + * } else { + * printf("Failed to write message.\n"); + * } * break; * case I2CSlave::WriteGeneral: - * slave.read(buf, 10); - * printf("Read G: %s\n", buf); + * int byte_read = slave.read(); + * printf("Read General: %c (%d)\n", byte_read, byte_read); * break; * case I2CSlave::WriteAddressed: - * slave.read(buf, 10); - * printf("Read A: %s\n", buf); + * int byte_read = slave.read(); + * printf("Read Addressed: %c (%d)\n", byte_read, byte_read); * break; * } - * for(int i = 0; i < 10; i++) buf[i] = 0; // Clear buffer * } * } * @endcode @@ -74,71 +77,71 @@ public: /** Create an I2C Slave interface, connected to the specified pins. * - * @param sda I2C data line pin - * @param scl I2C clock line pin + * @param sda I2C data line pin. + * @param scl I2C clock line pin. */ I2CSlave(PinName sda, PinName scl); - /** Set the frequency of the I2C interface + /** Set the frequency of the I2C interface. * - * @param hz The bus frequency in hertz + * @param hz The bus frequency in Hertz. */ void frequency(int hz); - /** Checks to see if this I2C Slave has been addressed. + /** Check if this I2C Slave has been addressed. * - * @returns - * A status indicating if the device has been addressed, and how - * - NoData - the slave has not been addressed - * - ReadAddressed - the master has requested a read from this slave - * - WriteAddressed - the master is writing to this slave - * - WriteGeneral - the master is writing to all slave + * @return A status indicating if the device has been addressed and how. + * @retval NoData The slave has not been addressed. + * @retval ReadAddressed The master has requested a read from this slave. + * @retval WriteAddressed The master is writing to this slave. + * @retval WriteGeneral The master is writing to all slave. */ int receive(void); - /** Read from an I2C master. + /** Read specified number of bytes from an I2C master. * - * @param data pointer to the byte array to read data in to - * @param length maximum number of bytes to read + * @param data Pointer to the buffer to read data into. + * @param length Number of bytes to read. * - * @returns - * 0 on success, - * non-0 otherwise + * @return Result of the operation. + * @retval 0 If the number of bytes read is equal to length requested. + * @retval nonzero On error or if the number of bytes read is less than requested. */ int read(char *data, int length); /** Read a single byte from an I2C master. * - * @returns - * the byte read + * @return The byte read. */ int read(void); /** Write to an I2C master. * - * @param data pointer to the byte array to be transmitted - * @param length the number of bytes to transmite + * @param data Pointer to the buffer containing the data to be sent. + * @param length Number of bytes to send. * - * @returns - * 0 on success, - * non-0 otherwise + * @return + * @retval 0 If written all bytes successfully. + * @retval nonzero On error or if the number of bytes written is less than requested. */ int write(const char *data, int length); /** Write a single byte to an I2C master. * - * @param data the byte to write + * @param data Value to write. * - * @returns - * '1' if an ACK was received, - * '0' otherwise + * @return Result of the operation. + * @retval 0 If a NACK is received. + * @retval 1 If an ACK is received. + * @retval 2 On timeout. */ int write(int data); - /** Sets the I2C slave address. + /** Set the I2C slave address. * - * @param address The address to set for the slave (ignoring the least - * signifcant bit). If set to 0, the slave will only respond to the + * @param address The address to set for the slave (least significant bit is ignored). + * + * @note If address is set to 0, the slave will only respond to the * general call address. */ void address(int address); @@ -147,8 +150,13 @@ public: */ void stop(void); +#if !defined(DOXYGEN_ONLY) + protected: + /* Internal i2c object identifying the resources */ i2c_t _i2c; + +#endif //!defined(DOXYGEN_ONLY) }; } // namespace mbed diff --git a/drivers/InterruptIn.h b/drivers/InterruptIn.h index ebc8c84fac..85928e3e85 100644 --- a/drivers/InterruptIn.h +++ b/drivers/InterruptIn.h @@ -48,6 +48,7 @@ namespace mbed { * } * * int main() { + * // register trigger() to be called upon the rising edge of event * event.rise(&trigger); * while(1) { * led = !led; @@ -71,7 +72,10 @@ public: * and the pin configured to the specified mode. * * @param pin InterruptIn pin to connect to - * @param mode The mode to set the pin to (PullUp/PullDown/etc.) + * @param mode Desired Pin mode configuration. + * (Valid values could be PullNone, PullDown, PullUp and PullDefault. + * See PinNames.h for your target for definitions) + * */ InterruptIn(PinName pin, PinMode mode); @@ -142,22 +146,23 @@ public: /** Set the input pin mode * - * @param pull PullUp, PullDown, PullNone + * @param pull PullUp, PullDown, PullNone, PullDefault + * See PinNames.h for your target for definitions) */ void mode(PinMode pull); - /** Enable IRQ. This method depends on hw implementation, might enable one + /** Enable IRQ. This method depends on hardware implementation, might enable one * port interrupts. For further information, check gpio_irq_enable(). */ void enable_irq(); - /** Disable IRQ. This method depends on hw implementation, might disable one + /** Disable IRQ. This method depends on hardware implementation, might disable one * port interrupts. For further information, check gpio_irq_disable(). */ void disable_irq(); static void _irq_handler(uint32_t id, gpio_irq_event event); - +#if !defined(DOXYGEN_ONLY) protected: gpio_t gpio; gpio_irq_t gpio_irq; @@ -166,6 +171,7 @@ protected: Callback _fall; void irq_init(PinName pin); +#endif }; } // namespace mbed diff --git a/drivers/InterruptManager.h b/drivers/InterruptManager.h index c65fb683e8..6b3c1d086c 100644 --- a/drivers/InterruptManager.h +++ b/drivers/InterruptManager.h @@ -166,6 +166,7 @@ public: "public API of mbed-os and is being removed in the future.") bool remove_handler(pFunctionPointer_t handler, IRQn_Type irq); +#if !defined(DOXYGEN_ONLY) private: InterruptManager(); ~InterruptManager(); @@ -198,6 +199,7 @@ private: CallChain *_chains[NVIC_NUM_VECTORS]; static InterruptManager *_instance; PlatformMutex _mutex; +#endif }; } // namespace mbed diff --git a/drivers/LowPowerTimeout.h b/drivers/LowPowerTimeout.h index 7c9d00e384..561c4a2201 100644 --- a/drivers/LowPowerTimeout.h +++ b/drivers/LowPowerTimeout.h @@ -33,12 +33,13 @@ namespace mbed { * @ingroup drivers */ class LowPowerTimeout : public LowPowerTicker, private NonCopyable { - +#if !defined(DOXYGEN_ONLY) private: virtual void handler(void) { _function.call(); } +#endif }; } diff --git a/drivers/MbedCRC.h b/drivers/MbedCRC.h index fd4fa1c7f0..9c7328bd00 100644 --- a/drivers/MbedCRC.h +++ b/drivers/MbedCRC.h @@ -99,8 +99,7 @@ template class MbedCRC { public: - enum CrcMode - { + enum CrcMode { #ifdef DEVICE_CRC HARDWARE = 0, #endif @@ -120,7 +119,7 @@ public: * MbedCRC ct; --- Valid POLY_7BIT_SD * MbedCRC <0x1021, 16> ct; --- Valid POLY_16BIT_CCITT * MbedCRC ct; --- Invalid, compilation error - * MbedCRC ct (i,f,rd,rr) Consturctor can be used for not supported polynomials + * MbedCRC ct (i,f,rd,rr) Constructor can be used for not supported polynomials * MbedCRC sd(0, 0, false, false); Constructor can also be used for supported * polynomials with different intial/final/reflect values * @@ -165,7 +164,7 @@ public: status = compute_partial_stop(crc); if (0 != status) { - *crc = 0; + *crc = 0; } return status; @@ -176,7 +175,7 @@ public: * * CRC data if not available fully, CRC can be computed in parts with available data. * - * In case of hardware, intermediate values and states are saved by hardware and mutex + * In case of hardware, intermediate values and states are saved by hardware. Mutex * locking is used to serialize access to hardware CRC. * * In case of software CRC, previous CRC output should be passed as argument to the @@ -218,7 +217,7 @@ public: return status; } - /** Compute partial start, indicate start of partial computation + /** Compute partial start, indicate start of partial computation. * * This API should be called before performing any partial computation * with compute_partial API. @@ -258,6 +257,7 @@ public: * This API is used to perform final computation to get correct CRC value. * * @param crc CRC result + * @return 0 on success or a negative in case of failure. */ int32_t compute_partial_stop(uint32_t *crc) { @@ -284,7 +284,7 @@ public: return 0; } - /** Get the current CRC polynomial + /** Get the current CRC polynomial. * * @return Polynomial value */ @@ -302,6 +302,7 @@ public: return width; } +#if !defined(DOXYGEN_ONLY) private: uint32_t _initial_value; uint32_t _final_xor; @@ -310,9 +311,9 @@ private: uint32_t *_crc_table; CrcMode _mode; - /** Acquire exclusive access to CRC hardware/software + /** Acquire exclusive access to CRC hardware/software. */ - void lock() + void lock() { #ifdef DEVICE_CRC if (_mode == HARDWARE) { @@ -321,7 +322,7 @@ private: #endif } - /** Release exclusive access to CRC hardware/software + /** Release exclusive access to CRC hardware/software. */ virtual void unlock() { @@ -332,7 +333,7 @@ private: #endif } - /** Get the current CRC data size + /** Get the current CRC data size. * * @return CRC data size in bytes */ @@ -341,7 +342,7 @@ private: return (width <= 8 ? 1 : (width <= 16 ? 2 : 4)); } - /** Get the top bit of current CRC + /** Get the top bit of current CRC. * * @return Top bit is set high for respective data width of current CRC * Top bit for CRC width less then 8 bits will be set as 8th bit. @@ -351,7 +352,7 @@ private: return (width < 8 ? (1u << 7) : (uint32_t)(1ul << (width - 1))); } - /** Get the CRC data mask + /** Get the CRC data mask. * * @return CRC data mask is generated based on current CRC width */ @@ -360,7 +361,7 @@ private: return (width < 8 ? ((1u << 8) - 1) : (uint32_t)((uint64_t)(1ull << width) - 1)); } - /** Final value of CRC is reflected + /** Final value of CRC is reflected. * * @param data final crc value, which should be reflected * @return Reflected CRC value @@ -383,7 +384,7 @@ private: } } - /** Data bytes are reflected + /** Data bytes are reflected. * * @param data value to be reflected * @return Reflected data value @@ -405,7 +406,7 @@ private: } } - /** Bitwise CRC computation + /** Bitwise CRC computation. * * @param buffer data buffer * @param size size of the data @@ -449,7 +450,7 @@ private: return 0; } - /** CRC computation using ROM tables + /** CRC computation using ROM tables. * * @param buffer data buffer * @param size size of the data @@ -483,8 +484,7 @@ private: p_crc = (p_crc >> 4) ^ crc_table[(p_crc ^ (data[i] >> 0)) & 0xf]; p_crc = (p_crc >> 4) ^ crc_table[(p_crc ^ (data[i] >> 4)) & 0xf]; } - } - else { + } else { for (crc_data_size_t byte = 0; byte < size; byte++) { data_byte = reflect_bytes(data[byte]) ^ (p_crc >> (width - 8)); p_crc = crc_table[data_byte] ^ (p_crc << 8); @@ -495,7 +495,7 @@ private: return 0; } - /** Constructor init called from all specialized cases of constructor + /** Constructor init called from all specialized cases of constructor. * Note: All construtor common code should be in this function. */ void mbed_crc_ctor(void) @@ -547,6 +547,7 @@ private: } _mode = (_crc_table != NULL) ? TABLE : BITWISE; } +#endif }; #if defined ( __CC_ARM ) diff --git a/drivers/PortIn.h b/drivers/PortIn.h index 62e48e1c19..fbecc257e0 100644 --- a/drivers/PortIn.h +++ b/drivers/PortIn.h @@ -32,20 +32,20 @@ namespace mbed { * * Example: * @code - * // Switch on an LED if any of mbed pins 21-26 is high + * // Turn on an LED if any pins of Port2[0:5] are high * * #include "mbed.h" * - * PortIn p(Port2, 0x0000003F); // p21-p26 - * DigitalOut ind(LED4); + * PortIn p(Port2, 0x0000003F); // Port2 pins [0:5] only + * DigitalOut led(LED4); * * int main() { * while(1) { * int pins = p.read(); * if(pins) { - * ind = 1; + * led = 1; * } else { - * ind = 0; + * led = 0; * } * } * } @@ -55,10 +55,10 @@ namespace mbed { class PortIn { public: - /** Create an PortIn, connected to the specified port + /** Create a PortIn, connected to the specified port * - * @param port Port to connect to (Port0-Port5) - * @param mask A bitmask to identify which bits in the port should be included (0 - ignore) + * @param port Port to connect to (as defined in target's PortNames.h) + * @param mask Bitmask defines which port pins should be an input (0 - ignore, 1 - include) */ PortIn(PortName port, int mask = 0xFFFFFFFF) { @@ -67,10 +67,10 @@ public: core_util_critical_section_exit(); } - /** Read the value currently output on the port + /** Read the value input to the port * * @returns - * An integer with each bit corresponding to associated port pin setting + * An integer with each bit corresponding to the associated pin value */ int read() { diff --git a/drivers/PortOut.h b/drivers/PortOut.h index ccdcc25dbf..8df644e56c 100644 --- a/drivers/PortOut.h +++ b/drivers/PortOut.h @@ -25,7 +25,7 @@ namespace mbed { /** \addtogroup drivers */ -/** A multiple pin digital out +/** A multiple pin digital output * * @note Synchronization level: Interrupt safe * @@ -54,10 +54,10 @@ namespace mbed { class PortOut { public: - /** Create an PortOut, connected to the specified port + /** Create a PortOut, connected to the specified port * - * @param port Port to connect to (Port0-Port5) - * @param mask A bitmask to identify which bits in the port should be included (0 - ignore) + * @param port Port to connect to (as defined in target's PortNames.h) + * @param mask Bitmask defines which port pins are an output (0 - ignore, 1 - include) */ PortOut(PortName port, int mask = 0xFFFFFFFF) { @@ -78,7 +78,7 @@ public: /** Read the value currently output on the port * * @returns - * An integer with each bit corresponding to associated PortOut pin setting + * An integer with each bit corresponding to associated pin value */ int read() { diff --git a/drivers/PwmOut.h b/drivers/PwmOut.h index 04e0a22618..6d6f847f8f 100644 --- a/drivers/PwmOut.h +++ b/drivers/PwmOut.h @@ -32,7 +32,7 @@ namespace mbed { * * Example * @code - * // Fade a led on. + * // Gradually change the intensity of the LED. * #include "mbed.h" * * PwmOut led(LED1); @@ -71,7 +71,7 @@ public: core_util_critical_section_exit(); } - /** Set the ouput duty-cycle, specified as a percentage (float) + /** Set the output duty-cycle, specified as a percentage (float) * * @param value A floating-point value representing the output duty-cycle, * specified as a percentage. The value should lie between @@ -118,8 +118,8 @@ public: core_util_critical_section_exit(); } - /** Set the PWM period, specified in milli-seconds (int), keeping the duty cycle the same. - * @param ms Change the period of a PWM signal in milli-seconds without modifying the duty cycle + /** Set the PWM period, specified in milliseconds (int), keeping the duty cycle the same. + * @param ms Change the period of a PWM signal in milliseconds without modifying the duty cycle */ void period_ms(int ms) { @@ -128,8 +128,8 @@ public: core_util_critical_section_exit(); } - /** Set the PWM period, specified in micro-seconds (int), keeping the duty cycle the same. - * @param us Change the period of a PWM signal in micro-seconds without modifying the duty cycle + /** Set the PWM period, specified in microseconds (int), keeping the duty cycle the same. + * @param us Change the period of a PWM signal in microseconds without modifying the duty cycle */ void period_us(int us) { @@ -148,8 +148,8 @@ public: core_util_critical_section_exit(); } - /** Set the PWM pulsewidth, specified in milli-seconds (int), keeping the period the same. - * @param ms Change the pulse width of a PWM signal specified in milli-seconds + /** Set the PWM pulsewidth, specified in milliseconds (int), keeping the period the same. + * @param ms Change the pulse width of a PWM signal specified in milliseconds */ void pulsewidth_ms(int ms) { @@ -158,8 +158,8 @@ public: core_util_critical_section_exit(); } - /** Set the PWM pulsewidth, specified in micro-seconds (int), keeping the period the same. - * @param us Change the pulse width of a PWM signal specified in micro-seconds + /** Set the PWM pulsewidth, specified in microseconds (int), keeping the period the same. + * @param us Change the pulse width of a PWM signal specified in microseconds */ void pulsewidth_us(int us) { @@ -197,6 +197,7 @@ public: return read(); } +#if !(DOXYGEN_ONLY) protected: /** Lock deep sleep only if it is not yet locked */ void lock_deep_sleep() @@ -218,6 +219,7 @@ protected: pwmout_t _pwm; bool _deep_sleep_locked; +#endif }; } // namespace mbed diff --git a/drivers/QSPI.h b/drivers/QSPI.h index fc8f6b3b0f..764a1167ff 100644 --- a/drivers/QSPI.h +++ b/drivers/QSPI.h @@ -84,11 +84,14 @@ public: * @param io3 4th IO pin used for sending/receiving data during data phase of a transaction * @param sclk QSPI Clock pin * @param ssel QSPI chip select pin - * @param mode Mode specifies the SPI mode(Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1) - * default value = 0 + * @param mode Clock polarity and phase mode (0 - 3) of SPI + * (Default: Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1) * */ QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel = NC, int mode = 0); + virtual ~QSPI() + { + } /** Configure the data transmission format * @@ -96,7 +99,7 @@ public: * @param address_width Bus width used by address phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD) * @param address_size Size in bits used by address phase(Valid values are QSPI_CFG_ADDR_SIZE_8, QSPI_CFG_ADDR_SIZE_16, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_ADDR_SIZE_32) * @param alt_width Bus width used by alt phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD) - * @param alt_size Size in bits used by alt phase(Valid values are QSPI_CFG_ADDR_SIZE_8, QSPI_CFG_ADDR_SIZE_16, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_ADDR_SIZE_32) + * @param alt_size Size in bits used by alt phase(Valid values are QSPI_CFG_ALT_SIZE_8, QSPI_CFG_ALT_SIZE_16, QSPI_CFG_ALT_SIZE_24, QSPI_CFG_ALT_SIZE_32) * @param data_width Bus width used by data phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD) * @param dummy_cycles Number of dummy clock cycles to be used after alt phase * @@ -179,6 +182,7 @@ public: */ qspi_status_t command_transfer(int instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length); +#if !defined(DOXYGEN_ONLY) protected: /** Acquire exclusive access to this SPI bus */ @@ -188,12 +192,6 @@ protected: */ virtual void unlock(void); -public: - virtual ~QSPI() - { - } - -protected: qspi_t _qspi; bool acquire(void); @@ -223,6 +221,7 @@ private: * This function builds the qspi command struct to be send to Hal */ inline void _build_qspi_command(int instruction, int address, int alt); +#endif }; } // namespace mbed diff --git a/drivers/RawSerial.h b/drivers/RawSerial.h index 1ede0c8a33..bb06fe4787 100644 --- a/drivers/RawSerial.h +++ b/drivers/RawSerial.h @@ -20,6 +20,7 @@ #if defined (DEVICE_SERIAL) || defined(DOXYGEN_ONLY) +#include "mbed_toolchain.h" #include "drivers/SerialBase.h" #include "hal/serial_api.h" #include "platform/NonCopyable.h" @@ -86,8 +87,9 @@ public: */ int puts(const char *str); - int printf(const char *format, ...); + int printf(const char *format, ...) MBED_PRINTF_METHOD(1, 2); +#if !(DOXYGEN_ONLY) protected: /* Acquire exclusive access to this serial port @@ -97,6 +99,7 @@ protected: /* Release exclusive access to this serial port */ virtual void unlock(void); +#endif }; } // namespace mbed diff --git a/drivers/SPI.cpp b/drivers/SPI.cpp index fc52be754d..d679a9c0a8 100644 --- a/drivers/SPI.cpp +++ b/drivers/SPI.cpp @@ -41,9 +41,14 @@ SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) : _write_fill(SPI_FILL_CHAR) { // No lock needed in the constructor - spi_init(&_spi, mosi, miso, sclk, ssel); - _acquire(); +} + +SPI::~SPI() +{ + if (_owner == this) { + _owner = NULL; + } } void SPI::format(int bits, int mode) diff --git a/drivers/SPI.h b/drivers/SPI.h index 8d24dcc966..10efc7d0aa 100644 --- a/drivers/SPI.h +++ b/drivers/SPI.h @@ -36,39 +36,44 @@ namespace mbed { /** \addtogroup drivers */ -/** A SPI Master, used for communicating with SPI slave devices +/** A SPI Master, used for communicating with SPI slave devices. * - * The default format is set to 8-bits, mode 0, and a clock frequency of 1MHz + * The default format is set to 8-bits, mode 0, and a clock frequency of 1MHz. * * Most SPI devices will also require Chip Select and Reset signals. These - * can be controlled using DigitalOut pins + * can be controlled using DigitalOut pins. * * @note Synchronization level: Thread safe * - * Example: + * Example of how to send a byte to a SPI slave and record the response: * @code - * // Send a byte to a SPI slave, and record the response - * * #include "mbed.h" * - * // hardware ssel (where applicable) - * //SPI device(p5, p6, p7, p8); // mosi, miso, sclk, ssel + * SPI device(SPI_MOSI, SPI_MISO, SPI_SCLK) * - * // software ssel - * SPI device(p5, p6, p7); // mosi, miso, sclk - * DigitalOut cs(p8); // ssel + * DigitalOut chip_select(SPI_CS); * * int main() { - * // hardware ssel (where applicable) - * //int response = device.write(0xFF); - * * device.lock(); - * // software ssel - * cs = 0; - * int response = device.write(0xFF); - * cs = 1; - * device.unlock(); + * chip_select = 0; * + * int response = device.write(0xFF); + * + * chip_select = 1; + * device.unlock(); + * } + * @endcode + * + * Example using hardware Chip Select line: + * @code + * #include "mbed.h" + * + * SPI device(SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS) + * + * int main() { + * device.lock(); + * int response = device.write(0xFF); + * device.unlock(); * } * @endcode * @ingroup drivers @@ -77,21 +82,22 @@ class SPI : private NonCopyable { public: - /** Create a SPI master connected to the specified pins + /** Create a SPI master connected to the specified pins. * - * mosi or miso can be specified as NC if not used + * @note You can specify mosi or miso as NC if not used. * - * @param mosi SPI Master Out, Slave In pin - * @param miso SPI Master In, Slave Out pin - * @param sclk SPI Clock pin - * @param ssel SPI chip select pin + * @param mosi SPI Master Out, Slave In pin. + * @param miso SPI Master In, Slave Out pin. + * @param sclk SPI Clock pin. + * @param ssel SPI Chip Select pin. */ SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel = NC); + virtual ~SPI(); - /** Configure the data transmission format + /** Configure the data transmission format. * - * @param bits Number of bits per SPI frame (4 - 16) - * @param mode Clock polarity and phase mode (0 - 3) + * @param bits Number of bits per SPI frame (4 - 16). + * @param mode Clock polarity and phase mode (0 - 3). * * @code * mode | POL PHA @@ -104,51 +110,50 @@ public: */ void format(int bits, int mode = 0); - /** Set the spi bus clock frequency + /** Set the SPI bus clock frequency. * - * @param hz SCLK frequency in hz (default = 1MHz) + * @param hz Clock frequency in Hz (default = 1MHz). */ void frequency(int hz = 1000000); - /** Write to the SPI Slave and return the response + /** Write to the SPI Slave and return the response. * - * @param value Data to be sent to the SPI slave + * @param value Data to be sent to the SPI slave. * - * @returns - * Response from the SPI slave + * @return Response from the SPI slave. */ virtual int write(int value); - /** Write to the SPI Slave and obtain the response + /** Write to the SPI Slave and obtain the response. * * The total number of bytes sent and received will be the maximum of * tx_length and rx_length. The bytes written will be padded with the * value 0xff. * - * @param tx_buffer Pointer to the byte-array of data to write to the device - * @param tx_length Number of bytes to write, may be zero - * @param rx_buffer Pointer to the byte-array of data to read from the device - * @param rx_length Number of bytes to read, may be zero - * @returns + * @param tx_buffer Pointer to the byte-array of data to write to the device. + * @param tx_length Number of bytes to write, may be zero. + * @param rx_buffer Pointer to the byte-array of data to read from the device. + * @param rx_length Number of bytes to read, may be zero. + * @return * The number of bytes written and read from the device. This is * maximum of tx_length and rx_length. */ virtual int write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length); - /** Acquire exclusive access to this SPI bus + /** Acquire exclusive access to this SPI bus. */ virtual void lock(void); - /** Release exclusive access to this SPI bus + /** Release exclusive access to this SPI bus. */ virtual void unlock(void); - /** Set default write data + /** Set default write data. * SPI requires the master to send some data during a read operation. * Different devices may require different default byte values. * For example: A SD Card requires default bytes to be 0xFF. * - * @param data Default character to be transmitted while read operation + * @param data Default character to be transmitted during a read operation. */ void set_default_write_value(char data); @@ -156,17 +161,20 @@ public: /** Start non-blocking SPI transfer using 8bit buffers. * - * This function locks the deep sleep until any event has occurred + * This function locks the deep sleep until any event has occurred. * - * @param tx_buffer The TX buffer with data to be transfered. If NULL is passed, - * the default SPI value is sent - * @param tx_length The length of TX buffer in bytes + * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed, + * the default SPI value is sent. + * @param tx_length The length of TX buffer in bytes. * @param rx_buffer The RX buffer which is used for received data. If NULL is passed, - * received data are ignored - * @param rx_length The length of RX buffer in bytes - * @param callback The event callback function - * @param event The logical OR of events to modify. Look at spi hal header file for SPI events. - * @return Zero if the transfer has started, or -1 if SPI peripheral is busy + * received data are ignored. + * @param rx_length The length of RX buffer in bytes. + * @param callback The event callback function. + * @param event The event mask of events to modify. @see spi_api.h for SPI events. + * + * @return Operation result. + * @retval 0 If the transfer has started. + * @retval -1 If SPI peripheral is busy. */ template int transfer(const Type *tx_buffer, int tx_length, Type *rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE) @@ -178,73 +186,82 @@ public: return 0; } - /** Abort the on-going SPI transfer, and continue with transfer's in the queue if any. + /** Abort the on-going SPI transfer, and continue with transfers in the queue, if any. */ void abort_transfer(); - /** Clear the transaction buffer + /** Clear the queue of transfers. */ void clear_transfer_buffer(); - /** Clear the transaction buffer and abort on-going transfer. + /** Clear the queue of transfers and abort the on-going transfer. */ void abort_all_transfers(); - /** Configure DMA usage suggestion for non-blocking transfers + /** Configure DMA usage suggestion for non-blocking transfers. * - * @param usage The usage DMA hint for peripheral - * @return Zero if the usage was set, -1 if a transaction is on-going - */ + * @param usage The usage DMA hint for peripheral. + * + * @return Result of the operation. + * @retval 0 The usage was set. + * @retval -1 Usage cannot be set as there is an ongoing transaction. + */ int set_dma_usage(DMAUsage usage); +#if !defined(DOXYGEN_ONLY) protected: - /** SPI IRQ handler - * - */ + /** SPI interrupt handler. + */ void irq_handler_asynch(void); - /** Common transfer method + /** Start the transfer or put it on the queue. * - * @param tx_buffer The TX buffer with data to be transfered. If NULL is passed, + * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed, * the default SPI value is sent - * @param tx_length The length of TX buffer in bytes + * @param tx_length The length of TX buffer in bytes. * @param rx_buffer The RX buffer which is used for received data. If NULL is passed, - * received data are ignored - * @param rx_length The length of RX buffer in bytes - * @param bit_width The buffers element width - * @param callback The event callback function - * @param event The logical OR of events to modify - * @return Zero if the transfer has started or was added to the queue, or -1 if SPI peripheral is busy/buffer is full - */ + * received data are ignored. + * @param rx_length The length of RX buffer in bytes. + * @param bit_width The buffers element width in bits. + * @param callback The event callback function. + * @param event The event mask of events to modify. + * + * @return Operation success. + * @retval 0 A transfer was started or added to the queue. + * @retval -1 Transfer can't be added because queue is full. + */ int transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t &callback, int event); - /** + /** Put a transfer on the transfer queue. * - * @param tx_buffer The TX buffer with data to be transfered. If NULL is passed, - * the default SPI value is sent - * @param tx_length The length of TX buffer in bytes + * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed, + * the default SPI value is sent. + * @param tx_length The length of TX buffer in bytes. * @param rx_buffer The RX buffer which is used for received data. If NULL is passed, - * received data are ignored - * @param rx_length The length of RX buffer in bytes - * @param bit_width The buffers element width - * @param callback The event callback function - * @param event The logical OR of events to modify - * @return Zero if a transfer was added to the queue, or -1 if the queue is full - */ + * received data are ignored. + * @param rx_length The length of RX buffer in bytes. + * @param bit_width The buffers element width in bits. + * @param callback The event callback function. + * @param event The event mask of events to modify. + * + * @return Operation success. + * @retval 0 A transfer was added to the queue. + * @retval -1 Transfer can't be added because queue is full. + */ int queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t &callback, int event); - /** Configures a callback, spi peripheral and initiate a new transfer + /** Configure a callback, SPI peripheral, and initiate a new transfer. * - * @param tx_buffer The TX buffer with data to be transfered. If NULL is passed, - * the default SPI value is sent - * @param tx_length The length of TX buffer in bytes + * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed, + * the default SPI value is sent. + * @param tx_length The length of TX buffer in bytes. * @param rx_buffer The RX buffer which is used for received data. If NULL is passed, - * received data are ignored - * @param rx_length The length of RX buffer in bytes - * @param bit_width The buffers element width - * @param callback The event callback function - * @param event The logical OR of events to modify - */ + * received data are ignored. + * @param rx_length The length of RX buffer in bytes. + * @param bit_width The buffers element width. + * @param callback The event callback function. + * @param event The event mask of events to modify. + */ void start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t &callback, int event); private: @@ -257,49 +274,62 @@ private: #if TRANSACTION_QUEUE_SIZE_SPI - /** Start a new transaction + /** Start a new transaction. * - * @param data Transaction data - */ + * @param data Transaction data. + */ void start_transaction(transaction_t *data); - /** Dequeue a transaction - * - */ + /** Dequeue a transaction and start the transfer if there was one pending. + */ void dequeue_transaction(); + + /* Queue of pending transfers */ static CircularBuffer, TRANSACTION_QUEUE_SIZE_SPI> _transaction_buffer; #endif -#endif +#endif //!defined(DOXYGEN_ONLY) -public: - virtual ~SPI() - { - } +#endif //DEVICE_SPI_ASYNCH +#if !defined(DOXYGEN_ONLY) protected: + /* Internal SPI object identifying the resources */ spi_t _spi; #if DEVICE_SPI_ASYNCH + /* Interrupt */ CThunk _irq; + /* Interrupt handler callback */ event_callback_t _callback; + /* Current preferred DMA mode @see dma_api.h */ DMAUsage _usage; + /* Current sate of the sleep manager */ bool _deep_sleep_locked; #endif + /* Take over the physical SPI and apply our settings (thread safe) */ void aquire(void); + /* Current user of the SPI */ static SPI *_owner; + /* Used by lock and unlock for thread safety */ static SingletonPtr _mutex; + /* Size of the SPI frame */ int _bits; + /* Clock polairy and phase */ int _mode; + /* Clock frequency */ int _hz; + /* Default character used for NULL transfers */ char _write_fill; private: - /* Private acquire function without locking/unlocking - * Implemented in order to avoid duplicate locking and boost performance + /** Private acquire function without locking/unlocking. + * Implemented in order to avoid duplicate locking and boost performance. */ void _acquire(void); + +#endif //!defined(DOXYGEN_ONLY) }; } // namespace mbed diff --git a/drivers/SPISlave.h b/drivers/SPISlave.h index ec8456cb75..6ee9ba6171 100644 --- a/drivers/SPISlave.h +++ b/drivers/SPISlave.h @@ -26,19 +26,18 @@ namespace mbed { /** \addtogroup drivers */ -/** A SPI slave, used for communicating with a SPI Master device +/** A SPI slave, used for communicating with a SPI master device. * - * The default format is set to 8-bits, mode 0, and a clock frequency of 1MHz + * The default format is set to 8 bits, mode 0 and a clock frequency of 1MHz. * * @note Synchronization level: Not protected * - * Example: + * Example of how to reply to a SPI master as slave: * @code - * // Reply to a SPI master as slave * * #include "mbed.h" * - * SPISlave device(p5, p6, p7, p8); // mosi, miso, sclk, ssel + * SPISlave device(SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS); * * int main() { * device.reply(0x00); // Prime SPI with first reply @@ -57,21 +56,21 @@ class SPISlave : private NonCopyable { public: - /** Create a SPI slave connected to the specified pins + /** Create a SPI slave connected to the specified pins. * - * mosi or miso can be specified as NC if not used + * @note Either mosi or miso can be specified as NC if not used. * - * @param mosi SPI Master Out, Slave In pin - * @param miso SPI Master In, Slave Out pin - * @param sclk SPI Clock pin - * @param ssel SPI chip select pin + * @param mosi SPI Master Out, Slave In pin. + * @param miso SPI Master In, Slave Out pin. + * @param sclk SPI Clock pin. + * @param ssel SPI Chip Select pin. */ SPISlave(PinName mosi, PinName miso, PinName sclk, PinName ssel); - /** Configure the data transmission format + /** Configure the data transmission format. * - * @param bits Number of bits per SPI frame (4 - 16) - * @param mode Clock polarity and phase mode (0 - 3) + * @param bits Number of bits per SPI frame (4 - 16). + * @param mode Clock polarity and phase mode (0 - 3). * * @code * mode | POL PHA @@ -84,40 +83,47 @@ public: */ void format(int bits, int mode = 0); - /** Set the spi bus clock frequency + /** Set the SPI bus clock frequency. * - * @param hz SCLK frequency in hz (default = 1MHz) + * @param hz Clock frequency in hz (default = 1MHz). */ void frequency(int hz = 1000000); - /** Polls the SPI to see if data has been received + /** Polls the SPI to see if data has been received. * - * @returns - * 0 if no data, - * 1 otherwise + * @return Presence of received data. + * @retval 0 No data waiting. + * @retval 1 Data waiting. */ int receive(void); - /** Retrieve data from receive buffer as slave + /** Retrieve data from receive buffer as slave. * - * @returns - * the data in the receive buffer + * @return The data in the receive buffer. */ int read(void); /** Fill the transmission buffer with the value to be written out * as slave on the next received message from the master. * - * @param value the data to be transmitted next + * @param value The data to be transmitted next. */ void reply(int value); +#if !defined(DOXYGEN_ONLY) + protected: + /* Internal SPI object identifying the resources */ spi_t _spi; + /* How many bits in an SPI frame */ int _bits; + /* Clock phase and polarity */ int _mode; + /* Clock frequency */ int _hz; + +#endif //!defined(DOXYGEN_ONLY) }; } // namespace mbed diff --git a/drivers/Serial.h b/drivers/Serial.h index 7c5e536acb..1b1e6aa34e 100644 --- a/drivers/Serial.h +++ b/drivers/Serial.h @@ -63,10 +63,10 @@ public: * @param tx Transmit pin * @param rx Receive pin * @param name The name of the stream associated with this serial port (optional) - * @param baud The baud rate of the serial port (optional, defaults to MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE) + * @param baud The baud rate of the serial port (optional, defaults to MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE or 9600) * * @note - * Either tx or rx may be specified as NC if unused + * Either tx or rx may be specified as NC (Not Connected) if unused */ Serial(PinName tx, PinName rx, const char *name = NULL, int baud = MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE); @@ -78,7 +78,7 @@ public: * @param baud The baud rate of the serial port * * @note - * Either tx or rx may be specified as NC if unused + * Either tx or rx may be specified as NC (Not Connected) if unused */ Serial(PinName tx, PinName rx, int baud); @@ -99,6 +99,7 @@ public: return SerialBase::writeable(); } +#if !(DOXYGEN_ONLY) protected: virtual int _getc(); virtual int _putc(int c); @@ -106,6 +107,7 @@ protected: virtual void unlock(); PlatformMutex _mutex; +#endif }; } // namespace mbed diff --git a/drivers/SerialBase.h b/drivers/SerialBase.h index 5d7989ecb5..6eca8807ce 100644 --- a/drivers/SerialBase.h +++ b/drivers/SerialBase.h @@ -97,7 +97,7 @@ public: /** Attach a function to call whenever a serial interrupt is generated * * @param func A pointer to a void function, or 0 to set as none - * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty) + * @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty) */ void attach(Callback func, IrqType type = RxIrq); @@ -105,7 +105,7 @@ public: * * @param obj pointer to the object to call the member function on * @param method pointer to the member function to be called - * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty) + * @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty) * @deprecated * The attach function does not support cv-qualifiers. Replaced by * attach(callback(obj, method), type). @@ -123,7 +123,7 @@ public: * * @param obj pointer to the object to call the member function on * @param method pointer to the member function to be called - * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty) + * @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty) * @deprecated * The attach function does not support cv-qualifiers. Replaced by * attach(callback(obj, method), type). @@ -141,6 +141,7 @@ public: */ void send_break(); +#if !defined(DOXYGEN_ONLY) protected: /** Acquire exclusive access to this serial port @@ -150,7 +151,7 @@ protected: /** Release exclusive access to this serial port */ virtual void unlock(void); - +#endif public: #if DEVICE_SERIAL_FC @@ -167,7 +168,7 @@ public: #if DEVICE_SERIAL_ASYNCH - /** Begin asynchronous write using 8bit buffer. The completition invokes registered TX event callback + /** Begin asynchronous write using 8bit buffer. The completion invokes registered TX event callback * * This function locks the deep sleep until any event has occurred * @@ -178,7 +179,7 @@ public: */ int write(const uint8_t *buffer, int length, const event_callback_t &callback, int event = SERIAL_EVENT_TX_COMPLETE); - /** Begin asynchronous write using 16bit buffer. The completition invokes registered TX event callback + /** Begin asynchronous write using 16bit buffer. The completion invokes registered TX event callback * * This function locks the deep sleep until any event has occurred * @@ -193,7 +194,7 @@ public: */ void abort_write(); - /** Begin asynchronous reading using 8bit buffer. The completition invokes registred RX event callback. + /** Begin asynchronous reading using 8bit buffer. The completion invokes registered RX event callback. * * This function locks the deep sleep until any event has occurred * @@ -205,7 +206,7 @@ public: */ int read(uint8_t *buffer, int length, const event_callback_t &callback, int event = SERIAL_EVENT_RX_COMPLETE, unsigned char char_match = SERIAL_RESERVED_CHAR_MATCH); - /** Begin asynchronous reading using 16bit buffer. The completition invokes registred RX event callback. + /** Begin asynchronous reading using 16bit buffer. The completion invokes registered RX event callback. * * This function locks the deep sleep until any event has occurred * @@ -235,12 +236,15 @@ public: */ int set_dma_usage_rx(DMAUsage usage); +#if !defined(DOXYGEN_ONLY) protected: void start_read(void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event, unsigned char char_match); void start_write(const void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event); void interrupt_handler_asynch(void); #endif +#endif +#if !defined(DOXYGEN_ONLY) protected: SerialBase(PinName tx, PinName rx, int baud); virtual ~SerialBase(); @@ -259,7 +263,7 @@ protected: serial_t _serial; Callback _irq[IrqCnt]; int _baud; - +#endif }; } // namespace mbed diff --git a/drivers/SerialWireOutput.h b/drivers/SerialWireOutput.h index ab3e38f3a1..1e90ebc17c 100644 --- a/drivers/SerialWireOutput.h +++ b/drivers/SerialWireOutput.h @@ -14,6 +14,9 @@ * limitations under the License. */ +#ifndef MBED_SERIALWIREOUTPUT_H +#define MBED_SERIALWIREOUTPUT_H + #if defined(DEVICE_ITM) #include "hal/itm_api.h" @@ -70,4 +73,6 @@ public: } // namespace mbed -#endif +#endif // DEVICE_ITM + +#endif // MBED_SERIALWIREOUTPUT_H diff --git a/drivers/Ticker.h b/drivers/Ticker.h index e8bca7cbe9..059d6a1792 100644 --- a/drivers/Ticker.h +++ b/drivers/Ticker.h @@ -35,7 +35,7 @@ namespace mbed { * * Example: * @code - * // Toggle the blinking led after 5 seconds + * // Toggle the blinking LED after 5 seconds * * #include "mbed.h" * @@ -70,7 +70,7 @@ public: { } - // When low power ticker is in use, then do not disable deep-sleep. + // When low power ticker is in use, then do not disable deep sleep. Ticker(const ticker_data_t *data) : TimerEvent(data), _function(0), _lock_deepsleep(true) { #if DEVICE_LPTICKER @@ -106,13 +106,13 @@ public: attach(callback(obj, method), t); } - /** Attach a function to be called by the Ticker, specifying the interval in micro-seconds + /** Attach a function to be called by the Ticker, specifying the interval in microseconds * * @param func pointer to the function to be called * @param t the time between calls in micro-seconds * - * @note setting @a t to a value shorter that it takes to process the ticker callback - * will cause the system to hang. Ticker callback will be called constantly with no time + * @note setting @a t to a value shorter than it takes to process the ticker callback + * causes the system to hang. Ticker callback is called constantly with no time * for threads scheduling. * */ @@ -128,11 +128,11 @@ public: core_util_critical_section_exit(); } - /** Attach a member function to be called by the Ticker, specifying the interval in micro-seconds + /** Attach a member function to be called by the Ticker, specifying the interval in microseconds * * @param obj pointer to the object to call the member function on * @param method pointer to the member function to be called - * @param t the time between calls in micro-seconds + * @param t the time between calls in microseconds * @deprecated * The attach_us function does not support cv-qualifiers. Replaced by * attach_us(callback(obj, method), t). @@ -155,14 +155,16 @@ public: */ void detach(); +#if !defined(DOXYGEN_ONLY) protected: void setup(us_timestamp_t t); virtual void handler(); protected: - us_timestamp_t _delay; /**< Time delay (in microseconds) for re-setting the multi-shot callback. */ + us_timestamp_t _delay; /**< Time delay (in microseconds) for resetting the multishot callback. */ Callback _function; /**< Callback. */ - bool _lock_deepsleep; /**< Flag which indicates if deep-sleep should be disabled. */ + bool _lock_deepsleep; /**< Flag which indicates if deep sleep should be disabled. */ +#endif }; } // namespace mbed diff --git a/drivers/Timeout.h b/drivers/Timeout.h index e3a92cc3be..f39dcc03d1 100644 --- a/drivers/Timeout.h +++ b/drivers/Timeout.h @@ -25,7 +25,7 @@ namespace mbed { /** A Timeout is used to call a function at a point in the future * - * You can use as many seperate Timeout objects as you require. + * You can use as many separate Timeout objects as you require. * * @note Synchronization level: Interrupt safe * @@ -56,8 +56,10 @@ namespace mbed { */ class Timeout : public Ticker, private NonCopyable { +#if !defined(DOXYGEN_ONLY) protected: virtual void handler(); +#endif }; } // namespace mbed diff --git a/drivers/Timer.h b/drivers/Timer.h index 9fafad945a..9cc3586d98 100644 --- a/drivers/Timer.h +++ b/drivers/Timer.h @@ -30,7 +30,7 @@ namespace mbed { * * Example: * @code - * // Count the time to toggle a LED + * // Count the time to toggle an LED * * #include "mbed.h" * @@ -65,7 +65,7 @@ public: /** Reset the timer to 0. * - * If it was already counting, it will continue + * If it was already running, it will continue */ void reset(); @@ -75,15 +75,15 @@ public: */ float read(); - /** Get the time passed in milli-seconds + /** Get the time passed in milliseconds * - * @returns Time passed in milli seconds + * @returns Time passed in milliseconds */ int read_ms(); - /** Get the time passed in micro-seconds + /** Get the time passed in microseconds * - * @returns Time passed in micro seconds + * @returns Time passed in microseconds */ int read_us(); @@ -91,18 +91,21 @@ public: */ operator float(); - /** Get in a high resolution type the time passed in micro-seconds. + /** Get in a high resolution type the time passed in microseconds. + * Returns a 64 bit integer. */ us_timestamp_t read_high_resolution_us(); +#if !defined(DOXYGEN_ONLY) protected: us_timestamp_t slicetime(); int _running; // whether the timer is running us_timestamp_t _start; // the start time of the latest slice us_timestamp_t _time; // any accumulated time from previous slices const ticker_data_t *_ticker_data; - bool _lock_deepsleep; // flag which indicates if deep-sleep should be disabled + bool _lock_deepsleep; // flag that indicates if deep sleep should be disabled }; +#endif } // namespace mbed diff --git a/drivers/TimerEvent.h b/drivers/TimerEvent.h index 3dda439e59..87e2481cf2 100644 --- a/drivers/TimerEvent.h +++ b/drivers/TimerEvent.h @@ -43,6 +43,7 @@ public: */ virtual ~TimerEvent(); +#if !defined(DOXYGEN_ONLY) protected: // The handler called to service the timer event of the derived class virtual void handler() = 0; @@ -77,6 +78,7 @@ protected: ticker_event_t event; const ticker_data_t *_ticker_data; +#endif }; } // namespace mbed diff --git a/drivers/UARTSerial.cpp b/drivers/UARTSerial.cpp index 81a5913c52..845f0a19e8 100644 --- a/drivers/UARTSerial.cpp +++ b/drivers/UARTSerial.cpp @@ -13,15 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "drivers/UARTSerial.h" #if (DEVICE_SERIAL && DEVICE_INTERRUPTIN) -#include -#include "UARTSerial.h" #include "platform/mbed_poll.h" #if MBED_CONF_RTOS_PRESENT -#include "rtos/Thread.h" +#include "rtos/ThisThread.h" #else #include "platform/mbed_wait_api.h" #endif @@ -134,6 +133,23 @@ void UARTSerial::sigio(Callback func) core_util_critical_section_exit(); } +/* Special synchronous write designed to work from critical section, such + * as in mbed_error_vprintf. + */ +ssize_t UARTSerial::write_unbuffered(const char *buf_ptr, size_t length) +{ + while (!_txbuf.empty()) { + tx_irq(); + } + + for (size_t data_written = 0; data_written < length; data_written++) { + SerialBase::_base_putc(*buf_ptr++); + data_written++; + } + + return length; +} + ssize_t UARTSerial::write(const void *buffer, size_t length) { size_t data_written = 0; @@ -143,6 +159,10 @@ ssize_t UARTSerial::write(const void *buffer, size_t length) return 0; } + if (core_util_in_critical_section()) { + return write_unbuffered(buf_ptr, length); + } + api_lock(); // Unlike read, we should write the whole thing if blocking. POSIX only @@ -332,7 +352,7 @@ void UARTSerial::wait_ms(uint32_t millisec) * want to just sleep until next tick. */ #if MBED_CONF_RTOS_PRESENT - rtos::Thread::wait(millisec); + rtos::ThisThread::sleep_for(millisec); #else ::wait_ms(millisec); #endif diff --git a/drivers/UARTSerial.h b/drivers/UARTSerial.h index 667591bf82..792d3e0f36 100644 --- a/drivers/UARTSerial.h +++ b/drivers/UARTSerial.h @@ -238,6 +238,9 @@ private: /** Release mutex */ virtual void api_unlock(void); + /** Unbuffered write - invoked when write called from critical section */ + ssize_t write_unbuffered(const char *buf_ptr, size_t length); + /** Software serial buffers * By default buffer size is 256 for TX and 256 for RX. Configurable through mbed_app.json */ diff --git a/events/Event.h b/events/Event.h index 3f66d4f72c..dd0d8e6cf3 100644 --- a/events/Event.h +++ b/events/Event.h @@ -131,8 +131,8 @@ public: * The event is posted to the underlying queue and is executed in the * context of the event queue's dispatch loop. * - * The post function is irq safe and can act as a mechanism for moving - * events out of irq contexts. + * The post function is IRQ safe and can act as a mechanism for moving + * events out of IRQ contexts. * * @return A unique id that represents the posted event and can * be passed to EventQueue::cancel, or an id of 0 if @@ -179,7 +179,7 @@ public: * Attempts to cancel the most recently posted event. It is safe to call * cancel after an event has already been dispatched. * - * The cancel function is irq safe. + * The cancel function is IRQ safe. * * If called while the event queue's dispatch loop is active, the cancel * function does not guarantee that the event will not execute after it @@ -235,7 +235,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0 Argument to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0, the * arguments to the underlying callback. */ @@ -249,7 +249,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b1, the * arguments to the underlying callback. */ @@ -263,7 +263,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b2, the * arguments to the underlying callback. */ @@ -277,7 +277,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2,c3 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b3, the * arguments to the underlying callback. */ @@ -291,7 +291,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2,c3,c4 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b4, the * arguments to the underlying callback. */ @@ -583,8 +583,8 @@ public: * The event is posted to the underlying queue and is executed in the * context of the event queue's dispatch loop. * - * The post function is irq safe and can act as a mechanism for moving - * events out of irq contexts. + * The post function is IRQ safe and can act as a mechanism for moving + * events out of IRQ contexts. * * @param a0 Argument to pass to the event * @return A unique id that represents the posted event and can @@ -635,7 +635,7 @@ public: * Attempts to cancel the most recently posted event. It is safe to call * cancel after an event has already been dispatched. * - * The cancel function is irq safe. + * The cancel function is IRQ safe. * * If called while the event queue's dispatch loop is active, the cancel * function does not guarantee that the event will not execute after it @@ -691,7 +691,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0 Argument to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0, the * arguments to the underlying callback. */ @@ -705,7 +705,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b1, the * arguments to the underlying callback. */ @@ -719,7 +719,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b2, the * arguments to the underlying callback. */ @@ -733,7 +733,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2,c3 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b3, the * arguments to the underlying callback. */ @@ -747,7 +747,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2,c3,c4 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b4, the * arguments to the underlying callback. */ @@ -1039,8 +1039,8 @@ public: * The event is posted to the underlying queue and is executed in the * context of the event queue's dispatch loop. * - * The post function is irq safe and can act as a mechanism for moving - * events out of irq contexts. + * The post function is IRQ safe and can act as a mechanism for moving + * events out of IRQ contexts. * * @param a0,a1 Arguments to pass to the event * @return A unique id that represents the posted event and can @@ -1091,7 +1091,7 @@ public: * Attempts to cancel the most recently posted event. It is safe to call * cancel after an event has already been dispatched. * - * The cancel function is irq safe. + * The cancel function is IRQ safe. * * If called while the event queue's dispatch loop is active, the cancel * function does not guarantee that the event will not execute after it @@ -1147,7 +1147,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0 Argument to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0, the * arguments to the underlying callback. */ @@ -1161,7 +1161,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b1, the * arguments to the underlying callback. */ @@ -1175,7 +1175,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b2, the * arguments to the underlying callback. */ @@ -1189,7 +1189,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2,c3 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b3, the * arguments to the underlying callback. */ @@ -1203,7 +1203,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2,c3,c4 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b4, the * arguments to the underlying callback. */ @@ -1495,8 +1495,8 @@ public: * The event is posted to the underlying queue and is executed in the * context of the event queue's dispatch loop. * - * The post function is irq safe and can act as a mechanism for moving - * events out of irq contexts. + * The post function is IRQ safe and can act as a mechanism for moving + * events out of IRQ contexts. * * @param a0,a1,a2 Arguments to pass to the event * @return A unique id that represents the posted event and can @@ -1547,7 +1547,7 @@ public: * Attempts to cancel the most recently posted event. It is safe to call * cancel after an event has already been dispatched. * - * The cancel function is irq safe. + * The cancel function is IRQ safe. * * If called while the event queue's dispatch loop is active, the cancel * function does not guarantee that the event will not execute after it @@ -1603,7 +1603,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0 Argument to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0, the * arguments to the underlying callback. */ @@ -1617,7 +1617,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b1, the * arguments to the underlying callback. */ @@ -1631,7 +1631,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b2, the * arguments to the underlying callback. */ @@ -1645,7 +1645,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2,c3 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b3, the * arguments to the underlying callback. */ @@ -1659,7 +1659,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2,c3,c4 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b4, the * arguments to the underlying callback. */ @@ -1951,8 +1951,8 @@ public: * The event is posted to the underlying queue and is executed in the * context of the event queue's dispatch loop. * - * The post function is irq safe and can act as a mechanism for moving - * events out of irq contexts. + * The post function is IRQ safe and can act as a mechanism for moving + * events out of IRQ contexts. * * @param a0,a1,a2,a3 Arguments to pass to the event * @return A unique id that represents the posted event and can @@ -2003,7 +2003,7 @@ public: * Attempts to cancel the most recently posted event. It is safe to call * cancel after an event has already been dispatched. * - * The cancel function is irq safe. + * The cancel function is IRQ safe. * * If called while the event queue's dispatch loop is active, the cancel * function does not guarantee that the event will not execute after it @@ -2060,7 +2060,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0 Argument to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0, the * arguments to the underlying callback. */ @@ -2074,7 +2074,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b1, the * arguments to the underlying callback. */ @@ -2088,7 +2088,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b2, the * arguments to the underlying callback. */ @@ -2102,7 +2102,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2,c3 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b3, the * arguments to the underlying callback. */ @@ -2116,7 +2116,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2,c3,c4 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b4, the * arguments to the underlying callback. */ @@ -2408,8 +2408,8 @@ public: * The event is posted to the underlying queue and is executed in the * context of the event queue's dispatch loop. * - * The post function is irq safe and can act as a mechanism for moving - * events out of irq contexts. + * The post function is IRQ safe and can act as a mechanism for moving + * events out of IRQ contexts. * * @param a0,a1,a2,a3,a4 Arguments to pass to the event * @return A unique id that represents the posted event and can @@ -2460,7 +2460,7 @@ public: * Attempts to cancel the most recently posted event. It is safe to call * cancel after an event has already been dispatched. * - * The cancel function is irq safe. + * The cancel function is IRQ safe. * * If called while the event queue's dispatch loop is active, the cancel * function does not guarantee that the event will not execute after it @@ -2516,7 +2516,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0 Argument to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0, the * arguments to the underlying callback. */ @@ -2530,7 +2530,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b1, the * arguments to the underlying callback. */ @@ -2544,7 +2544,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b2, the * arguments to the underlying callback. */ @@ -2558,7 +2558,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2,c3 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b3, the * arguments to the underlying callback. */ @@ -2572,7 +2572,7 @@ public: * @param q Event queue to dispatch on * @param f Function to execute when the event is dispatched * @param c0,c1,c2,c3,c4 Arguments to bind to the callback, these arguments are - * allocated on an irq-safe allocator from the event queue's + * allocated on an IRQ-safe allocator from the event queue's * memory pool. Must be type-compatible with b0..b4, the * arguments to the underlying callback. */ diff --git a/events/EventQueue.cpp b/events/EventQueue.cpp index fae08f2957..f04917c4ef 100644 --- a/events/EventQueue.cpp +++ b/events/EventQueue.cpp @@ -14,10 +14,11 @@ * limitations under the License. */ #include "events/EventQueue.h" - #include "events/mbed_events.h" -#include "mbed.h" +using mbed::Callback; + +namespace events { EventQueue::EventQueue(unsigned event_size, unsigned char *event_pointer) { @@ -77,3 +78,4 @@ void EventQueue::chain(EventQueue *target) equeue_chain(&_equeue, 0); } } +} diff --git a/events/EventQueue.h b/events/EventQueue.h index b06b595fa7..c6930d4c50 100644 --- a/events/EventQueue.h +++ b/events/EventQueue.h @@ -74,7 +74,7 @@ public: * * When called with a finite timeout, the dispatch function is guaranteed * to terminate. When called with a timeout of 0, the dispatch function - * does not wait and is irq safe. + * does not wait and is IRQ safe. * * @param ms Time to wait for events in milliseconds, a negative * value will dispatch events indefinitely @@ -119,7 +119,7 @@ public: * * id must be valid i.e. event must have not finished executing. * - * The cancel function is irq safe. + * The cancel function is IRQ safe. * * If called while the event queue's dispatch loop is active, the cancel * function does not guarantee that the event will not execute after it @@ -136,7 +136,7 @@ public: * * id must be valid i.e. event must have not finished executing. * - * This function is irq safe. + * This function is IRQ safe. * * @param id Unique id of the event * @@ -191,8 +191,8 @@ public: * The specified callback will be executed in the context of the event * queue's dispatch loop. * - * The call function is irq safe and can act as a mechanism for moving - * events out of irq contexts. + * The call function is IRQ safe and can act as a mechanism for moving + * events out of IRQ contexts. * * @param f Function to execute in the context of the dispatch loop * @param args Arguments to pass to the callback @@ -892,8 +892,8 @@ public: * The specified callback will be executed in the context of the event * queue's dispatch loop. * - * The call_in function is irq safe and can act as a mechanism for moving - * events out of irq contexts. + * The call_in function is IRQ safe and can act as a mechanism for moving + * events out of IRQ contexts. * * @param ms Time to delay in milliseconds * @param f Function to execute in the context of the dispatch loop @@ -1199,8 +1199,8 @@ public: * The specified callback will be executed in the context of the event * queue's dispatch loop. * - * The call_every function is irq safe and can act as a mechanism for - * moving events out of irq contexts. + * The call_every function is IRQ safe and can act as a mechanism for + * moving events out of IRQ contexts. * * @param f Function to execute in the context of the dispatch loop * @param ms Period of the event in milliseconds @@ -2803,6 +2803,7 @@ public: #endif protected: + #if !defined(DOXYGEN_ONLY) template friend class Event; struct equeue _equeue; @@ -3379,6 +3380,7 @@ protected: f(c0, c1, c2, c3, c4, a0, a1, a2, a3, a4); } }; + #endif //!defined(DOXYGEN_ONLY) }; } diff --git a/events/equeue/equeue.c b/events/equeue/equeue.c index 4fc29fc6dd..4d985539da 100644 --- a/events/equeue/equeue.c +++ b/events/equeue/equeue.c @@ -23,19 +23,22 @@ // calculate the relative-difference between absolute times while // correctly handling overflow conditions -static inline int equeue_tickdiff(unsigned a, unsigned b) { +static inline int equeue_tickdiff(unsigned a, unsigned b) +{ return (int)(unsigned)(a - b); } // calculate the relative-difference between absolute times, but // also clamp to zero, resulting in only non-zero values. -static inline int equeue_clampdiff(unsigned a, unsigned b) { +static inline int equeue_clampdiff(unsigned a, unsigned b) +{ int diff = equeue_tickdiff(a, b); - return ~(diff >> (8*sizeof(int)-1)) & diff; + return ~(diff >> (8 * sizeof(int) -1)) & diff; } // Increment the unique id in an event, hiding the event from cancel -static inline void equeue_incid(equeue_t *q, struct equeue_event *e) { +static inline void equeue_incid(equeue_t *q, struct equeue_event *e) +{ e->id += 1; if ((e->id << q->npw2) == 0) { e->id = 1; @@ -44,7 +47,8 @@ static inline void equeue_incid(equeue_t *q, struct equeue_event *e) { // equeue lifetime management -int equeue_create(equeue_t *q, size_t size) { +int equeue_create(equeue_t *q, size_t size) +{ // dynamically allocate the specified buffer void *buffer = malloc(size); if (!buffer) { @@ -56,7 +60,8 @@ int equeue_create(equeue_t *q, size_t size) { return err; } -int equeue_create_inplace(equeue_t *q, size_t size, void *buffer) { +int equeue_create_inplace(equeue_t *q, size_t size, void *buffer) +{ // setup queue around provided buffer q->buffer = buffer; q->allocated = 0; @@ -99,7 +104,8 @@ int equeue_create_inplace(equeue_t *q, size_t size, void *buffer) { return 0; } -void equeue_destroy(equeue_t *q) { +void equeue_destroy(equeue_t *q) +{ // call destructors on pending events for (struct equeue_event *es = q->queue; es; es = es->next) { for (struct equeue_event *e = q->queue; e; e = e->sibling) { @@ -123,10 +129,11 @@ void equeue_destroy(equeue_t *q) { // equeue chunk allocation functions -static struct equeue_event *equeue_mem_alloc(equeue_t *q, size_t size) { +static struct equeue_event *equeue_mem_alloc(equeue_t *q, size_t size) +{ // add event overhead size += sizeof(struct equeue_event); - size = (size + sizeof(void*)-1) & ~(sizeof(void*)-1); + size = (size + sizeof(void *) -1) & ~(sizeof(void *) -1); equeue_mutex_lock(&q->memlock); @@ -162,7 +169,8 @@ static struct equeue_event *equeue_mem_alloc(equeue_t *q, size_t size) { return 0; } -static void equeue_mem_dealloc(equeue_t *q, struct equeue_event *e) { +static void equeue_mem_dealloc(equeue_t *q, struct equeue_event *e) +{ equeue_mutex_lock(&q->memlock); // stick chunk into list of chunks @@ -183,7 +191,8 @@ static void equeue_mem_dealloc(equeue_t *q, struct equeue_event *e) { equeue_mutex_unlock(&q->memlock); } -void *equeue_alloc(equeue_t *q, size_t size) { +void *equeue_alloc(equeue_t *q, size_t size) +{ struct equeue_event *e = equeue_mem_alloc(q, size); if (!e) { return 0; @@ -196,11 +205,12 @@ void *equeue_alloc(equeue_t *q, size_t size) { return e + 1; } -void equeue_dealloc(equeue_t *q, void *p) { - struct equeue_event *e = (struct equeue_event*)p - 1; +void equeue_dealloc(equeue_t *q, void *p) +{ + struct equeue_event *e = (struct equeue_event *)p - 1; if (e->dtor) { - e->dtor(e+1); + e->dtor(e + 1); } equeue_mem_dealloc(q, e); @@ -208,7 +218,8 @@ void equeue_dealloc(equeue_t *q, void *p) { // equeue scheduling functions -static int equeue_enqueue(equeue_t *q, struct equeue_event *e, unsigned tick) { +static int equeue_enqueue(equeue_t *q, struct equeue_event *e, unsigned tick) +{ // setup event and hash local id with buffer offset for unique id int id = (e->id << q->npw2) | ((unsigned char *)e - q->buffer); e->target = tick + equeue_clampdiff(e->target, tick); @@ -245,9 +256,9 @@ static int equeue_enqueue(equeue_t *q, struct equeue_event *e, unsigned tick) { // notify background timer if ((q->background.update && q->background.active) && - (q->queue == e && !e->sibling)) { + (q->queue == e && !e->sibling)) { q->background.update(q->background.timer, - equeue_clampdiff(e->target, tick)); + equeue_clampdiff(e->target, tick)); } equeue_mutex_unlock(&q->queuelock); @@ -255,10 +266,11 @@ static int equeue_enqueue(equeue_t *q, struct equeue_event *e, unsigned tick) { return id; } -static struct equeue_event *equeue_unqueue(equeue_t *q, int id) { +static struct equeue_event *equeue_unqueue(equeue_t *q, int id) +{ // decode event from unique id and check that the local id matches struct equeue_event *e = (struct equeue_event *) - &q->buffer[id & ((1 << q->npw2)-1)]; + &q->buffer[id & ((1 << q->npw2) - 1)]; equeue_mutex_lock(&q->queuelock); if (e->id != id >> q->npw2) { @@ -298,7 +310,8 @@ static struct equeue_event *equeue_unqueue(equeue_t *q, int id) { return e; } -static struct equeue_event *equeue_dequeue(equeue_t *q, unsigned target) { +static struct equeue_event *equeue_dequeue(equeue_t *q, unsigned target) +{ equeue_mutex_lock(&q->queuelock); // find all expired events and mark a new generation @@ -342,8 +355,9 @@ static struct equeue_event *equeue_dequeue(equeue_t *q, unsigned target) { return head; } -int equeue_post(equeue_t *q, void (*cb)(void*), void *p) { - struct equeue_event *e = (struct equeue_event*)p - 1; +int equeue_post(equeue_t *q, void (*cb)(void *), void *p) +{ + struct equeue_event *e = (struct equeue_event *)p - 1; unsigned tick = equeue_tick(); e->cb = cb; e->target = tick + e->target; @@ -353,7 +367,8 @@ int equeue_post(equeue_t *q, void (*cb)(void*), void *p) { return id; } -void equeue_cancel(equeue_t *q, int id) { +void equeue_cancel(equeue_t *q, int id) +{ if (!id) { return; } @@ -364,7 +379,8 @@ void equeue_cancel(equeue_t *q, int id) { } } -int equeue_timeleft(equeue_t *q, int id) { +int equeue_timeleft(equeue_t *q, int id) +{ int ret = -1; if (!id) { @@ -373,7 +389,7 @@ int equeue_timeleft(equeue_t *q, int id) { // decode event from unique id and check that the local id matches struct equeue_event *e = (struct equeue_event *) - &q->buffer[id & ((1 << q->npw2)-1)]; + &q->buffer[id & ((1 << q->npw2) - 1)]; equeue_mutex_lock(&q->queuelock); if (e->id == id >> q->npw2) { @@ -383,14 +399,16 @@ int equeue_timeleft(equeue_t *q, int id) { return ret; } -void equeue_break(equeue_t *q) { +void equeue_break(equeue_t *q) +{ equeue_mutex_lock(&q->queuelock); q->break_requested = true; equeue_mutex_unlock(&q->queuelock); equeue_sema_signal(&q->eventsema); } -void equeue_dispatch(equeue_t *q, int ms) { +void equeue_dispatch(equeue_t *q, int ms) +{ unsigned tick = equeue_tick(); unsigned timeout = tick + ms; q->background.active = false; @@ -416,7 +434,7 @@ void equeue_dispatch(equeue_t *q, int ms) { equeue_enqueue(q, e, equeue_tick()); } else { equeue_incid(q, e); - equeue_dealloc(q, e+1); + equeue_dealloc(q, e + 1); } } @@ -432,7 +450,7 @@ void equeue_dispatch(equeue_t *q, int ms) { equeue_mutex_lock(&q->queuelock); if (q->background.update && q->queue) { q->background.update(q->background.timer, - equeue_clampdiff(q->queue->target, tick)); + equeue_clampdiff(q->queue->target, tick)); } q->background.active = true; equeue_mutex_unlock(&q->queuelock); @@ -473,34 +491,39 @@ void equeue_dispatch(equeue_t *q, int ms) { // event functions -void equeue_event_delay(void *p, int ms) { - struct equeue_event *e = (struct equeue_event*)p - 1; +void equeue_event_delay(void *p, int ms) +{ + struct equeue_event *e = (struct equeue_event *)p - 1; e->target = ms; } -void equeue_event_period(void *p, int ms) { - struct equeue_event *e = (struct equeue_event*)p - 1; +void equeue_event_period(void *p, int ms) +{ + struct equeue_event *e = (struct equeue_event *)p - 1; e->period = ms; } -void equeue_event_dtor(void *p, void (*dtor)(void *)) { - struct equeue_event *e = (struct equeue_event*)p - 1; +void equeue_event_dtor(void *p, void (*dtor)(void *)) +{ + struct equeue_event *e = (struct equeue_event *)p - 1; e->dtor = dtor; } // simple callbacks struct ecallback { - void (*cb)(void*); + void (*cb)(void *); void *data; }; -static void ecallback_dispatch(void *p) { - struct ecallback *e = (struct ecallback*)p; +static void ecallback_dispatch(void *p) +{ + struct ecallback *e = (struct ecallback *)p; e->cb(e->data); } -int equeue_call(equeue_t *q, void (*cb)(void*), void *data) { +int equeue_call(equeue_t *q, void (*cb)(void *), void *data) +{ struct ecallback *e = equeue_alloc(q, sizeof(struct ecallback)); if (!e) { return 0; @@ -511,7 +534,8 @@ int equeue_call(equeue_t *q, void (*cb)(void*), void *data) { return equeue_post(q, ecallback_dispatch, e); } -int equeue_call_in(equeue_t *q, int ms, void (*cb)(void*), void *data) { +int equeue_call_in(equeue_t *q, int ms, void (*cb)(void *), void *data) +{ struct ecallback *e = equeue_alloc(q, sizeof(struct ecallback)); if (!e) { return 0; @@ -523,7 +547,8 @@ int equeue_call_in(equeue_t *q, int ms, void (*cb)(void*), void *data) { return equeue_post(q, ecallback_dispatch, e); } -int equeue_call_every(equeue_t *q, int ms, void (*cb)(void*), void *data) { +int equeue_call_every(equeue_t *q, int ms, void (*cb)(void *), void *data) +{ struct ecallback *e = equeue_alloc(q, sizeof(struct ecallback)); if (!e) { return 0; @@ -539,7 +564,8 @@ int equeue_call_every(equeue_t *q, int ms, void (*cb)(void*), void *data) { // backgrounding void equeue_background(equeue_t *q, - void (*update)(void *timer, int ms), void *timer) { + void (*update)(void *timer, int ms), void *timer) +{ equeue_mutex_lock(&q->queuelock); if (q->background.update) { q->background.update(q->background.timer, -1); @@ -550,7 +576,7 @@ void equeue_background(equeue_t *q, if (q->background.update && q->queue) { q->background.update(q->background.timer, - equeue_clampdiff(q->queue->target, equeue_tick())); + equeue_clampdiff(q->queue->target, equeue_tick())); } q->background.active = true; equeue_mutex_unlock(&q->queuelock); @@ -562,11 +588,13 @@ struct equeue_chain_context { int id; }; -static void equeue_chain_dispatch(void *p) { +static void equeue_chain_dispatch(void *p) +{ equeue_dispatch((equeue_t *)p, 0); } -static void equeue_chain_update(void *p, int ms) { +static void equeue_chain_update(void *p, int ms) +{ struct equeue_chain_context *c = (struct equeue_chain_context *)p; equeue_cancel(c->target, c->id); @@ -577,14 +605,15 @@ static void equeue_chain_update(void *p, int ms) { } } -void equeue_chain(equeue_t *q, equeue_t *target) { +void equeue_chain(equeue_t *q, equeue_t *target) +{ if (!target) { equeue_background(q, 0, 0); return; } struct equeue_chain_context *c = equeue_alloc(q, - sizeof(struct equeue_chain_context)); + sizeof(struct equeue_chain_context)); c->q = q; c->target = target; diff --git a/events/equeue/equeue_mbed.cpp b/events/equeue/equeue_mbed.cpp index 79ca4c8318..ca337df21f 100644 --- a/events/equeue/equeue_mbed.cpp +++ b/events/equeue/equeue_mbed.cpp @@ -21,18 +21,29 @@ #if defined(EQUEUE_PLATFORM_MBED) #include -#include "mbed.h" +#include +#include "platform/mbed_critical.h" +#include "drivers/Timer.h" +#include "drivers/Ticker.h" +#include "drivers/Timeout.h" +#include "drivers/LowPowerTimeout.h" +#include "drivers/LowPowerTicker.h" +#include "drivers/LowPowerTimer.h" + +using namespace mbed; // Ticker operations #if MBED_CONF_RTOS_PRESENT -unsigned equeue_tick() { +unsigned equeue_tick() +{ return osKernelGetTickCount(); } #else #if MBED_CONF_EVENTS_USE_LOWPOWER_TIMER_TICKER + #define ALIAS_TIMER LowPowerTimer #define ALIAS_TICKER LowPowerTicker #define ALIAS_TIMEOUT LowPowerTimeout @@ -45,20 +56,22 @@ unsigned equeue_tick() { static bool equeue_tick_inited = false; static volatile unsigned equeue_minutes = 0; static unsigned equeue_timer[ - (sizeof(ALIAS_TIMER)+sizeof(unsigned)-1)/sizeof(unsigned)]; + (sizeof(ALIAS_TIMER) + sizeof(unsigned) - 1) / sizeof(unsigned)]; static unsigned equeue_ticker[ - (sizeof(ALIAS_TICKER)+sizeof(unsigned)-1)/sizeof(unsigned)]; + (sizeof(ALIAS_TICKER) + sizeof(unsigned) - 1) / sizeof(unsigned)]; -static void equeue_tick_update() { - equeue_minutes += reinterpret_cast(equeue_timer)->read_ms(); - reinterpret_cast(equeue_timer)->reset(); +static void equeue_tick_update() +{ + equeue_minutes += reinterpret_cast(equeue_timer)->read_ms(); + reinterpret_cast(equeue_timer)->reset(); } -static void equeue_tick_init() { +static void equeue_tick_init() +{ MBED_STATIC_ASSERT(sizeof(equeue_timer) >= sizeof(ALIAS_TIMER), - "The equeue_timer buffer must fit the class Timer"); + "The equeue_timer buffer must fit the class Timer"); MBED_STATIC_ASSERT(sizeof(equeue_ticker) >= sizeof(ALIAS_TICKER), - "The equeue_ticker buffer must fit the class Ticker"); + "The equeue_ticker buffer must fit the class Ticker"); ALIAS_TIMER *timer = new (equeue_timer) ALIAS_TIMER; ALIAS_TICKER *ticker = new (equeue_ticker) ALIAS_TICKER; @@ -69,7 +82,8 @@ static void equeue_tick_init() { equeue_tick_inited = true; } -unsigned equeue_tick() { +unsigned equeue_tick() +{ if (!equeue_tick_inited) { equeue_tick_init(); } @@ -79,7 +93,7 @@ unsigned equeue_tick() { do { minutes = equeue_minutes; - ms = reinterpret_cast(equeue_timer)->read_ms(); + ms = reinterpret_cast(equeue_timer)->read_ms(); } while (minutes != equeue_minutes); return minutes + ms; @@ -88,14 +102,19 @@ unsigned equeue_tick() { #endif // Mutex operations -int equeue_mutex_create(equeue_mutex_t *m) { return 0; } +int equeue_mutex_create(equeue_mutex_t *m) +{ + return 0; +} void equeue_mutex_destroy(equeue_mutex_t *m) { } -void equeue_mutex_lock(equeue_mutex_t *m) { +void equeue_mutex_lock(equeue_mutex_t *m) +{ core_util_critical_section_enter(); } -void equeue_mutex_unlock(equeue_mutex_t *m) { +void equeue_mutex_unlock(equeue_mutex_t *m) +{ core_util_critical_section_exit(); } @@ -103,7 +122,8 @@ void equeue_mutex_unlock(equeue_mutex_t *m) { // Semaphore operations #ifdef MBED_CONF_RTOS_PRESENT -int equeue_sema_create(equeue_sema_t *s) { +int equeue_sema_create(equeue_sema_t *s) +{ osEventFlagsAttr_t attr; memset(&attr, 0, sizeof(attr)); attr.cb_mem = &s->mem; @@ -113,15 +133,18 @@ int equeue_sema_create(equeue_sema_t *s) { return !s->id ? -1 : 0; } -void equeue_sema_destroy(equeue_sema_t *s) { +void equeue_sema_destroy(equeue_sema_t *s) +{ osEventFlagsDelete(s->id); } -void equeue_sema_signal(equeue_sema_t *s) { +void equeue_sema_signal(equeue_sema_t *s) +{ osEventFlagsSet(s->id, 1); } -bool equeue_sema_wait(equeue_sema_t *s, int ms) { +bool equeue_sema_wait(equeue_sema_t *s, int ms) +{ if (ms < 0) { ms = osWaitForever; } @@ -132,29 +155,34 @@ bool equeue_sema_wait(equeue_sema_t *s, int ms) { #else // Semaphore operations -int equeue_sema_create(equeue_sema_t *s) { +int equeue_sema_create(equeue_sema_t *s) +{ *s = false; return 0; } -void equeue_sema_destroy(equeue_sema_t *s) { +void equeue_sema_destroy(equeue_sema_t *s) +{ } -void equeue_sema_signal(equeue_sema_t *s) { +void equeue_sema_signal(equeue_sema_t *s) +{ *s = 1; } -static void equeue_sema_timeout(equeue_sema_t *s) { +static void equeue_sema_timeout(equeue_sema_t *s) +{ *s = -1; } -bool equeue_sema_wait(equeue_sema_t *s, int ms) { +bool equeue_sema_wait(equeue_sema_t *s, int ms) +{ int signal = 0; ALIAS_TIMEOUT timeout; if (ms == 0) { return false; } else if (ms > 0) { - timeout.attach_us(callback(equeue_sema_timeout, s), (us_timestamp_t)ms*1000); + timeout.attach_us(callback(equeue_sema_timeout, s), (us_timestamp_t)ms * 1000); } core_util_critical_section_enter(); diff --git a/events/equeue/equeue_posix.c b/events/equeue/equeue_posix.c index 5d0c9309fd..02ebad794b 100644 --- a/events/equeue/equeue_posix.c +++ b/events/equeue/equeue_posix.c @@ -25,33 +25,39 @@ // Tick operations -unsigned equeue_tick(void) { +unsigned equeue_tick(void) +{ struct timeval tv; gettimeofday(&tv, 0); - return (unsigned)(tv.tv_sec*1000 + tv.tv_usec/1000); + return (unsigned)(tv.tv_sec * 1000 + tv.tv_usec / 1000); } // Mutex operations -int equeue_mutex_create(equeue_mutex_t *m) { +int equeue_mutex_create(equeue_mutex_t *m) +{ return pthread_mutex_init(m, 0); } -void equeue_mutex_destroy(equeue_mutex_t *m) { +void equeue_mutex_destroy(equeue_mutex_t *m) +{ pthread_mutex_destroy(m); } -void equeue_mutex_lock(equeue_mutex_t *m) { +void equeue_mutex_lock(equeue_mutex_t *m) +{ pthread_mutex_lock(m); } -void equeue_mutex_unlock(equeue_mutex_t *m) { +void equeue_mutex_unlock(equeue_mutex_t *m) +{ pthread_mutex_unlock(m); } // Semaphore operations -int equeue_sema_create(equeue_sema_t *s) { +int equeue_sema_create(equeue_sema_t *s) +{ int err = pthread_mutex_init(&s->mutex, 0); if (err) { return err; @@ -66,19 +72,22 @@ int equeue_sema_create(equeue_sema_t *s) { return 0; } -void equeue_sema_destroy(equeue_sema_t *s) { +void equeue_sema_destroy(equeue_sema_t *s) +{ pthread_cond_destroy(&s->cond); pthread_mutex_destroy(&s->mutex); } -void equeue_sema_signal(equeue_sema_t *s) { +void equeue_sema_signal(equeue_sema_t *s) +{ pthread_mutex_lock(&s->mutex); s->signal = true; pthread_cond_signal(&s->cond); pthread_mutex_unlock(&s->mutex); } -bool equeue_sema_wait(equeue_sema_t *s, int ms) { +bool equeue_sema_wait(equeue_sema_t *s, int ms) +{ pthread_mutex_lock(&s->mutex); if (!s->signal) { if (ms < 0) { @@ -88,8 +97,8 @@ bool equeue_sema_wait(equeue_sema_t *s, int ms) { gettimeofday(&tv, 0); struct timespec ts = { - .tv_sec = ms/1000 + tv.tv_sec, - .tv_nsec = ms*1000000 + tv.tv_usec*1000, + .tv_sec = ms / 1000 + tv.tv_sec, + .tv_nsec = ms * 1000000 + tv.tv_usec * 1000, }; pthread_cond_timedwait(&s->cond, &s->mutex, &ts); diff --git a/events/equeue/tests/prof.c b/events/equeue/tests/prof.c index 20d5ac514b..82b5c93e0c 100644 --- a/events/equeue/tests/prof.c +++ b/events/equeue/tests/prof.c @@ -113,20 +113,23 @@ static const char *prof_units; // Various test functions -void no_func(void *eh) { +void no_func(void *eh) +{ } // Actual performance tests -void baseline_prof(void) { +void baseline_prof(void) +{ prof_loop() { prof_start(); - __asm__ volatile (""); + __asm__ volatile(""); prof_stop(); } } -void equeue_tick_prof(void) { +void equeue_tick_prof(void) +{ prof_volatile(unsigned) res; prof_loop() { prof_start(); @@ -135,9 +138,10 @@ void equeue_tick_prof(void) { } } -void equeue_alloc_prof(void) { +void equeue_alloc_prof(void) +{ struct equeue q; - equeue_create(&q, 32*EQUEUE_EVENT_SIZE); + equeue_create(&q, 32 * EQUEUE_EVENT_SIZE); prof_loop() { prof_start(); @@ -150,9 +154,10 @@ void equeue_alloc_prof(void) { equeue_destroy(&q); } -void equeue_alloc_many_prof(int count) { +void equeue_alloc_many_prof(int count) +{ struct equeue q; - equeue_create(&q, count*EQUEUE_EVENT_SIZE); + equeue_create(&q, count * EQUEUE_EVENT_SIZE); void *es[count]; @@ -175,7 +180,8 @@ void equeue_alloc_many_prof(int count) { equeue_destroy(&q); } -void equeue_post_prof(void) { +void equeue_post_prof(void) +{ struct equeue q; equeue_create(&q, EQUEUE_EVENT_SIZE); @@ -192,11 +198,12 @@ void equeue_post_prof(void) { equeue_destroy(&q); } -void equeue_post_many_prof(int count) { +void equeue_post_many_prof(int count) +{ struct equeue q; - equeue_create(&q, count*EQUEUE_EVENT_SIZE); + equeue_create(&q, count * EQUEUE_EVENT_SIZE); - for (int i = 0; i < count-1; i++) { + for (int i = 0; i < count - 1; i++) { equeue_call(&q, no_func, 0); } @@ -213,7 +220,8 @@ void equeue_post_many_prof(int count) { equeue_destroy(&q); } -void equeue_post_future_prof(void) { +void equeue_post_future_prof(void) +{ struct equeue q; equeue_create(&q, EQUEUE_EVENT_SIZE); @@ -231,11 +239,12 @@ void equeue_post_future_prof(void) { equeue_destroy(&q); } -void equeue_post_future_many_prof(int count) { +void equeue_post_future_many_prof(int count) +{ struct equeue q; - equeue_create(&q, count*EQUEUE_EVENT_SIZE); + equeue_create(&q, count * EQUEUE_EVENT_SIZE); - for (int i = 0; i < count-1; i++) { + for (int i = 0; i < count - 1; i++) { equeue_call(&q, no_func, 0); } @@ -253,7 +262,8 @@ void equeue_post_future_many_prof(int count) { equeue_destroy(&q); } -void equeue_dispatch_prof(void) { +void equeue_dispatch_prof(void) +{ struct equeue q; equeue_create(&q, EQUEUE_EVENT_SIZE); @@ -268,9 +278,10 @@ void equeue_dispatch_prof(void) { equeue_destroy(&q); } -void equeue_dispatch_many_prof(int count) { +void equeue_dispatch_many_prof(int count) +{ struct equeue q; - equeue_create(&q, count*EQUEUE_EVENT_SIZE); + equeue_create(&q, count * EQUEUE_EVENT_SIZE); prof_loop() { for (int i = 0; i < count; i++) { @@ -285,7 +296,8 @@ void equeue_dispatch_many_prof(int count) { equeue_destroy(&q); } -void equeue_cancel_prof(void) { +void equeue_cancel_prof(void) +{ struct equeue q; equeue_create(&q, EQUEUE_EVENT_SIZE); @@ -300,11 +312,12 @@ void equeue_cancel_prof(void) { equeue_destroy(&q); } -void equeue_cancel_many_prof(int count) { +void equeue_cancel_many_prof(int count) +{ struct equeue q; - equeue_create(&q, count*EQUEUE_EVENT_SIZE); + equeue_create(&q, count * EQUEUE_EVENT_SIZE); - for (int i = 0; i < count-1; i++) { + for (int i = 0; i < count - 1; i++) { equeue_call(&q, no_func, 0); } @@ -319,8 +332,9 @@ void equeue_cancel_many_prof(int count) { equeue_destroy(&q); } -void equeue_alloc_size_prof(void) { - size_t size = 32*EQUEUE_EVENT_SIZE; +void equeue_alloc_size_prof(void) +{ + size_t size = 32 * EQUEUE_EVENT_SIZE; struct equeue q; equeue_create(&q, size); @@ -331,8 +345,9 @@ void equeue_alloc_size_prof(void) { equeue_destroy(&q); } -void equeue_alloc_many_size_prof(int count) { - size_t size = count*EQUEUE_EVENT_SIZE; +void equeue_alloc_many_size_prof(int count) +{ + size_t size = count * EQUEUE_EVENT_SIZE; struct equeue q; equeue_create(&q, size); @@ -346,8 +361,9 @@ void equeue_alloc_many_size_prof(int count) { equeue_destroy(&q); } -void equeue_alloc_fragmented_size_prof(int count) { - size_t size = count*EQUEUE_EVENT_SIZE; +void equeue_alloc_fragmented_size_prof(int count) +{ + size_t size = count * EQUEUE_EVENT_SIZE; struct equeue q; equeue_create(&q, size); @@ -362,11 +378,11 @@ void equeue_alloc_fragmented_size_prof(int count) { equeue_dealloc(&q, es[i]); } - for (int i = count-1; i >= 0; i--) { + for (int i = count - 1; i >= 0; i--) { es[i] = equeue_alloc(&q, (i % 4) * sizeof(int)); } - for (int i = count-1; i >= 0; i--) { + for (int i = count - 1; i >= 0; i--) { equeue_dealloc(&q, es[i]); } @@ -381,7 +397,8 @@ void equeue_alloc_fragmented_size_prof(int count) { // Entry point -int main() { +int main() +{ printf("beginning profiling...\n"); prof_baseline(baseline_prof); diff --git a/events/equeue/tests/tests.c b/events/equeue/tests/tests.c index 00758ec88f..547255b2c4 100644 --- a/events/equeue/tests/tests.c +++ b/events/equeue/tests/tests.c @@ -51,14 +51,17 @@ static int test_failure; // Test functions -void pass_func(void *eh) { +void pass_func(void *eh) +{ } -void simple_func(void *p) { +void simple_func(void *p) +{ (*(int *)p)++; } -void sloth_func(void *p) { +void sloth_func(void *p) +{ usleep(10000); (*(int *)p)++; } @@ -68,8 +71,9 @@ struct indirect { uint8_t buffer[7]; }; -void indirect_func(void *p) { - struct indirect *i = (struct indirect*)p; +void indirect_func(void *p) +{ + struct indirect *i = (struct indirect *)p; (*i->touched)++; } @@ -78,8 +82,9 @@ struct timing { unsigned delay; }; -void timing_func(void *p) { - struct timing *timing = (struct timing*)p; +void timing_func(void *p) +{ + struct timing *timing = (struct timing *)p; unsigned tick = equeue_tick(); unsigned t1 = timing->delay; @@ -95,8 +100,9 @@ struct fragment { struct timing timing; }; -void fragment_func(void *p) { - struct fragment *fragment = (struct fragment*)p; +void fragment_func(void *p) +{ + struct fragment *fragment = (struct fragment *)p; timing_func(&fragment->timing); struct fragment *nfragment = equeue_alloc(fragment->q, fragment->size); @@ -114,7 +120,8 @@ struct cancel { int id; }; -void cancel_func(void *p) { +void cancel_func(void *p) +{ struct cancel *cancel = (struct cancel *)p; equeue_cancel(cancel->q, cancel->id); } @@ -125,7 +132,8 @@ struct nest { void *data; }; -void nest_func(void *p) { +void nest_func(void *p) +{ struct nest *nest = (struct nest *)p; equeue_call(nest->q, nest->cb, nest->data); @@ -134,7 +142,8 @@ void nest_func(void *p) { // Simple call tests -void simple_call_test(void) { +void simple_call_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -147,7 +156,8 @@ void simple_call_test(void) { equeue_destroy(&q); } -void simple_call_in_test(void) { +void simple_call_in_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -162,7 +172,8 @@ void simple_call_in_test(void) { equeue_destroy(&q); } -void simple_call_every_test(void) { +void simple_call_every_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -177,7 +188,8 @@ void simple_call_every_test(void) { equeue_destroy(&q); } -void simple_post_test(void) { +void simple_post_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -197,7 +209,8 @@ void simple_post_test(void) { } // Misc tests -void destructor_test(void) { +void destructor_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -253,7 +266,8 @@ void destructor_test(void) { test_assert(touched == 3); } -void allocation_failure_test(void) { +void allocation_failure_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -269,19 +283,20 @@ void allocation_failure_test(void) { equeue_destroy(&q); } -void cancel_test(int N) { +void cancel_test(int N) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); bool touched = false; - int *ids = malloc(N*sizeof(int)); + int *ids = malloc(N * sizeof(int)); for (int i = 0; i < N; i++) { ids[i] = equeue_call(&q, simple_func, &touched); } - for (int i = N-1; i >= 0; i--) { + for (int i = N - 1; i >= 0; i--) { equeue_cancel(&q, ids[i]); } @@ -293,7 +308,8 @@ void cancel_test(int N) { equeue_destroy(&q); } -void cancel_inflight_test(void) { +void cancel_inflight_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -328,7 +344,8 @@ void cancel_inflight_test(void) { equeue_destroy(&q); } -void cancel_unnecessarily_test(void) { +void cancel_unnecessarily_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -356,7 +373,8 @@ void cancel_unnecessarily_test(void) { equeue_destroy(&q); } -void loop_protect_test(void) { +void loop_protect_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -376,7 +394,8 @@ void loop_protect_test(void) { equeue_destroy(&q); } -void break_test(void) { +void break_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -391,7 +410,8 @@ void break_test(void) { equeue_destroy(&q); } -void break_no_windup_test(void) { +void break_no_windup_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -411,7 +431,8 @@ void break_no_windup_test(void) { equeue_destroy(&q); } -void period_test(void) { +void period_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -425,7 +446,8 @@ void period_test(void) { equeue_destroy(&q); } -void nested_test(void) { +void nested_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -462,7 +484,8 @@ void nested_test(void) { equeue_destroy(&q); } -void sloth_test(void) { +void sloth_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -483,13 +506,15 @@ void sloth_test(void) { equeue_destroy(&q); } -void *multithread_thread(void *p) { +void *multithread_thread(void *p) +{ equeue_t *q = (equeue_t *)p; equeue_dispatch(q, -1); return 0; } -void multithread_test(void) { +void multithread_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -511,11 +536,13 @@ void multithread_test(void) { equeue_destroy(&q); } -void background_func(void *p, int ms) { +void background_func(void *p, int ms) +{ *(unsigned *)p = ms; } -void background_test(void) { +void background_test(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -542,7 +569,8 @@ void background_test(void) { test_assert(ms == -1); } -void chain_test(void) { +void chain_test(void) +{ equeue_t q1; int err = equeue_create(&q1, 2048); test_assert(!err); @@ -582,7 +610,8 @@ void chain_test(void) { equeue_destroy(&q2); } -void unchain_test(void) { +void unchain_test(void) +{ equeue_t q1; int err = equeue_create(&q1, 2048); test_assert(!err); @@ -616,9 +645,10 @@ void unchain_test(void) { } // Barrage tests -void simple_barrage_test(int N) { +void simple_barrage_test(int N) +{ equeue_t q; - int err = equeue_create(&q, N*(EQUEUE_EVENT_SIZE+sizeof(struct timing))); + int err = equeue_create(&q, N * (EQUEUE_EVENT_SIZE + sizeof(struct timing))); test_assert(!err); for (int i = 0; i < N; i++) { @@ -626,7 +656,7 @@ void simple_barrage_test(int N) { test_assert(timing); timing->tick = equeue_tick(); - timing->delay = (i+1)*100; + timing->delay = (i + 1) * 100; equeue_event_delay(timing, timing->delay); equeue_event_period(timing, timing->delay); @@ -634,33 +664,34 @@ void simple_barrage_test(int N) { test_assert(id); } - equeue_dispatch(&q, N*100); + equeue_dispatch(&q, N * 100); equeue_destroy(&q); } -void fragmenting_barrage_test(int N) { +void fragmenting_barrage_test(int N) +{ equeue_t q; int err = equeue_create(&q, - 2*N*(EQUEUE_EVENT_SIZE+sizeof(struct fragment)+N*sizeof(int))); + 2 * N * (EQUEUE_EVENT_SIZE + sizeof(struct fragment) + N * sizeof(int))); test_assert(!err); for (int i = 0; i < N; i++) { - size_t size = sizeof(struct fragment) + i*sizeof(int); + size_t size = sizeof(struct fragment) + i * sizeof(int); struct fragment *fragment = equeue_alloc(&q, size); test_assert(fragment); fragment->q = &q; fragment->size = size; fragment->timing.tick = equeue_tick(); - fragment->timing.delay = (i+1)*100; + fragment->timing.delay = (i + 1) * 100; equeue_event_delay(fragment, fragment->timing.delay); int id = equeue_post(&q, fragment_func, fragment); test_assert(id); } - equeue_dispatch(&q, N*100); + equeue_dispatch(&q, N * 100); equeue_destroy(&q); } @@ -671,20 +702,22 @@ struct ethread { int ms; }; -static void *ethread_dispatch(void *p) { - struct ethread *t = (struct ethread*)p; +static void *ethread_dispatch(void *p) +{ + struct ethread *t = (struct ethread *)p; equeue_dispatch(t->q, t->ms); return 0; } -void multithreaded_barrage_test(int N) { +void multithreaded_barrage_test(int N) +{ equeue_t q; - int err = equeue_create(&q, N*(EQUEUE_EVENT_SIZE+sizeof(struct timing))); + int err = equeue_create(&q, N * (EQUEUE_EVENT_SIZE + sizeof(struct timing))); test_assert(!err); struct ethread t; t.q = &q; - t.ms = N*100; + t.ms = N * 100; err = pthread_create(&t.thread, 0, ethread_dispatch, &t); test_assert(!err); @@ -693,7 +726,7 @@ void multithreaded_barrage_test(int N) { test_assert(timing); timing->tick = equeue_tick(); - timing->delay = (i+1)*100; + timing->delay = (i + 1) * 100; equeue_event_delay(timing, timing->delay); equeue_event_period(timing, timing->delay); @@ -707,20 +740,21 @@ void multithreaded_barrage_test(int N) { equeue_destroy(&q); } -struct count_and_queue -{ +struct count_and_queue { int p; - equeue_t* q; + equeue_t *q; }; -void simple_breaker(void *p) { - struct count_and_queue* caq = (struct count_and_queue*)p; +void simple_breaker(void *p) +{ + struct count_and_queue *caq = (struct count_and_queue *)p; equeue_break(caq->q); usleep(10000); caq->p++; } -void break_request_cleared_on_timeout(void) { +void break_request_cleared_on_timeout(void) +{ equeue_t q; int err = equeue_create(&q, 2048); test_assert(!err); @@ -745,7 +779,8 @@ void break_request_cleared_on_timeout(void) { equeue_destroy(&q); } -int main() { +int main() +{ printf("beginning tests...\n"); test_run(simple_call_test); diff --git a/events/mbed_shared_queues.cpp b/events/mbed_shared_queues.cpp index b227d8d850..1fc6a079b9 100644 --- a/events/mbed_shared_queues.cpp +++ b/events/mbed_shared_queues.cpp @@ -15,7 +15,11 @@ */ #include "events/mbed_shared_queues.h" -#include "mbed.h" + +#ifdef MBED_CONF_RTOS_PRESENT +#include "rtos/Thread.h" +using rtos::Thread; +#endif using namespace events; @@ -28,13 +32,13 @@ namespace mbed { */ template -EventQueue *do_shared_event_queue_with_thread() +EventQueue *do_shared_event_queue_with_thread(const char *name) { static uint64_t queue_buffer[QueueSize / sizeof(uint64_t)]; static EventQueue queue(sizeof queue_buffer, (unsigned char *) queue_buffer); static uint64_t stack[StackSize / sizeof(uint64_t)]; - static Thread thread(Priority, StackSize, (unsigned char *) stack); + static Thread thread(Priority, StackSize, (unsigned char *) stack, name); Thread::State state = thread.get_state(); if (state == Thread::Inactive || state == Thread::Deleted) { @@ -58,14 +62,14 @@ EventQueue *mbed_event_queue() return &queue; #else - return do_shared_event_queue_with_thread(); + return do_shared_event_queue_with_thread("shared_event_queue"); #endif } #ifdef MBED_CONF_RTOS_PRESENT EventQueue *mbed_highprio_event_queue() { - return do_shared_event_queue_with_thread(); + return do_shared_event_queue_with_thread("shared_highprio_event_queue"); } #endif diff --git a/events/mbed_shared_queues.h b/events/mbed_shared_queues.h index fea0d0000f..eb8d91e791 100644 --- a/events/mbed_shared_queues.h +++ b/events/mbed_shared_queues.h @@ -41,9 +41,9 @@ namespace mbed { * If an RTOS is not present or the configuration option * `events.shared-dispatch-from-application` is set to true, then this * does not create a dedicated dispatch thread - instead the application is - * expected to run the EventQueue's dispatch, eg from main. This is necessary - * for the event loop to work without an RTOS, or an RTOS system can can save - * memory by reusing the main stack. + * expected to run the EventQueue's dispatch, for example from main. This is + * necessary for the event loop to work without an RTOS, or an RTOS system can + * save memory by reusing the main stack. * * @note * mbed_event_queue is not itself IRQ safe. To use the mbed_event_queue in @@ -75,7 +75,7 @@ events::EventQueue *mbed_event_queue(); * @note * mbed_highprio_event_queue is not itself IRQ safe. To use the * mbed_highprio_event_queue in interrupt context, you must first call - * `mbed_event_queue()` in threaded context and store the pointer for + * `mbed_highprio_event_queue()` in threaded context and store the pointer for * later use. * * @return pointer to high-priority event queue diff --git a/features/FEATURE_BLE/DOXYGEN_FRONTPAGE.md b/features/FEATURE_BLE/DOXYGEN_FRONTPAGE_BLE.md similarity index 100% rename from features/FEATURE_BLE/DOXYGEN_FRONTPAGE.md rename to features/FEATURE_BLE/DOXYGEN_FRONTPAGE_BLE.md diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h index e4eeafba1d..fe3cc0e348 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h @@ -30,7 +30,7 @@ #include "CordioPalGenericAccessService.h" #include "ble/generic/GenericGap.h" #include "ble/generic/GenericSecurityManager.h" -#include "ble/pal/SimpleEventQueue.h" +#include "SimpleEventQueue.h" namespace ble { namespace vendor { @@ -152,7 +152,7 @@ private: } initialization_status; ::BLE::InstanceID_t instanceID; - mutable pal::SimpleEventQueue _event_queue; + mutable SimpleEventQueue _event_queue; class SigningEventMonitorProxy : public pal::SigningEventMonitor { public: diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h index f882fa98ce..6f102d05d9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h @@ -222,8 +222,8 @@ private: void add_generic_attribute_service(); void* alloc_block(size_t block_size); GattCharacteristic* get_auth_char(uint16_t value_handle); - bool get_cccd_id(GattAttribute::Handle_t cccd_handle, uint8_t& idx) const; - bool has_cccd(GattAttribute::Handle_t char_handle) const; + bool get_cccd_index_by_cccd_handle(GattAttribute::Handle_t cccd_handle, uint8_t& idx) const; + bool get_cccd_index_by_value_handle(GattAttribute::Handle_t char_handle, uint8_t& idx) const; bool is_update_authorized(Gap::Handle_t connection, GattAttribute::Handle_t value_handle); struct alloc_block_t { diff --git a/features/FEATURE_BLE/ble/pal/SimpleEventQueue.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/SimpleEventQueue.h similarity index 83% rename from features/FEATURE_BLE/ble/pal/SimpleEventQueue.h rename to features/FEATURE_BLE/targets/TARGET_CORDIO/SimpleEventQueue.h index 84ccacfd48..c84063205e 100644 --- a/features/FEATURE_BLE/ble/pal/SimpleEventQueue.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/SimpleEventQueue.h @@ -23,12 +23,13 @@ #include "ble/BLE.h" namespace ble { -namespace pal { +namespace vendor { +namespace cordio { /** * Simple implementation of the pal::EventQueue. */ -struct SimpleEventQueue : EventQueue { +struct SimpleEventQueue : pal::EventQueue { typedef mbed::Callback event_t; @@ -51,7 +52,7 @@ struct SimpleEventQueue : EventQueue { * * @param ble_id Id of the BLE instance using that event queue. */ - void initialize(BLEInstanceBase* ble_base, BLE::InstanceID_t ble_id) + void initialize(BLEInstanceBase* ble_base, ::BLE::InstanceID_t ble_id) { _ble_base = ble_base; _ble_instance_id = ble_id; @@ -73,8 +74,12 @@ struct SimpleEventQueue : EventQueue { if (_ble_base == NULL) { return false; } - - EventNode* next = new (std::nothrow) EventNode(event); + void* event_buf = WsfBufAlloc(sizeof(EventNode)); + MBED_ASSERT(event_buf != NULL); + if (event_buf == NULL) { + return false; + } + EventNode* next = new(event_buf) EventNode(event); if (next == NULL) { return false; } @@ -102,7 +107,8 @@ struct SimpleEventQueue : EventQueue { { while (_events) { EventNode* next = _events->next; - delete _events; + _events->~EventNode(); + WsfBufFree(_events); _events = next; } } @@ -115,7 +121,8 @@ struct SimpleEventQueue : EventQueue { while (_events) { EventNode* next = _events->next; _events->event(); - delete _events; + _events->~EventNode(); + WsfBufFree(_events); _events = next; } } @@ -133,11 +140,12 @@ private: } BLEInstanceBase* _ble_base; - BLE::InstanceID_t _ble_instance_id; + ::BLE::InstanceID_t _ble_instance_id; EventNode* _events; }; -} // namespace pal +} // namespace cordio +} // namespace vendor } // namespace ble #endif /* BLE_PAL_SIMPLE_EVENT_QUEUE_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp index af13e72db3..4e1b5bad68 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp @@ -560,7 +560,7 @@ ble_error_t GattServer::read( ) { // Check to see if this is a CCCD uint8_t cccd_index; - if (get_cccd_id(att_handle, cccd_index)) { + if (get_cccd_index_by_cccd_handle(att_handle, cccd_index)) { if (connection == DM_CONN_ID_NONE) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } @@ -588,7 +588,7 @@ ble_error_t GattServer::write( // Check to see if this is a CCCD, if it is the case update the value for all // connections uint8_t cccd_index; - if (get_cccd_id(att_handle, cccd_index)) { + if (get_cccd_index_by_cccd_handle(att_handle, cccd_index)) { if (len != sizeof(uint16_t)) { return BLE_ERROR_INVALID_PARAM; } @@ -615,7 +615,7 @@ ble_error_t GattServer::write( } // return if the update does not have to be propagated to peers - if (local_only || !has_cccd(att_handle)) { + if (local_only || !get_cccd_index_by_value_handle(att_handle, cccd_index)) { return BLE_ERROR_NONE; } @@ -660,7 +660,7 @@ ble_error_t GattServer::write( ) { // Check to see if this is a CCCD uint8_t cccd_index; - if (get_cccd_id(att_handle, cccd_index)) { + if (get_cccd_index_by_cccd_handle(att_handle, cccd_index)) { if ((connection == DM_CONN_ID_NONE) || (len != 2)) { // CCCDs are always 16 bits return BLE_ERROR_PARAM_OUT_OF_RANGE; } @@ -677,7 +677,7 @@ ble_error_t GattServer::write( } // return if the update does not have to be propagated to peers - if (local_only || !has_cccd(att_handle)) { + if (local_only || !get_cccd_index_by_value_handle(att_handle, cccd_index)) { return BLE_ERROR_NONE; } @@ -1211,7 +1211,7 @@ GattCharacteristic* GattServer::get_auth_char(uint16_t value_handle) return NULL; } -bool GattServer::get_cccd_id(GattAttribute::Handle_t cccd_handle, uint8_t& idx) const +bool GattServer::get_cccd_index_by_cccd_handle(GattAttribute::Handle_t cccd_handle, uint8_t& idx) const { for (idx = 0; idx < cccd_cnt; idx++) { if (cccd_handle == cccds[idx].handle) { @@ -1221,10 +1221,10 @@ bool GattServer::get_cccd_id(GattAttribute::Handle_t cccd_handle, uint8_t& idx) return false; } -bool GattServer::has_cccd(GattAttribute::Handle_t char_handle) const +bool GattServer::get_cccd_index_by_value_handle(GattAttribute::Handle_t char_handle, uint8_t& idx) const { - for (uint8_t cccd_index = 0; cccd_index < cccd_cnt; ++cccd_index) { - if (char_handle == cccd_handles[cccd_index]) { + for (idx = 0; idx < cccd_cnt; ++idx) { + if (char_handle == cccd_handles[idx]) { return true; } } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp index 7fca33e470..ed14d1920d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp @@ -334,8 +334,12 @@ ble_error_t Gap::set_address_resolution( } ble_error_t Gap::read_phy(connection_handle_t connection) { - DmReadPhy(connection); - return BLE_ERROR_NONE; + if (is_feature_supported(ControllerSupportedFeatures_t::LE_2M_PHY) + || is_feature_supported(ControllerSupportedFeatures_t::LE_CODED_PHY)) { + DmReadPhy(connection); + return BLE_ERROR_NONE; + } + return BLE_ERROR_NOT_IMPLEMENTED; } ble_error_t Gap::set_preferred_phys( diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_ODIN_W2/HCIDriver.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO_ODIN_W2/HCIDriver.cpp new file mode 100644 index 0000000000..fe5fbdc4ab --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_ODIN_W2/HCIDriver.cpp @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2018 ARM Limited + * + * 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. + */ + +#include "CordioBLE.h" +#include "CordioHCIDriver.h" +#include "hci_defs.h" +#include "hci_api.h" +#include "hci_cmd.h" +#include "hci_core.h" +#include "bstream.h" +#include "wsf_buf.h" +#include +#include "hci_mbed_os_adaptation.h" +#include "H4TransportDriver.h" +#include "OdinCordioInterface.h" + +namespace ble { +namespace vendor { +namespace odin_w2 { + +class HCIDriver : public cordio::CordioHCIDriver { +public: + HCIDriver(cordio::CordioHCITransportDriver &transport_driver, PinName shutdown_name, PinName hci_rts_name) : + cordio::CordioHCIDriver(transport_driver), + shutdown(shutdown_name, 0), + hci_rts(hci_rts_name, 0), + service_pack_index(0), + service_pack_transfered(false) { + }; + + virtual void do_initialize(); + + virtual void do_terminate(); + + virtual void start_reset_sequence(); + + virtual void handle_reset_sequence(uint8_t *pMsg); + +private: + void start_service_pack_transfer(void) + { + service_pack_index = 0; + service_pack_transfered = false; + send_service_pack_command(); + } + + void send_service_pack_command(void) + { + uint16_t cmd_len = odin_service_pack[service_pack_index + HCI_CMD_HDR_LEN]; + cmd_opcode_ack_expected = (odin_service_pack[service_pack_index + 2] << 8) | odin_service_pack[service_pack_index + 1]; + uint8_t *pBuf = hciCmdAlloc(cmd_opcode_ack_expected, cmd_len); + if (pBuf) { + memcpy(pBuf, odin_service_pack + service_pack_index + 1, cmd_len + HCI_CMD_HDR_LEN); + hciCmdSend(pBuf); + } else { + printf("Error cannot allocate memory for the buffer"); + } + } + + void ack_service_pack_command(uint16_t opcode, uint8_t *msg) + { + /* check if response opcode is same as expected command opcode */ + MBED_ASSERT (cmd_opcode_ack_expected == opcode); + + /* update service pack index */ + service_pack_index += (1 + HCI_CMD_HDR_LEN + odin_service_pack[service_pack_index + HCI_CMD_HDR_LEN]); + + if (service_pack_index < service_pack_size) + send_service_pack_command(); + else if (opcode == HCID_VS_WRITE_BD_ADDR) { + /* send an HCI Reset command to start the sequence */ + HciResetCmd(); + service_pack_transfered = true; + } else { + /* send BT device hardware address write command */ + send_hci_vs_cmd(HCID_VS_WRITE_BD_ADDR); + cmd_opcode_ack_expected = HCID_VS_WRITE_BD_ADDR; + } + } + + void hci_read_resolving_list_size(void) + { + /* if LL Privacy is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_PRIVACY) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_PRIVACY)) { + /* send next command in sequence */ + HciLeReadResolvingListSize(); + } else { + hciCoreCb.resListSize = 0; + + /* send next command in sequence */ + hci_read_max_data_len(); + } + } + + void hci_read_max_data_len(void) + { + /* if LE Data Packet Length Extensions is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_DATA_LEN_EXT) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_DATA_LEN_EXT)) { + /* send next command in sequence */ + HciLeReadMaxDataLen(); + } else { + /* send next command in sequence */ + HciLeRandCmd(); + } + } + + DigitalOut shutdown; // power/shutdown pin for bt device + DigitalOut hci_rts; // request to sent pin + size_t service_pack_index; // Index of command to be recently sent over hci + bool service_pack_transfered; // Flag to notify if service pack is completely transferred or not + uint16_t cmd_opcode_ack_expected; // Command against which acknowledgment is expected + uint32_t service_pack_size; // size of service pack + char *odin_service_pack ; // Service pack needs to be provided by driver + vs_cmd_send_t send_hci_vs_cmd ; // callback function to call vendor specific call handler + +}; + +} // namespace odin_w2 +} // namespace vendor +} // namespace ble + +void ble::vendor::odin_w2::HCIDriver::do_initialize() +{ + cordio_callback_s callback; + + hci_rts = 1; // Flow Control is OFF + + shutdown = 0; // BT Power is OFF + wait_ms(20); + shutdown = 1; // BT Power is ON + wait_ms(500); + + hci_rts = 0; // Flow Control is ON + + /* ODIN ble driver initialization function */ + cbCordio_Btinit(&callback); + + odin_service_pack = callback.Service_pack; + send_hci_vs_cmd = callback.vs_command_callback; + service_pack_size = callback.service_pack_size; +} + +void ble::vendor::odin_w2::HCIDriver::do_terminate() +{ + +} + +void ble::vendor::odin_w2::HCIDriver::start_reset_sequence() +{ + /* Update baudrate of ble to speed up setup time */ + send_hci_vs_cmd(HCID_VS_UPDATE_UART_BAUD_RATE); + +} + +void ble::vendor::odin_w2::HCIDriver::handle_reset_sequence(uint8_t *pMsg) +{ + uint16_t opcode; + static uint8_t randCnt; + + /* if event is a command complete event */ + if (*pMsg == HCI_CMD_CMPL_EVT) { + /* parse parameters */ + pMsg += HCI_EVT_HDR_LEN; + pMsg++; /* skip num packets */ + BSTREAM_TO_UINT16(opcode, pMsg); + pMsg++; /* skip status */ + + if (opcode == HCID_VS_UPDATE_UART_BAUD_RATE) { + update_uart_baud_rate(); + start_service_pack_transfer(); + return; + } + + if (service_pack_transfered == false) { + ack_service_pack_command(opcode, pMsg); + return; + } + + /* decode opcode */ + switch (opcode) { + + case HCI_OPCODE_RESET: + /* Send (fast and slow) clock configuration command */ + send_hci_vs_cmd(HCID_VS_FAST_CLOCK_CONFIG_BTIP); + break; + + case HCID_VS_FAST_CLOCK_CONFIG_BTIP: + /* Send deep-sleep behavior control command (setting retransmission, inactivity and rts pulse width for Bt) */ + send_hci_vs_cmd(HCID_VS_HCILL_PARS_CFG); + break; + + case HCID_VS_HCILL_PARS_CFG: + /* Send sleep mode configuration command */ + send_hci_vs_cmd(HCID_VS_SLEEP_PROTOCOLS_CFG); + break; + + case HCID_VS_SLEEP_PROTOCOLS_CFG: + /* initialize rand command count */ + randCnt = 0; + + /* send next command in sequence */ + HciSetEventMaskCmd((uint8_t *)hciEventMask); + break; + + case HCI_OPCODE_SET_EVENT_MASK: + /* send next command in sequence */ + HciLeSetEventMaskCmd((uint8_t *)hciLeEventMask); + break; + + case HCI_OPCODE_LE_SET_EVENT_MASK: + /* send next command in sequence */ + HciSetEventMaskPage2Cmd((uint8_t *)hciEventMaskPage2); + break; + + case HCI_OPCODE_SET_EVENT_MASK_PAGE2: + /* send next command in sequence */ + HciReadBdAddrCmd(); + break; + + case HCI_OPCODE_READ_BD_ADDR: + /* parse and store event parameters */ + BdaCpy(hciCoreCb.bdAddr, pMsg); + + /* send next command in sequence */ + HciLeReadBufSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_BUF_SIZE: + /* parse and store event parameters */ + BSTREAM_TO_UINT16(hciCoreCb.bufSize, pMsg); + BSTREAM_TO_UINT8(hciCoreCb.numBufs, pMsg); + + /* initialize ACL buffer accounting */ + hciCoreCb.availBufs = hciCoreCb.numBufs; + + /* send next command in sequence */ + HciLeReadSupStatesCmd(); + break; + + case HCI_OPCODE_LE_READ_SUP_STATES: + /* parse and store event parameters */ + memcpy(hciCoreCb.leStates, pMsg, HCI_LE_STATES_LEN); + + /* send next command in sequence */ + HciLeReadWhiteListSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_WHITE_LIST_SIZE: + /* parse and store event parameters */ + BSTREAM_TO_UINT8(hciCoreCb.whiteListSize, pMsg); + + /* send next command in sequence */ + HciLeReadLocalSupFeatCmd(); + break; + + case HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT: + /* parse and store event parameters */ + BSTREAM_TO_UINT16(hciCoreCb.leSupFeat, pMsg); + + /* send next command in sequence */ + hci_read_resolving_list_size(); + break; + + case HCI_OPCODE_LE_READ_RES_LIST_SIZE: + /* parse and store event parameters */ + BSTREAM_TO_UINT8(hciCoreCb.resListSize, pMsg); + + /* send next command in sequence */ + hci_read_max_data_len(); + break; + + case HCI_OPCODE_LE_READ_MAX_DATA_LEN: + uint16_t maxTxOctets; + uint16_t maxTxTime; + + BSTREAM_TO_UINT16(maxTxOctets, pMsg); + BSTREAM_TO_UINT16(maxTxTime, pMsg); + + /* use Controller's maximum supported payload octets and packet duration times + * for transmission as Host's suggested values for maximum transmission number + * of payload octets and maximum packet transmission time for new connections. + */ + HciLeWriteDefDataLen(maxTxOctets, maxTxTime); + break; + + case HCI_OPCODE_LE_WRITE_DEF_DATA_LEN: + if (hciCoreCb.extResetSeq) { + /* send first extended command */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } else { + /* initialize extended parameters */ + hciCoreCb.maxAdvDataLen = 0; + hciCoreCb.numSupAdvSets = 0; + hciCoreCb.perAdvListSize = 0; + + /* send next command in sequence */ + HciLeRandCmd(); + } + break; + + case HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN: + case HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS: + case HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE: + if (hciCoreCb.extResetSeq) { + /* send next extended command in sequence */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } + break; + + case HCI_OPCODE_LE_RAND: + /* check if need to send second rand command */ + if (randCnt < (HCI_RESET_RAND_CNT - 1)) { + randCnt++; + HciLeRandCmd(); + } else { + signal_reset_sequence_done(); + } + break; + + default: + break; + } + } +} + +ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver() { + static ble::vendor::cordio::H4TransportDriver transport_driver (/* cbCFG_PIO_PIN_BT_HCI_TX */ PG_14, + /* cbCFG_PIO_PIN_BT_HCI_RX */ PC_7, + /* cbCFG_PIO_PIN_BT_HCI_CTS */ PG_15, + /* cbCFG_PIO_PIN_BT_HCI_RTS */ PG_12, + 115200); + static ble::vendor::odin_w2::HCIDriver hci_driver ( transport_driver, + /* cbCFG_PIO_PIN_BT_ENABLE */ PG_7, + /* cbCFG_PIO_PIN_BT_HCI_RTS */ PG_12); + + return hci_driver; +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO_ODIN_W2/OdinCordioInterface.h b/features/FEATURE_BLE/targets/TARGET_CORDIO_ODIN_W2/OdinCordioInterface.h new file mode 100644 index 0000000000..d84756c8ff --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO_ODIN_W2/OdinCordioInterface.h @@ -0,0 +1,45 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef ODIN_CORDIO_INTF_H +#define ODIN_CORDIO_INTF_H + +#include +#include "cb_main.h" + +/*------------------------------------------------------------------------------ +* Vendor specific commands opcode +* ------------------------------------------------------------------------------ +*/ + +/* Command to write hardware address to BT device */ +#define HCID_VS_WRITE_BD_ADDR 0xFC06 + +/* It configures clk parameters for fast and slow clock */ +#define HCID_VS_FAST_CLOCK_CONFIG_BTIP 0xFD1C + +/* Command to configure stand-by behavior */ +#define HCID_VS_HCILL_PARS_CFG 0xFD2B + +/* Command to configures the sleep mode */ +#define HCID_VS_SLEEP_PROTOCOLS_CFG 0xFD0C + +/* Command to Update BT device baudrate */ +#define HCID_VS_UPDATE_UART_BAUD_RATE 0xFF36 + +#define HCI_RESET_RAND_CNT 4 + +#endif /* ODIN_CORDIO_INTF_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CY8C63XX/Psoc6BLE.cpp b/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CY8C63XX/Psoc6BLE.cpp new file mode 100644 index 0000000000..9b47662b31 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CY8C63XX/Psoc6BLE.cpp @@ -0,0 +1,117 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#include "hci_api.h" +#include "bstream.h" +#include "driver/CordioHCIDriver.h" +#include "drivers/IPCPipeTransportDriver.h" +#include "psoc6_utils.h" + +using namespace ble::vendor::cordio; +using namespace ble::vendor::cypress; + +const uint16_t HCI_VEND_SET_BD_ADDR = 0xfda0; +const uint8_t HCI_VEND_SET_BD_ADDR_LEN = 7; /* MAC address + address type */ + +class Psoc6HCIDriver : public CordioHCIDriver +{ +public: + Psoc6HCIDriver(IPCPipeTransportDriver& transport_driver) : + CordioHCIDriver(transport_driver) + { + } + + +private: + + struct BdAddress { + uint8_t mac_address[6]; + uint8_t addr_type; + + BdAddress() : addr_type(0) {} + }; + + /** + * Initialize the chip. + * The transport is up at that time. + */ + virtual void do_initialize(); + + /** + * Terminate the driver + */ + virtual void do_terminate() {} + + virtual void handle_reset_sequence(uint8_t *pMsg); + +private: + BdAddress bd_address; +}; + + +void Psoc6HCIDriver::do_initialize() +{ + cy_get_bd_mac_address(bd_address.mac_address); +} + + +void Psoc6HCIDriver::handle_reset_sequence(uint8_t *pMsg) { + + uint16_t opcode; + + /* if event is a command complete event */ + if (*pMsg == HCI_CMD_CMPL_EVT) { + /* parse parameters */ + uint8_t *pMsg2 = pMsg + HCI_EVT_HDR_LEN; + pMsg2++; /* skip num packets */ + BSTREAM_TO_UINT16(opcode, pMsg2); + pMsg2 -= 2; + /* decode opcode */ + switch (opcode) { + case HCI_OPCODE_RESET: + /* send next command in sequence */ + HciVendorSpecificCmd(HCI_VEND_SET_BD_ADDR, + HCI_VEND_SET_BD_ADDR_LEN, + reinterpret_cast(&bd_address)); + break; + + case HCI_VEND_SET_BD_ADDR: + /* pretend we have just completed reset */ + UINT16_TO_BSTREAM(pMsg2, HCI_OPCODE_RESET); + CordioHCIDriver::handle_reset_sequence(pMsg); + break; + + default: + /* pass to parent */ + CordioHCIDriver::handle_reset_sequence(pMsg); + } + } +} + + +CordioHCIDriver& ble_cordio_get_hci_driver() { + static IPCPipeTransportDriver transport_driver; + + static Psoc6HCIDriver hci_driver( + transport_driver /* other hci driver parameters */ + ); + + return hci_driver; +} + + diff --git a/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CY8C63XX/drivers/IPCPipeTransportDriver.cpp b/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CY8C63XX/drivers/IPCPipeTransportDriver.cpp new file mode 100644 index 0000000000..a7cfa94f99 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CY8C63XX/drivers/IPCPipeTransportDriver.cpp @@ -0,0 +1,75 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#include "IPCPipeTransportDriver.h" +#include "ipcpipe_transport.h" +#include "mbed_assert.h" +#include "mbed_error.h" + +namespace ble { +namespace vendor { +namespace cypress { + + +void dump_buffer(uint8_t *buffer, uint32_t len) +{ + + while (len > 0) { + printf(" %02x", *buffer++); + --len; + } + printf("\n"); +} + +void ipc_h4_receive(uint32_t *ptr) +{ + IpcPipeMessage *message = (IpcPipeMessage *)ptr; + + // We don't expect header to be received from M0+ core. + MBED_ASSERT(message->header_length == 0); + +// printf("BLE received: "); +// h4_dump_buffer(buffer->message.data, buffer->message.length); + cordio::CordioHCITransportDriver::on_data_received(message->data, message->data_length); +} + +IPCPipeTransportDriver::IPCPipeTransportDriver() +{ } + +void IPCPipeTransportDriver::initialize() +{ +// printf("H4 Transport driver initialization.\n"); + ipcpipe_transport_start(IPCPIPE_CLIENT_H4, ipc_h4_receive, NULL); +} + +void IPCPipeTransportDriver::terminate() +{ + ipcpipe_transport_stop(IPCPIPE_CLIENT_H4); +} + +uint16_t IPCPipeTransportDriver::write(uint8_t type, uint16_t len, uint8_t *pData) +{ +// printf("BLE sending T<%02x>:", type); +// dump_buffer(pData, len); + ipcpipe_write_data(IPCPIPE_CLIENT_H4, &type, 1, pData, len); + return len; +} + +} // namespace cypress +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CY8C63XX/drivers/IPCPipeTransportDriver.h b/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CY8C63XX/drivers/IPCPipeTransportDriver.h new file mode 100644 index 0000000000..7707e0de15 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_Cypress/TARGET_CY8C63XX/drivers/IPCPipeTransportDriver.h @@ -0,0 +1,72 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#ifndef PSOC6_IPCPIPE_TRANSPORT_DRIVER_H_ +#define PSOC6_IPCPIPE_TRANSPORT_DRIVER_H_ + +#include +#include "mbed.h" +#include "CordioHCITransportDriver.h" + + +namespace ble { +namespace vendor { +namespace cypress { + +using namespace ble::vendor; + +/** + * Implementation of the H4 driver over PSoC6 IPC pipe. + */ +class IPCPipeTransportDriver : public cordio::CordioHCITransportDriver { +public: + /** + * Initialize the transport driver. + * + */ + IPCPipeTransportDriver(); + + /** + * Destructor + */ + virtual ~IPCPipeTransportDriver() { } + + /** + * @see CordioHCITransportDriver::initialize + */ + virtual void initialize(); + + /** + * @see CordioHCITransportDriver::terminate + */ + virtual void terminate(); + + /** + * @see CordioHCITransportDriver::write + */ + virtual uint16_t write(uint8_t type, uint16_t len, uint8_t *pData); + +private: + +}; + +} // namespace cypress +} // namespace vendor +} // namespace ble + +#endif /* PSOC6_IPCPIPE_TRANSPORT_DRIVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.h index 25d6c21656..74836bb255 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.h @@ -22,10 +22,8 @@ #include "ble/BLEInstanceBase.h" #include "ble/generic/GenericGattClient.h" #include "ble/generic/GenericSecurityManager.h" -#include "ble/pal/SimpleEventQueue.h" #include "nRF5xPalSecurityManager.h" - #include "nRF5xGap.h" #include "nRF5xGattServer.h" diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGattServer.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGattServer.h index 6be90ff733..253c2d1446 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGattServer.h @@ -43,8 +43,8 @@ public: private: - const static unsigned BLE_TOTAL_CHARACTERISTICS = 20; - const static unsigned BLE_TOTAL_DESCRIPTORS = 8; + const static unsigned BLE_TOTAL_CHARACTERISTICS = NRF_SDH_BLE_TOTAL_CHARACTERISTICS; + const static unsigned BLE_TOTAL_DESCRIPTORS = NRF_SDH_BLE_TOTAL_DESCRIPTORS; const static unsigned TOTAL_CONCURRENT_LONG_WRITE_REQUESTS = 3; private: diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xn.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xn.h index 6efd3ec37a..088944faa6 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xn.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xn.h @@ -22,7 +22,6 @@ #include "ble/BLEInstanceBase.h" #include "ble/generic/GenericGattClient.h" #include "ble/generic/GenericSecurityManager.h" -#include "ble/pal/SimpleEventQueue.h" #include "nRF5xPalSecurityManager.h" #include "nRF5xGap.h" diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/mbed_lib.json b/features/FEATURE_BLE/targets/TARGET_NORDIC/mbed_lib.json index 53e4da4135..03881ba7cf 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/mbed_lib.json +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/mbed_lib.json @@ -11,6 +11,11 @@ "value": "1", "macro_name": "NRF_SDH_BLE_PERIPHERAL_LINK_COUNT" }, + "total_link_count": { + "help": "How many concurrent connections the system support.", + "value": "(NRF_SDH_BLE_CENTRAL_LINK_COUNT + NRF_SDH_BLE_PERIPHERAL_LINK_COUNT)", + "macro_name": "NRF_SDH_BLE_TOTAL_LINK_COUNT" + }, "gatt_attr_tab_size": { "help": "The size of the table used to hold gatts. Can be adjusted by trial and error", "value": "0x600", @@ -25,6 +30,16 @@ "help": "select whether to include the Service Changed characteristic in the GATT Server", "value": "1", "macro_name": "NRF_SDH_BLE_SERVICE_CHANGED" + }, + "max_characteristics": { + "help": "Sets the maximum number of characteristics that can be registered", + "value": "20", + "macro_name": "NRF_SDH_BLE_TOTAL_CHARACTERISTICS" + }, + "max_descriptors": { + "help": "Sets the maximum number of descriptors that can be registered", + "value": "8", + "macro_name": "NRF_SDH_BLE_TOTAL_DESCRIPTORS" } } } diff --git a/features/FEATURE_BOOTLOADER/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/LICENSE b/features/FEATURE_BOOTLOADER/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/LICENSE new file mode 100644 index 0000000000..591ac29615 --- /dev/null +++ b/features/FEATURE_BOOTLOADER/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/LICENSE @@ -0,0 +1,49 @@ +Permissive Binary License + +Version 1.0, September 2015 + +Redistribution. Redistribution and use in binary form, without +modification, are permitted provided that the following conditions are +met: + +1) Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. + +2) Unless to the extent explicitly permitted by law, no reverse + engineering, decompilation, or disassembly of this software is + permitted. + +3) Redistribution as part of a software development kit must include the + accompanying file named "DEPENDENCIES" and any dependencies listed in + that file. + +4) Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +Limited patent license. The copyright holders (and contributors) grant a +worldwide, non-exclusive, no-charge, royalty-free patent license to +make, have made, use, offer to sell, sell, import, and otherwise +transfer this software, where such license applies only to those patent +claims licensable by the copyright holders (and contributors) that are +necessarily infringed by this software. This patent license shall not +apply to any combinations that include this software. No hardware is +licensed hereunder. + +If you institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the software +itself infringes your patent(s), then your rights granted under this +license shall terminate as of the date such litigation is filed. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/features/FEATURE_BOOTLOADER/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/mbed-bootloader-internal_dfb7cc.bin b/features/FEATURE_BOOTLOADER/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/mbed-bootloader-internal_dfb7cc.bin new file mode 100644 index 0000000000..00fd19b5a7 Binary files /dev/null and b/features/FEATURE_BOOTLOADER/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/mbed-bootloader-internal_dfb7cc.bin differ diff --git a/features/FEATURE_BOOTLOADER/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/mbed_lib.json b/features/FEATURE_BOOTLOADER/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/mbed_lib.json new file mode 100644 index 0000000000..99c40b0898 --- /dev/null +++ b/features/FEATURE_BOOTLOADER/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/mbed_lib.json @@ -0,0 +1,10 @@ +{ + "name": "bootloader_DISCO_L475VG_IOT01A", + "target_overrides": { + "*": { + "target.app_offset": "0x9800", + "target.header_offset": "0x9000", + "target.bootloader_img": "mbed-bootloader-internal_dfb7cc.bin" + } + } +} diff --git a/features/cellular/TESTS/api/cellular_information/main.cpp b/features/cellular/TESTS/api/cellular_information/main.cpp index 7f8607afd2..1bb017284e 100644 --- a/features/cellular/TESTS/api/cellular_information/main.cpp +++ b/features/cellular/TESTS/api/cellular_information/main.cpp @@ -84,8 +84,8 @@ static void test_information_interface() TEST_ASSERT(info->get_model(buf, kbuf_size) == NSAPI_ERROR_OK); TEST_ASSERT(info->get_revision(buf, kbuf_size) == NSAPI_ERROR_OK); TEST_ASSERT((info->get_serial_number(buf, kbuf_size, CellularInformation::SN) == NSAPI_ERROR_OK) || - ((((AT_CellularInformation *)info)->get_device_error().errType == 3) && // 3 == CME error from the modem - (((AT_CellularInformation *)info)->get_device_error().errCode == 4))); // 4 == "operation not supported" + ((((AT_CellularInformation *)info)->get_device_error().errType == 3) && // 3 == CME error from the modem + (((AT_CellularInformation *)info)->get_device_error().errCode == 4))); // 4 == "operation not supported" nsapi_error_t err = info->get_serial_number(buf, kbuf_size, CellularInformation::IMEI); TEST_ASSERT(err == NSAPI_ERROR_UNSUPPORTED || err == NSAPI_ERROR_OK); diff --git a/features/cellular/TESTS/api/cellular_network/main.cpp b/features/cellular/TESTS/api/cellular_network/main.cpp index d2af4e0e05..2c75482c68 100644 --- a/features/cellular/TESTS/api/cellular_network/main.cpp +++ b/features/cellular/TESTS/api/cellular_network/main.cpp @@ -102,9 +102,11 @@ static bool get_network_registration(CellularNetwork::RegistrationType type, CellularNetwork::RegistrationStatus &status, bool &is_registered) { is_registered = false; - nsapi_error_t err = nw->get_registration_status(type, status); + CellularNetwork::registration_params_t reg_params; + nsapi_error_t err = nw->get_registration_params(type, reg_params); TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_UNSUPPORTED); + status = reg_params._status; switch (status) { case CellularNetwork::RegisteredRoaming: case CellularNetwork::RegisteredHomeNetwork: @@ -200,21 +202,28 @@ static void test_activate_context() static void test_connect() { TEST_ASSERT(nw->connect() == NSAPI_ERROR_OK); + char count = 0; + while ((nw->get_connection_status() != NSAPI_STATUS_GLOBAL_UP) && (count++ < 60)) { + wait(1); + } nsapi_connection_status_t st = nw->get_connection_status(); TEST_ASSERT(st == NSAPI_STATUS_GLOBAL_UP); } static void test_credentials() { - TEST_ASSERT(nw->set_credentials(NULL, "username", "pass") == NSAPI_ERROR_OK); + nsapi_error_t err = nw->set_credentials(NULL, "username", "pass"); + TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_UNSUPPORTED); + err = nw->set_credentials("internet", "user", NULL); + TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_UNSUPPORTED); + err = nw->set_credentials("internet", CellularNetwork::NOAUTH, "user", "pass"); + TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_UNSUPPORTED); TEST_ASSERT(nw->set_credentials("internet", NULL, "pass") == NSAPI_ERROR_OK); - TEST_ASSERT(nw->set_credentials("internet", "user", NULL) == NSAPI_ERROR_OK); - TEST_ASSERT(nw->set_credentials("internet", CellularNetwork::NOAUTH, "user", "pass") == NSAPI_ERROR_OK); } static void test_other() { - const char* devi = CELLULAR_STRINGIFY(CELLULAR_DEVICE); + const char *devi = CELLULAR_STRINGIFY(CELLULAR_DEVICE); TEST_ASSERT(nw->get_3gpp_error() == 0); CellularNetwork::RateControlExceptionReports reports; @@ -223,7 +232,7 @@ static void test_other() // can't test values as they are optional nsapi_error_t err = nw->get_rate_control(reports, timeUnit, uplinkRate); TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_DEVICE_ERROR); - if (strcmp(devi, "QUECTEL_BG96") != 0 && strcmp(devi, "TELIT_HE910") != 0) { // QUECTEL_BG96 does not give any specific reason for device error + if (strcmp(devi, "QUECTEL_BG96") != 0 && strcmp(devi, "TELIT_HE910") != 0 && strcmp(devi, "SARA4_PPP") != 0) { // QUECTEL_BG96 does not give any specific reason for device error if (err == NSAPI_ERROR_DEVICE_ERROR) { TEST_ASSERT(((AT_CellularNetwork *)nw)->get_device_error().errCode == 100 && // 100 == unknown command for modem ((AT_CellularNetwork *)nw)->get_device_error().errType == 3); // 3 == CME error from the modem @@ -234,9 +243,9 @@ static void test_other() err = nw->get_apn_backoff_timer(uplinkRate); TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_DEVICE_ERROR || err == NSAPI_ERROR_PARAMETER); if (err == NSAPI_ERROR_DEVICE_ERROR) { - if (strcmp(devi, "QUECTEL_BG96") != 0 && strcmp(devi, "TELIT_HE910") != 0) { // QUECTEL_BG96 does not give any specific reason for device error - TEST_ASSERT(((AT_CellularNetwork *)nw)->get_device_error().errCode == 100 && // 100 == unknown command for modem - ((AT_CellularNetwork *)nw)->get_device_error().errType == 3); // 3 == CME error from the modem + if (strcmp(devi, "QUECTEL_BG96") != 0 && strcmp(devi, "TELIT_HE910") != 0 && strcmp(devi, "SARA4_PPP") != 0) { // QUECTEL_BG96 does not give any specific reason for device error + TEST_ASSERT(((AT_CellularNetwork *)nw)->get_device_error().errCode == 100 && // 100 == unknown command for modem + ((AT_CellularNetwork *)nw)->get_device_error().errType == 3); // 3 == CME error from the modem } } else if (err == NSAPI_ERROR_PARAMETER) { TEST_ASSERT(uplinkRate == -1); @@ -268,8 +277,8 @@ static void test_other() if (err == NSAPI_ERROR_DEVICE_ERROR) { if (strcmp(devi, "TELIT_HE910") != 0) { // TELIT_HE910 just gives an error and no specific error number so we can't know is this real error or that modem/network does not support the command TEST_ASSERT((((AT_CellularNetwork *)nw)->get_device_error().errType == 3) && // 3 == CME error from the modem - ((((AT_CellularNetwork *)nw)->get_device_error().errCode == 100) || // 100 == unknown command for modem - (((AT_CellularNetwork *)nw)->get_device_error().errCode == 50))); // 50 == incorrect parameters // seen in wise_1570 for not supported commands + ((((AT_CellularNetwork *)nw)->get_device_error().errCode == 100) || // 100 == unknown command for modem + (((AT_CellularNetwork *)nw)->get_device_error().errCode == 50))); // 50 == incorrect parameters // seen in wise_1570 for not supported commands } } else { // should have some values, only not optional are apn and bearer id @@ -283,8 +292,8 @@ static void test_other() if (err == NSAPI_ERROR_DEVICE_ERROR) { if (strcmp(devi, "QUECTEL_BG96") != 0 && strcmp(devi, "TELIT_HE910") != 0) {// QUECTEL_BG96 does not give any specific reason for device error TEST_ASSERT((((AT_CellularNetwork *)nw)->get_device_error().errType == 3) && // 3 == CME error from the modem - ((((AT_CellularNetwork *)nw)->get_device_error().errCode == 100) || // 100 == unknown command for modem - (((AT_CellularNetwork *)nw)->get_device_error().errCode == 50))); // 50 == incorrect parameters // seen in wise_1570 for not supported commands + ((((AT_CellularNetwork *)nw)->get_device_error().errCode == 100) || // 100 == unknown command for modem + (((AT_CellularNetwork *)nw)->get_device_error().errCode == 50))); // 50 == incorrect parameters // seen in wise_1570 for not supported commands } } else { // we should have some values which are not optional @@ -297,17 +306,18 @@ static void test_other() TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_DEVICE_ERROR); if (err == NSAPI_ERROR_DEVICE_ERROR) { TEST_ASSERT((((AT_CellularNetwork *)nw)->get_device_error().errType == 3) && // 3 == CME error from the modem - ((((AT_CellularNetwork *)nw)->get_device_error().errCode == 100) || // 100 == unknown command for modem - (((AT_CellularNetwork *)nw)->get_device_error().errCode == 50))); // 50 == incorrect parameters // seen in wise_1570 for not supported commands - } else { + ((((AT_CellularNetwork *)nw)->get_device_error().errCode == 100) || // 100 == unknown command for modem + (((AT_CellularNetwork *)nw)->get_device_error().errCode == 50))); // 50 == incorrect parameters // seen in wise_1570 for not supported commands + } else { // test for values TEST_ASSERT(rssi >= 0); TEST_ASSERT(ber >= 0); } - int cell_id = -5; - TEST_ASSERT(nw->get_cell_id(cell_id) == NSAPI_ERROR_OK); - TEST_ASSERT(cell_id != -5); + CellularNetwork::registration_params_t reg_params; + reg_params._cell_id = -5; + TEST_ASSERT(nw->get_registration_params(reg_params) == NSAPI_ERROR_OK); + TEST_ASSERT(reg_params._cell_id != -5); int format = -1; CellularNetwork::operator_t operator_params; @@ -320,7 +330,8 @@ static void test_other() TEST_ASSERT(nw->set_blocking(true) == NSAPI_ERROR_OK); - if (strcmp(devi, "QUECTEL_BG96") != 0) { +#ifndef TARGET_UBLOX_C027 // AT command is supported, but excluded as it runs out of memory easily (there can be very many operator names) + if (strcmp(devi, "QUECTEL_BG96") != 0 && strcmp(devi, "SARA4_PPP") != 0) { // QUECTEL_BG96 timeouts with this one, tested with 3 minute timeout CellularNetwork::operator_names_list op_names; err = nw->get_operator_names(op_names); @@ -328,14 +339,15 @@ static void test_other() if (err == NSAPI_ERROR_DEVICE_ERROR) { // if device error then we must check was that really device error or that modem/network does not support the commands TEST_ASSERT((((AT_CellularNetwork *)nw)->get_device_error().errType == 3) && // 3 == CME error from the modem - ((((AT_CellularNetwork *)nw)->get_device_error().errCode == 4) || // 4 == NOT SUPPORTED BY THE MODEM - (((AT_CellularNetwork *)nw)->get_device_error().errCode == 50))); // 50 == incorrect parameters // seen in wise_1570 for not supported commands + ((((AT_CellularNetwork *)nw)->get_device_error().errCode == 4) || // 4 == NOT SUPPORTED BY THE MODEM + (((AT_CellularNetwork *)nw)->get_device_error().errCode == 50))); // 50 == incorrect parameters // seen in wise_1570 for not supported commands } else { CellularNetwork::operator_names_t *opn = op_names.get_head(); TEST_ASSERT(strlen(opn->numeric) > 0); TEST_ASSERT(strlen(opn->alpha) > 0); } } +#endif // TELIT_HE910 and QUECTEL_BG96 just gives an error and no specific error number so we can't know is this real error or that modem/network does not support the command CellularNetwork::Supported_UE_Opt supported_opt = CellularNetwork::SUPPORTED_UE_OPT_MAX; @@ -344,10 +356,10 @@ static void test_other() TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_DEVICE_ERROR); if (err == NSAPI_ERROR_DEVICE_ERROR) { // if device error then we must check was that really device error or that modem/network does not support the commands - if (!(strcmp(devi, "TELIT_HE910") == 0 || strcmp(devi, "QUECTEL_BG96") == 0)) { + if (!(strcmp(devi, "TELIT_HE910") == 0 || strcmp(devi, "QUECTEL_BG96") == 0 || strcmp(devi, "SARA4_PPP") == 0)) { TEST_ASSERT((((AT_CellularNetwork *)nw)->get_device_error().errType == 3) && // 3 == CME error from the modem - ((((AT_CellularNetwork *)nw)->get_device_error().errCode == 100) || // 100 == unknown command for modem - (((AT_CellularNetwork *)nw)->get_device_error().errCode == 50))); // 50 == incorrect parameters // seen in wise_1570 for not supported commands + ((((AT_CellularNetwork *)nw)->get_device_error().errCode == 100) || // 100 == unknown command for modem + (((AT_CellularNetwork *)nw)->get_device_error().errCode == 50))); // 50 == incorrect parameters // seen in wise_1570 for not supported commands } } else { TEST_ASSERT(supported_opt != CellularNetwork::SUPPORTED_UE_OPT_MAX); @@ -358,10 +370,10 @@ static void test_other() TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_DEVICE_ERROR); if (err == NSAPI_ERROR_DEVICE_ERROR) { // if device error then we must check was that really device error or that modem/network does not support the commands - if (!(strcmp(devi, "TELIT_HE910") == 0 || strcmp(devi, "QUECTEL_BG96") == 0)) { + if (!(strcmp(devi, "TELIT_HE910") == 0 || strcmp(devi, "QUECTEL_BG96") == 0 || strcmp(devi, "SARA4_PPP") == 0)) { TEST_ASSERT((((AT_CellularNetwork *)nw)->get_device_error().errType == 3) && // 3 == CME error from the modem - ((((AT_CellularNetwork *)nw)->get_device_error().errCode == 100) || // 100 == unknown command for modem - (((AT_CellularNetwork *)nw)->get_device_error().errCode == 50))); // 50 == incorrect parameters // seen in wise_1570 for not supported commands + ((((AT_CellularNetwork *)nw)->get_device_error().errCode == 100) || // 100 == unknown command for modem + (((AT_CellularNetwork *)nw)->get_device_error().errCode == 50))); // 50 == incorrect parameters // seen in wise_1570 for not supported commands } } } @@ -371,12 +383,14 @@ static void test_disconnect() nsapi_connection_status_t st = nw->get_connection_status(); TEST_ASSERT(st == NSAPI_STATUS_GLOBAL_UP); TEST_ASSERT(nw->disconnect() == NSAPI_ERROR_OK); + // wait to process URC's, received after disconnect + rtos::ThisThread::sleep_for(500); } static void test_detach() { // in PPP mode there is NO CARRIER waiting so flush it out - rtos::Thread::wait(6 * 1000); + rtos::ThisThread::sleep_for(6 * 1000); ((AT_CellularNetwork *)nw)->get_at_handler().flush(); nsapi_connection_status_t st = nw->get_connection_status(); @@ -384,7 +398,7 @@ static void test_detach() TEST_ASSERT(nw->detach() == NSAPI_ERROR_OK); // wait to process URC's, received after detach - rtos::Thread::wait(50); + rtos::ThisThread::sleep_for(500); st = nw->get_connection_status(); TEST_ASSERT(st == NSAPI_STATUS_DISCONNECTED); } diff --git a/features/cellular/TESTS/api/cellular_power/main.cpp b/features/cellular/TESTS/api/cellular_power/main.cpp index f1d471e183..06bbea9922 100644 --- a/features/cellular/TESTS/api/cellular_power/main.cpp +++ b/features/cellular/TESTS/api/cellular_power/main.cpp @@ -37,6 +37,7 @@ #include "mbed.h" +#include "AT_CellularPower.h" #include "CellularDevice.h" #include "../../cellular_tests_common.h" #include CELLULAR_STRINGIFY(CELLULAR_DEVICE.h) @@ -72,7 +73,7 @@ static void wait_for_power(CellularPower *pwr) static void test_power_interface() { - const char* devi = CELLULAR_STRINGIFY(CELLULAR_DEVICE); + const char *devi = CELLULAR_STRINGIFY(CELLULAR_DEVICE); cellular_device = new CELLULAR_DEVICE(queue); cellular_device->set_timeout(5000); CellularPower *pwr = cellular_device->open_power(&cellular_serial); @@ -88,12 +89,12 @@ static void test_power_interface() TEST_ASSERT(err == NSAPI_ERROR_OK); wait_for_power(pwr); - err = pwr->opt_power_save_mode(0,0); + err = pwr->opt_power_save_mode(0, 0); TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_DEVICE_ERROR); if (err == NSAPI_ERROR_DEVICE_ERROR) { if (!(strcmp(devi, "TELIT_HE910") == 0 || strcmp(devi, "QUECTEL_BG96") == 0)) { // TELIT_HE910 and QUECTEL_BG96 just gives an error and no specific error number so we can't know is this real error or that modem/network does not support the command - TEST_ASSERT(((AT_CellularPower*)pwr)->get_device_error().errCode == 100 && // 100 == unknown command for modem - ((AT_CellularPower*)pwr)->get_device_error().errType == 3); // 3 == CME error from the modem + TEST_ASSERT(((AT_CellularPower *)pwr)->get_device_error().errCode == 100 && // 100 == unknown command for modem + ((AT_CellularPower *)pwr)->get_device_error().errType == 3); // 3 == CME error from the modem } } @@ -101,8 +102,8 @@ static void test_power_interface() TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_DEVICE_ERROR); if (err == NSAPI_ERROR_DEVICE_ERROR) { if (!(strcmp(devi, "TELIT_HE910") == 0 || strcmp(devi, "QUECTEL_BG96") == 0)) { // TELIT_HE910 and QUECTEL_BG96 just gives an error and no specific error number so we can't know is this real error or that modem/network does not support the command - TEST_ASSERT(((AT_CellularPower*)pwr)->get_device_error().errCode == 100 && // 100 == unknown command for modem - ((AT_CellularPower*)pwr)->get_device_error().errType == 3); // 3 == CME error from the modem + TEST_ASSERT(((AT_CellularPower *)pwr)->get_device_error().errCode == 100 && // 100 == unknown command for modem + ((AT_CellularPower *)pwr)->get_device_error().errType == 3); // 3 == CME error from the modem } } diff --git a/features/cellular/TESTS/api/cellular_sms/main.cpp b/features/cellular/TESTS/api/cellular_sms/main.cpp index dd238c2631..9a04380400 100644 --- a/features/cellular/TESTS/api/cellular_sms/main.cpp +++ b/features/cellular/TESTS/api/cellular_sms/main.cpp @@ -52,7 +52,7 @@ static EventQueue queue(8 * EVENTS_EVENT_SIZE); static rtos::Semaphore network_semaphore(0); static CellularConnectionFSM *cellularConnectionFSM; static CellularConnectionFSM::CellularState cellular_target_state; -static CellularSMS* sms; +static CellularSMS *sms; static char service_center_address[SMS_MAX_PHONE_NUMBER_SIZE]; static int service_address_type; @@ -199,7 +199,7 @@ static void test_get_sms() wait(7); - TEST_ASSERT(sms->get_sms(buf, buf_len, phone_num, SMS_MAX_PHONE_NUMBER_SIZE, time_stamp, SMS_MAX_TIME_STAMP_SIZE, &buf_size) == buf_len-1); + TEST_ASSERT(sms->get_sms(buf, buf_len, phone_num, SMS_MAX_PHONE_NUMBER_SIZE, time_stamp, SMS_MAX_TIME_STAMP_SIZE, &buf_size) == buf_len - 1); TEST_ASSERT(strcmp(phone_num, MBED_CONF_APP_CELLULAR_PHONE_NUMBER) == 0); TEST_ASSERT(strcmp(buf, TEST_MESSAGE) == 0); TEST_ASSERT(buf_size == 0); diff --git a/features/cellular/UNITTESTS/stubs/ATHandler_stub.cpp b/features/cellular/UNITTESTS/stubs/ATHandler_stub.cpp index 81267d0b44..5d8a906209 100644 --- a/features/cellular/UNITTESTS/stubs/ATHandler_stub.cpp +++ b/features/cellular/UNITTESTS/stubs/ATHandler_stub.cpp @@ -279,6 +279,13 @@ void ATHandler::cmd_stop() { } +void ATHandler::cmd_stop_read_resp() +{ + cmd_stop(); + resp_start(); + resp_stop(); +} + device_err_t ATHandler::get_last_device_error() const { return ATHandler_stub::device_err_value; diff --git a/features/cellular/easy_cellular/CellularConnectionFSM.cpp b/features/cellular/easy_cellular/CellularConnectionFSM.cpp index 43aa21dc1e..10a949f916 100644 --- a/features/cellular/easy_cellular/CellularConnectionFSM.cpp +++ b/features/cellular/easy_cellular/CellularConnectionFSM.cpp @@ -84,6 +84,11 @@ void CellularConnectionFSM::stop() _queue_thread = NULL; } + if (_at_queue) { + _at_queue->chain(NULL); + _at_queue = NULL; + } + if (_power) { _cellularDevice->close_power(); _power = NULL; @@ -131,6 +136,10 @@ nsapi_error_t CellularConnectionFSM::init() } _at_queue = _cellularDevice->get_queue(); + if (!_at_queue) { + stop(); + return NSAPI_ERROR_NO_MEMORY; + } _at_queue->chain(&_queue); _retry_count = 0; @@ -172,25 +181,32 @@ bool CellularConnectionFSM::open_sim() // here you could add wait(secs) if you know start delay of your SIM if (_sim->get_sim_state(state) != NSAPI_ERROR_OK) { tr_info("Waiting for SIM (err while reading)..."); + if (_event_status_cb) { + _event_status_cb((nsapi_event_t)CellularSIMStatusChanged, state); + } return false; } + // report current state so callback can set sim pin if needed + if (_event_status_cb) { + _event_status_cb((nsapi_event_t)CellularSIMStatusChanged, state); + } + if (state == CellularSIM::SimStatePinNeeded) { if (strlen(_sim_pin)) { - tr_info("SIM pin required, entering pin: %s", _sim_pin); + tr_info("SIM pin required, entering pin"); nsapi_error_t err = _sim->set_pin(_sim_pin); if (err) { tr_error("SIM pin set failed with: %d, bailing out...", err); } } else { - tr_warn("PIN required but No SIM pin provided."); + // No sim pin provided even it's needed, stop state machine + tr_error("PIN required but No SIM pin provided."); + _retry_count = MAX_RETRY_ARRAY_SIZE; + return false; } } - if (_event_status_cb) { - _event_status_cb((nsapi_event_t)CellularSIMStatusChanged, state); - } - return state == CellularSIM::SimStateReady; } @@ -216,13 +232,15 @@ bool CellularConnectionFSM::get_network_registration(CellularNetwork::Registrati { is_registered = false; bool is_roaming = false; - nsapi_error_t err = _network->get_registration_status(type, status); + CellularNetwork::registration_params_t reg_params; + nsapi_error_t err = _network->get_registration_params(type, reg_params); if (err != NSAPI_ERROR_OK) { if (err != NSAPI_ERROR_UNSUPPORTED) { tr_warn("Get network registration failed (type %d)!", type); } return false; } + status = reg_params._status; switch (status) { case CellularNetwork::RegisteredRoaming: is_roaming = true; @@ -608,7 +626,7 @@ nsapi_error_t CellularConnectionFSM::start_dispatch() { MBED_ASSERT(!_queue_thread); - _queue_thread = new rtos::Thread(osPriorityNormal, 2048); + _queue_thread = new rtos::Thread(osPriorityNormal, 2048, NULL, "cellular_fsm"); if (!_queue_thread) { stop(); return NSAPI_ERROR_NO_MEMORY; diff --git a/features/cellular/easy_cellular/EasyCellularConnection.cpp b/features/cellular/easy_cellular/EasyCellularConnection.cpp index c0e31468d2..1b8ce219f1 100644 --- a/features/cellular/easy_cellular/EasyCellularConnection.cpp +++ b/features/cellular/easy_cellular/EasyCellularConnection.cpp @@ -45,6 +45,16 @@ bool EasyCellularConnection::cellular_status(int state, int next_state) (void)_cellularSemaphore.release(); return false; // return false -> state machine is halted } + + // only in case of an error or when connected is reached state and next_state can be the same. + // Release semaphore to return application instead of waiting for semaphore to complete. + if (state == next_state) { + tr_error("cellular_status: state and next_state are same, release semaphore as this is an error in state machine"); + _stm_error = true; + (void)_cellularSemaphore.release(); + return false; // return false -> state machine is halted + } + return true; } @@ -63,9 +73,10 @@ void EasyCellularConnection::network_callback(nsapi_event_t ev, intptr_t ptr) } EasyCellularConnection::EasyCellularConnection(bool debug) : - _is_connected(false), _is_initialized(false), _target_state(CellularConnectionFSM::STATE_POWER_ON), _cellularSerial( - MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE), _cellularSemaphore(0), _cellularConnectionFSM(0), _credentials_err( - NSAPI_ERROR_OK), _status_cb(0) + _is_connected(false), _is_initialized(false), _stm_error(false), + _target_state(CellularConnectionFSM::STATE_POWER_ON), + _cellularSerial(MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE), _cellularSemaphore(0), + _cellularConnectionFSM(0), _credentials_err(NSAPI_ERROR_OK), _status_cb(0) { tr_info("EasyCellularConnection()"); #if USE_APN_LOOKUP @@ -86,6 +97,7 @@ EasyCellularConnection::~EasyCellularConnection() nsapi_error_t EasyCellularConnection::init() { nsapi_error_t err = NSAPI_ERROR_OK; + _stm_error = false; if (!_is_initialized) { #if defined (MDMRTS) && defined (MDMCTS) _cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS); @@ -156,7 +168,7 @@ nsapi_error_t EasyCellularConnection::connect(const char *sim_pin, const char *a } if (sim_pin) { - this->set_sim_pin(sim_pin); + set_sim_pin(sim_pin); } return connect(); @@ -193,7 +205,7 @@ nsapi_error_t EasyCellularConnection::connect() err = _cellularConnectionFSM->continue_to_state(_target_state); if (err == NSAPI_ERROR_OK) { int sim_wait = _cellularSemaphore.wait(60 * 1000); // reserve 60 seconds to access to SIM - if (sim_wait != 1) { + if (sim_wait != 1 || _stm_error) { tr_error("NO SIM ACCESS"); err = NSAPI_ERROR_NO_CONNECTION; } else { @@ -223,7 +235,7 @@ nsapi_error_t EasyCellularConnection::connect() err = _cellularConnectionFSM->continue_to_state(_target_state); if (err == NSAPI_ERROR_OK) { int ret_wait = _cellularSemaphore.wait(10 * 60 * 1000); // cellular network searching may take several minutes - if (ret_wait != 1) { + if (ret_wait != 1 || _stm_error) { tr_info("No cellular connection"); err = NSAPI_ERROR_NO_CONNECTION; } @@ -237,6 +249,7 @@ nsapi_error_t EasyCellularConnection::disconnect() _credentials_err = NSAPI_ERROR_OK; _is_connected = false; _is_initialized = false; + _stm_error = false; #if USE_APN_LOOKUP _credentials_set = false; #endif // #if USE_APN_LOOKUP diff --git a/features/cellular/easy_cellular/EasyCellularConnection.h b/features/cellular/easy_cellular/EasyCellularConnection.h index 036fa04a78..fd8d8f07e4 100644 --- a/features/cellular/easy_cellular/EasyCellularConnection.h +++ b/features/cellular/easy_cellular/EasyCellularConnection.h @@ -168,6 +168,7 @@ private: bool _is_connected; bool _is_initialized; + bool _stm_error; #if USE_APN_LOOKUP bool _credentials_set; #endif // #if USE_APN_LOOKUP diff --git a/features/cellular/framework/API/CellularNetwork.h b/features/cellular/framework/API/CellularNetwork.h index 609ccd844a..198f6476ca 100644 --- a/features/cellular/framework/API/CellularNetwork.h +++ b/features/cellular/framework/API/CellularNetwork.h @@ -66,6 +66,7 @@ public: /* Network registration status */ enum RegistrationStatus { + StatusNotAvailable = -1, NotRegistered = 0, RegisteredHomeNetwork, SearchingNetwork, @@ -150,9 +151,9 @@ public: op_status = Unknown; op_rat = RAT_UNKNOWN; next = NULL; - op_long[0] = NULL; - op_short[0] = NULL; - op_num[0] = NULL; + op_long[0] = '\0'; + op_short[0] = '\0'; + op_num[0] = '\0'; } }; @@ -225,6 +226,27 @@ public: NWModeManualAutomatic // if manual fails, fallback to automatic }; + /* Network registration information */ + struct registration_params_t { + RegistrationType _type; + RegistrationStatus _status; + RadioAccessTechnology _act; + int _cell_id; + int _lac; + int _active_time; + int _periodic_tau; + + registration_params_t() + { + _type = C_MAX; + _status = StatusNotAvailable; + _act = RAT_UNKNOWN; + _cell_id = -1; + _lac = -1; + _active_time = -1; + _periodic_tau = -1; + } + }; /** Does all the needed initializations that can fail * @@ -263,15 +285,6 @@ public: */ virtual nsapi_error_t set_registration_urc(RegistrationType type, bool on) = 0; - /** Gets the network registration status. - * - * @param type see RegistrationType values - * @param status see RegistrationStatus values - * @return NSAPI_ERROR_OK on success - * NSAPI_ERROR_UNSUPPORTED if the modem does not support RegistrationType - * NSAPI_ERROR_DEVICE_ERROR on failure - */ - virtual nsapi_error_t get_registration_status(RegistrationType type, RegistrationStatus &status) = 0; /** Set the cellular network APN and credentials * @@ -352,13 +365,6 @@ public: */ virtual nsapi_error_t set_access_technology(RadioAccessTechnology rat) = 0; - /** Get current radio access technology. - * - * @param rat Radio access technology - * @return NSAPI_ERROR_OK - */ - virtual nsapi_error_t get_access_technology(RadioAccessTechnology &rat) = 0; - /** Scans for operators module can reach. * * @param operators Container of reachable operators and their access technologies @@ -475,13 +481,6 @@ public: */ virtual nsapi_error_t get_signal_quality(int &rssi, int &ber) = 0; - /** Get cell id. - * - * @param cell_id cell ID - * @return NSAPI_ERROR_OK - */ - virtual nsapi_error_t get_cell_id(int &cell_id) = 0; - /** Get the last 3GPP error code * @return see 3GPP TS 27.007 error codes */ @@ -528,6 +527,26 @@ public: * NSAPI_ERROR_DEVICE_ERROR on other failures */ virtual nsapi_error_t get_operator_names(operator_names_list &op_names) = 0; + + /** Gets current network registration parameters: + * type, status, access technology, cell_id, lac, active_time, periodic_tau. + * + * @param reg_params see registration_params_t + * @return NSAPI_ERROR_OK on success + * NSAPI_ERROR_DEVICE_ERROR on failure + */ + virtual nsapi_error_t get_registration_params(registration_params_t ®_params) = 0; + + /** Gets the network registration parameters based on required registration type: + * status, access technology, cell_id, lac, active_time, periodic_tau. + * + * @param type see RegistrationType values + * @param reg_params see registration_params_t + * @return NSAPI_ERROR_OK on success + * NSAPI_ERROR_UNSUPPORTED if the modem does not support RegistrationType + * NSAPI_ERROR_DEVICE_ERROR on failure + */ + virtual nsapi_error_t get_registration_params(RegistrationType type, registration_params_t ®_params) = 0; }; } // namespace mbed diff --git a/features/cellular/framework/AT/ATHandler.cpp b/features/cellular/framework/AT/ATHandler.cpp index e3c6cdd39d..840bf5cfff 100644 --- a/features/cellular/framework/AT/ATHandler.cpp +++ b/features/cellular/framework/AT/ATHandler.cpp @@ -23,7 +23,7 @@ #include "FileHandle.h" #include "mbed_wait_api.h" #include "mbed_debug.h" -#include "rtos/Thread.h" +#include "rtos/ThisThread.h" #include "Kernel.h" #include "CellularUtil.h" @@ -81,6 +81,7 @@ ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char _max_resp_length(MAX_RESP_LENGTH), _debug_on(MBED_CONF_CELLULAR_DEBUG_AT), _cmd_start(false), + _use_delimiter(true), _start_time(0) { clear_error(); @@ -159,7 +160,7 @@ void ATHandler::set_is_filehandle_usable(bool usable) nsapi_error_t ATHandler::set_urc_handler(const char *prefix, mbed::Callback callback) { - if (find_urc_handler(prefix, &callback)) { + if (find_urc_handler(prefix)) { tr_warn("URC already added with prefix: %s", prefix); return NSAPI_ERROR_OK; } @@ -186,12 +187,12 @@ nsapi_error_t ATHandler::set_urc_handler(const char *prefix, mbed::Callback callback) +void ATHandler::remove_urc_handler(const char *prefix) { struct oob_t *current = _oobs; struct oob_t *prev = NULL; while (current) { - if (strcmp(prefix, current->prefix) == 0 && current->cb == callback) { + if (strcmp(prefix, current->prefix) == 0) { if (prev) { prev->next = current->next; } else { @@ -205,11 +206,11 @@ void ATHandler::remove_urc_handler(const char *prefix, mbed::Callback ca } } -bool ATHandler::find_urc_handler(const char *prefix, mbed::Callback *callback) +bool ATHandler::find_urc_handler(const char *prefix) { struct oob_t *oob = _oobs; while (oob) { - if (strcmp(prefix, oob->prefix) == 0 && oob->cb == *callback) { + if (strcmp(prefix, oob->prefix) == 0) { return true; } oob = oob->next; @@ -460,14 +461,9 @@ ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag) return -1; } - consume_char('\"'); - - if (_last_err) { - return -1; - } - - size_t len = 0; + int len = 0; size_t match_pos = 0; + bool delimiter_found = false; for (; len < (size - 1 + match_pos); len++) { int c = get_char(); @@ -476,6 +472,7 @@ ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag) return -1; } else if (c == _delimiter) { buf[len] = '\0'; + delimiter_found = true; break; } else if (c == '\"') { match_pos = 0; @@ -501,6 +498,26 @@ ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag) buf[len] = '\0'; } + // Consume to delimiter or stop_tag + if (!delimiter_found && !_stop_tag->found) { + match_pos = 0; + while (1) { + int c = get_char(); + if (c == -1) { + set_error(NSAPI_ERROR_DEVICE_ERROR); + break; + } else if (c == _delimiter) { + break; + } else if (_stop_tag->len && c == _stop_tag->tag[match_pos]) { + match_pos++; + if (match_pos == _stop_tag->len) { + _stop_tag->found = true; + break; + } + } + } + } + return len; } @@ -596,6 +613,11 @@ void ATHandler::set_default_delimiter() _delimiter = DEFAULT_DELIMITER; } +void ATHandler::use_delimiter(bool use_delimiter) +{ + _use_delimiter = use_delimiter; +} + void ATHandler::set_tag(tag_t *tag_dst, const char *tag_seq) { if (tag_seq) { @@ -798,6 +820,8 @@ void ATHandler::resp(const char *prefix, bool check_urc) if (check_urc && match_urc()) { _urc_matched = true; + clear_error(); + continue; } // If no match found, look for CRLF and consume everything up to and including CRLF @@ -830,6 +854,7 @@ void ATHandler::resp_start(const char *prefix, bool stop) return; } + set_scope(NotSet); // Try get as much data as possible rewind_buffer(); (void)fill_buffer(false); @@ -926,7 +951,9 @@ bool ATHandler::consume_to_tag(const char *tag, bool consume_tag) int c = get_char(); if (c == -1) { break; - } else if (c == tag[match_pos]) { + // compares c against tag at current position and if this match fails + // compares c against tag[0] and also resets match_pos to 0 + } else if (c == tag[match_pos] || ((match_pos = 1) && (c == tag[--match_pos]))) { match_pos++; if (match_pos == strlen(tag)) { if (!consume_tag) { @@ -934,8 +961,6 @@ bool ATHandler::consume_to_tag(const char *tag, bool consume_tag) } return true; } - } else if (match_pos) { - match_pos = 0; } } tr_debug("consume_to_tag not found"); @@ -1012,7 +1037,7 @@ void ATHandler::set_string(char *dest, const char *src, size_t src_len) const char *ATHandler::mem_str(const char *dest, size_t dest_len, const char *src, size_t src_len) { - if (dest_len > src_len) { + if (dest_len >= src_len) { for (size_t i = 0; i < dest_len - src_len + 1; ++i) { if (memcmp(dest + i, src, src_len) == 0) { return dest + i; @@ -1026,7 +1051,7 @@ void ATHandler::cmd_start(const char *cmd) { if (_at_send_delay) { - rtos::Thread::wait_until(_last_response_stop + _at_send_delay); + rtos::ThisThread::sleep_until(_last_response_stop + _at_send_delay); } if (_last_err != NSAPI_ERROR_OK) { @@ -1083,6 +1108,13 @@ void ATHandler::cmd_stop() (void)write(_output_delimiter, strlen(_output_delimiter)); } +void ATHandler::cmd_stop_read_resp() +{ + cmd_stop(); + resp_start(); + resp_stop(); +} + size_t ATHandler::write_bytes(const uint8_t *data, size_t len) { if (_last_err != NSAPI_ERROR_OK) { @@ -1123,6 +1155,11 @@ bool ATHandler::check_cmd_send() return false; } + // Don't write delimiter if flag was set so + if (!_use_delimiter) { + return true; + } + // Don't write delimiter if this is the first subparameter if (_cmd_start) { _cmd_start = false; diff --git a/features/cellular/framework/AT/ATHandler.h b/features/cellular/framework/AT/ATHandler.h index 4962c14223..1e9952a4f7 100644 --- a/features/cellular/framework/AT/ATHandler.h +++ b/features/cellular/framework/AT/ATHandler.h @@ -109,9 +109,8 @@ public: /** Remove urc handler from linked list of urc's * * @param prefix Register urc prefix for callback. Urc could be for example "+CMTI: " - * @param callback Callback, which is called if urc is found in AT response */ - void remove_urc_handler(const char *prefix, mbed::Callback callback); + void remove_urc_handler(const char *prefix); ATHandler *_nextATHandler; // linked list @@ -248,6 +247,11 @@ public: */ void cmd_stop(); + /** Stops the AT command by writing command-line terminator CR to mark command as finished and reads the OK/ERROR response. + * + */ + void cmd_stop_read_resp(); + /** Write bytes without any subparameter delimiters, such as comma. * In case of failure when writing, the last error is set to NSAPI_ERROR_DEVICE_ERROR. * @@ -277,6 +281,12 @@ public: */ void set_default_delimiter(); + /** Defines behaviour for using or ignoring the delimiter within an AT command + * + * @param use_delimiter indicating if delimiter should be used or not + */ + void use_delimiter(bool use_delimiter); + /** Consumes the reading buffer up to the delimiter or stop_tag * * @param count number of parameters to be skipped @@ -431,6 +441,7 @@ private: char _info_resp_prefix[BUFF_SIZE]; bool _debug_on; bool _cmd_start; + bool _use_delimiter; // time when a command or an URC processing was started uint64_t _start_time; @@ -510,7 +521,7 @@ private: const char *mem_str(const char *dest, size_t dest_len, const char *src, size_t src_len); // check is urc is already added - bool find_urc_handler(const char *prefix, mbed::Callback *callback); + bool find_urc_handler(const char *prefix); // print contents of a buffer to trace log void debug_print(char *p, int len); diff --git a/features/cellular/framework/AT/AT_CellularNetwork.cpp b/features/cellular/framework/AT/AT_CellularNetwork.cpp index 4c6a960c56..527589a04d 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.cpp +++ b/features/cellular/framework/AT/AT_CellularNetwork.cpp @@ -41,8 +41,8 @@ static const at_reg_t at_reg[] = { AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(atHandler), _stack(NULL), _apn(NULL), _uname(NULL), _pwd(NULL), _ip_stack_type_requested(DEFAULT_STACK), _ip_stack_type(DEFAULT_STACK), _cid(-1), _connection_status_cb(NULL), _op_act(RAT_UNKNOWN), - _authentication_type(CHAP), _cell_id(-1), _connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set(false), - _is_context_active(false), _reg_status(NotRegistered), _current_act(RAT_UNKNOWN) + _authentication_type(CHAP), _connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set(false), + _is_context_active(false) { } @@ -56,12 +56,12 @@ AT_CellularNetwork::~AT_CellularNetwork() for (int type = 0; type < CellularNetwork::C_MAX; type++) { if (has_registration((RegistrationType)type) != RegistrationModeDisable) { - _at.remove_urc_handler(at_reg[type].urc_prefix, _urc_funcs[type]); + _at.remove_urc_handler(at_reg[type].urc_prefix); } } - _at.remove_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier)); - _at.remove_urc_handler("+CGEV:", callback(this, &AT_CellularNetwork::urc_cgev)); + _at.remove_urc_handler("NO CARRIER"); + _at.remove_urc_handler("+CGEV:"); free_credentials(); } @@ -138,13 +138,11 @@ void AT_CellularNetwork::urc_cgev() void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type) { - RegistrationStatus reg_status = NotRegistered; - int lac = -1, cell_id = -1, act = -1; - - read_reg_params(type, reg_status, lac, cell_id, act); + registration_params_t reg_params; + read_reg_params(reg_params); #if MBED_CONF_MBED_TRACE_ENABLE - switch (reg_status) { + switch (reg_params._status) { case NotRegistered: tr_warn("not registered"); break; @@ -160,18 +158,19 @@ void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type) #endif if (_at.get_last_error() == NSAPI_ERROR_OK && _connection_status_cb) { - tr_debug("stat: %d, lac: %d, cellID: %d, act: %d", reg_status, lac, cell_id, act); - if (act != -1 && (RadioAccessTechnology)act != _current_act) { - _current_act = (RadioAccessTechnology)act; - _connection_status_cb((nsapi_event_t)CellularRadioAccessTechnologyChanged, _current_act); + tr_debug("type: %d, status: %d, lac: %d, cellID: %d, act: %d", type, reg_params._status, reg_params._lac, reg_params._cell_id, reg_params._act); + _reg_params._type = type; + if (reg_params._act != _reg_params._act) { + _reg_params._act = reg_params._act; + _connection_status_cb((nsapi_event_t)CellularRadioAccessTechnologyChanged, _reg_params._act); } - if (reg_status != _reg_status) { - _reg_status = reg_status; - _connection_status_cb((nsapi_event_t)CellularRegistrationStatusChanged, _reg_status); + if (reg_params._status != _reg_params._status) { + _reg_params._status = reg_params._status; + _connection_status_cb((nsapi_event_t)CellularRegistrationStatusChanged, _reg_params._status); } - if (cell_id != -1 && cell_id != _cell_id) { - _cell_id = cell_id; - _connection_status_cb((nsapi_event_t)CellularCellIDChanged, _cell_id); + if (reg_params._cell_id != -1 && reg_params._cell_id != _reg_params._cell_id) { + _reg_params._cell_id = reg_params._cell_id; + _connection_status_cb((nsapi_event_t)CellularCellIDChanged, _reg_params._cell_id); } } } @@ -263,9 +262,7 @@ nsapi_error_t AT_CellularNetwork::delete_current_context() _at.clear_error(); _at.cmd_start("AT+CGDCONT="); _at.write_int(_cid); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); if (_at.get_last_error() == NSAPI_ERROR_OK) { _cid = -1; @@ -325,9 +322,7 @@ nsapi_error_t AT_CellularNetwork::activate_context() tr_info("Activate PDP context %d", _cid); _at.cmd_start("AT+CGACT=1,"); _at.write_int(_cid); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); } err = (_at.get_last_error() == NSAPI_ERROR_OK) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_CONNECTION; @@ -372,9 +367,7 @@ nsapi_error_t AT_CellularNetwork::connect() if (err == NSAPI_ERROR_OK) { _at.lock(); _at.cmd_start("AT+CGEREP=1"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.unlock(); } @@ -393,9 +386,11 @@ nsapi_error_t AT_CellularNetwork::open_data_channel() _at.write_int(_cid); } else { MBED_ASSERT(_cid >= 0 && _cid <= 99); - char cmd_buf[sizeof("ATD*99***xx#")]; - std::sprintf(cmd_buf, "ATD*99***%d#", _cid); - _at.cmd_start(cmd_buf); + _at.cmd_start("ATD*99***"); + _at.use_delimiter(false); + _at.write_int(_cid); + _at.write_string("#", false); + _at.use_delimiter(true); } _at.cmd_stop(); @@ -455,17 +450,15 @@ nsapi_error_t AT_CellularNetwork::disconnect() // 3GPP TS 27.007: // For EPS, if an attempt is made to disconnect the last PDN connection, then the MT responds with ERROR - if (_is_context_active && (_current_act < RAT_E_UTRAN || active_contexts_count > 1)) { + if (_is_context_active && (_reg_params._act < RAT_E_UTRAN || active_contexts_count > 1)) { _at.cmd_start("AT+CGACT=0,"); _at.write_int(_cid); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); } _at.restore_at_timeout(); - _at.remove_urc_handler("+CGEV:", callback(this, &AT_CellularNetwork::urc_cgev)); + _at.remove_urc_handler("+CGEV:"); call_network_cb(NSAPI_STATUS_DISCONNECTED); return _at.unlock_return_error(); @@ -524,9 +517,7 @@ nsapi_error_t AT_CellularNetwork::do_user_authentication() _at.write_int(_authentication_type); _at.write_string(_uname); _at.write_string(_pwd); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); if (_at.get_last_error() != NSAPI_ERROR_OK) { return NSAPI_ERROR_AUTH_FAILURE; } @@ -574,21 +565,18 @@ bool AT_CellularNetwork::set_new_context(int cid) _at.write_int(cid); _at.write_string(pdp_type); _at.write_string(_apn); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); success = (_at.get_last_error() == NSAPI_ERROR_OK); // Fall back to ipv4 if (!success && tmp_stack == IPV4V6_STACK) { tmp_stack = IPV4_STACK; + _at.clear_error(); _at.cmd_start("AT+FCLASS=0;+CGDCONT="); _at.write_int(cid); _at.write_string("IP"); _at.write_string(_apn); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); success = (_at.get_last_error() == NSAPI_ERROR_OK); } @@ -730,15 +718,12 @@ nsapi_error_t AT_CellularNetwork::set_registration_urc(RegistrationType type, bo const uint8_t ch_eq = '='; _at.write_bytes(&ch_eq, 1); _at.write_int((int)mode); - _at.cmd_stop(); } else { _at.cmd_start(at_reg[index].cmd); _at.write_string("=0", false); - _at.cmd_stop(); } - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } } @@ -769,92 +754,61 @@ nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn) if (mode != 0) { _at.clear_error(); _at.cmd_start("AT+COPS=0"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); } } else { tr_debug("Manual network registration to %s", plmn); _at.cmd_start("AT+COPS=4,2,"); _at.write_string(plmn); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); } return _at.unlock_return_error(); } -void AT_CellularNetwork::read_reg_params(RegistrationType type, RegistrationStatus ®_status, int &lac, int &cell_id, int &act) +void AT_CellularNetwork::read_reg_params(registration_params_t ®_params) { - const int LAC_LENGTH = 5, CELL_ID_LENGTH = 9; - char lac_string[LAC_LENGTH] = {0}, cell_id_string[CELL_ID_LENGTH] = {0}; - bool lac_read = false, cell_id_read = false; + const int MAX_STRING_LENGTH = 9; + char string_param[MAX_STRING_LENGTH] = {0}; - reg_status = (RegistrationStatus)_at.read_int(); + int int_param = _at.read_int(); + reg_params._status = (RegistrationStatus)int_param; - int len = _at.read_string(lac_string, LAC_LENGTH); - if (memcmp(lac_string, "ffff", LAC_LENGTH - 1) && len >= 0) { - lac_read = true; + int len = _at.read_string(string_param, TWO_BYTES_HEX + 1); + if (len > 0) { + reg_params._lac = hex_str_to_int(string_param, TWO_BYTES_HEX); + tr_debug("lac %s %d", string_param, reg_params._lac); + } else { + reg_params._lac = -1; } - len = _at.read_string(cell_id_string, CELL_ID_LENGTH); - if (memcmp(cell_id_string, "ffffffff", CELL_ID_LENGTH - 1) && len >= 0) { - cell_id_read = true; + len = _at.read_string(string_param, FOUR_BYTES_HEX + 1); + if (len > 0) { + reg_params._cell_id = hex_str_to_int(string_param, FOUR_BYTES_HEX); + tr_debug("cell_id %s %d", string_param, reg_params._cell_id); + } else { + reg_params._cell_id = -1; } - act = _at.read_int(); + int_param = _at.read_int(); + reg_params._act = (int_param == -1) ? RAT_UNKNOWN : (RadioAccessTechnology)int_param; - if (lac_read) { - lac = hex_str_to_int(lac_string, LAC_LENGTH); - tr_debug("lac %s %d", lac_string, lac); + // Skip [],[] + _at.skip_param(2); + + len = _at.read_string(string_param, ONE_BYTE_BINARY + 1); + reg_params._active_time = calculate_active_time(string_param, len); + if (reg_params._active_time != -1) { + tr_debug("active_time %s %d", string_param, reg_params._active_time); } - if (cell_id_read) { - cell_id = hex_str_to_int(cell_id_string, CELL_ID_LENGTH); - tr_debug("cell_id %s %d", cell_id_string, cell_id); + len = _at.read_string(string_param, ONE_BYTE_BINARY + 1); + reg_params._periodic_tau = calculate_periodic_tau(string_param, len); + if (reg_params._periodic_tau == -1) { + tr_debug("periodic_tau %s %d", string_param, reg_params._periodic_tau); } } -nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, RegistrationStatus &status) -{ - int i = (int)type; - MBED_ASSERT(i >= 0 && i < C_MAX); - - if (has_registration(at_reg[i].type) == RegistrationModeDisable) { - return NSAPI_ERROR_UNSUPPORTED; - } - - _at.lock(); - - const char *rsp[] = { "+CEREG:", "+CGREG:", "+CREG:"}; - _at.cmd_start(at_reg[i].cmd); - _at.write_string("?", false); - _at.cmd_stop(); - _at.resp_start(rsp[i]); - - (void)_at.read_int(); // ignore urc mode subparam - int lac = -1, cell_id = -1, act = -1; - read_reg_params(type, status, lac, cell_id, act); - _at.resp_stop(); - _reg_status = status; - - if (cell_id != -1) { - _cell_id = cell_id; - } - if (act != -1) { - _current_act = (RadioAccessTechnology)act; - } - - return _at.unlock_return_error(); -} - -nsapi_error_t AT_CellularNetwork::get_cell_id(int &cell_id) -{ - cell_id = _cell_id; - return NSAPI_ERROR_OK; -} - AT_CellularNetwork::RegistrationMode AT_CellularNetwork::has_registration(RegistrationType reg_type) { (void)reg_type; @@ -873,9 +827,7 @@ nsapi_error_t AT_CellularNetwork::set_attach(int /*timeout*/) if (attached_state != 1) { tr_debug("Network attach"); _at.cmd_start("AT+CGATT=1"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); } return _at.unlock_return_error(); @@ -904,9 +856,7 @@ nsapi_error_t AT_CellularNetwork::detach() tr_debug("Network detach"); _at.cmd_start("AT+CGATT=0"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); call_network_cb(NSAPI_STATUS_DISCONNECTED); @@ -988,12 +938,6 @@ nsapi_error_t AT_CellularNetwork::set_access_technology_impl(RadioAccessTechnolo return NSAPI_ERROR_UNSUPPORTED; } -nsapi_error_t AT_CellularNetwork::get_access_technology(RadioAccessTechnology &rat) -{ - rat = _current_act; - return NSAPI_ERROR_OK; -} - nsapi_error_t AT_CellularNetwork::set_access_technology(RadioAccessTechnology opAct) { if (opAct == RAT_UNKNOWN) { @@ -1063,10 +1007,7 @@ nsapi_error_t AT_CellularNetwork::set_ciot_optimization_config(Supported_UE_Opt _at.write_int(_cid); _at.write_int(supported_opt); _at.write_int(preferred_opt); - _at.cmd_stop(); - - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -1329,3 +1270,88 @@ nsapi_error_t AT_CellularNetwork::get_operator_names(operator_names_list &op_nam _at.resp_stop(); return _at.unlock_return_error(); } + +nsapi_error_t AT_CellularNetwork::get_registration_params(registration_params_t ®_params) +{ + reg_params = _reg_params; + return NSAPI_ERROR_OK; +} + +nsapi_error_t AT_CellularNetwork::get_registration_params(RegistrationType type, registration_params_t ®_params) +{ + int i = (int)type; + MBED_ASSERT(i >= 0 && i < C_MAX); + + if (!has_registration(at_reg[i].type)) { + return NSAPI_ERROR_UNSUPPORTED; + } + + _at.lock(); + + const char *rsp[] = { "+CEREG:", "+CGREG:", "+CREG:"}; + _at.cmd_start(at_reg[i].cmd); + _at.write_string("?", false); + _at.cmd_stop(); + _at.resp_start(rsp[i]); + + (void)_at.read_int(); // ignore urc mode subparam + _reg_params._type = type; + read_reg_params(reg_params); + _at.resp_stop(); + + _reg_params = reg_params; + + return _at.unlock_return_error(); +} + +int AT_CellularNetwork::calculate_active_time(const char *active_time_string, int active_time_length) +{ + if (active_time_length != ONE_BYTE_BINARY) { + return -1; + } + + uint32_t ie_unit = binary_str_to_uint(active_time_string, TIMER_UNIT_LENGTH); + uint32_t ie_value = binary_str_to_uint(active_time_string + TIMER_UNIT_LENGTH, active_time_length - TIMER_UNIT_LENGTH); + + switch (ie_unit) { + case 0: // multiples of 2 seconds + return 2 * ie_value; + case 1: // multiples of 1 minute + return 60 * ie_value; + case 2: // multiples of decihours + return 6 * 60 * ie_value; + case 7: // timer is deactivated + return 0; + default: // other values shall be interpreted as multiples of 1 minute + return 60 * ie_value; + } +} + +int AT_CellularNetwork::calculate_periodic_tau(const char *periodic_tau_string, int periodic_tau_length) +{ + if (periodic_tau_length != ONE_BYTE_BINARY) { + return -1; + } + + uint32_t ie_unit = binary_str_to_uint(periodic_tau_string, TIMER_UNIT_LENGTH); + uint32_t ie_value = binary_str_to_uint(periodic_tau_string + TIMER_UNIT_LENGTH, periodic_tau_length - TIMER_UNIT_LENGTH); + + switch (ie_unit) { + case 0: // multiples of 10 minutes + return 60 * 10 * ie_value; + case 1: // multiples of 1 hour + return 60 * 60 * ie_value; + case 2: // multiples of 10 hours + return 10 * 60 * 60 * ie_value; + case 3: // multiples of 2 seconds + return 2 * ie_value; + case 4: // multiples of 30 seconds + return 30 * ie_value; + case 5: // multiples of 1 minute + return 60 * ie_value; + case 6: // multiples of 320 hours + return 320 * 60 * 60 * ie_value; + default: // timer is deactivated + return 0; + } +} diff --git a/features/cellular/framework/AT/AT_CellularNetwork.h b/features/cellular/framework/AT/AT_CellularNetwork.h index 80b5665b83..f33e162d66 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.h +++ b/features/cellular/framework/AT/AT_CellularNetwork.h @@ -25,6 +25,10 @@ namespace mbed { #define AT_NETWORK_TRIALS 5 +#define TIMER_UNIT_LENGTH 3 +#define TWO_BYTES_HEX 4 +#define FOUR_BYTES_HEX 8 +#define ONE_BYTE_BINARY 8 /** * Class AT_CellularNetwork @@ -67,8 +71,6 @@ public: // CellularNetwork virtual nsapi_error_t get_network_registering_mode(NWRegisteringMode &mode); - virtual nsapi_error_t get_registration_status(RegistrationType type, RegistrationStatus &status); - virtual nsapi_error_t set_attach(int timeout = 10 * 1000); virtual nsapi_error_t get_attach(AttachStatus &status); @@ -89,7 +91,6 @@ public: // CellularNetwork virtual const char *get_ip_address(); virtual nsapi_error_t set_access_technology(RadioAccessTechnology rat); - virtual nsapi_error_t get_access_technology(RadioAccessTechnology &rat); virtual nsapi_error_t scan_plmn(operList_t &operators, int &ops_count); @@ -109,8 +110,6 @@ public: // CellularNetwork virtual nsapi_error_t get_signal_quality(int &rssi, int &ber); - virtual nsapi_error_t get_cell_id(int &cell_id); - virtual int get_3gpp_error(); virtual nsapi_error_t get_operator_params(int &format, operator_t &operator_params); @@ -118,6 +117,10 @@ public: // CellularNetwork virtual nsapi_error_t set_registration_urc(RegistrationType type, bool on); virtual nsapi_error_t get_operator_names(operator_names_list &op_names); + + virtual nsapi_error_t get_registration_params(registration_params_t ®_params); + + virtual nsapi_error_t get_registration_params(RegistrationType type, registration_params_t ®_params); protected: /** Check if modem supports the given stack type. @@ -171,10 +174,17 @@ private: nsapi_error_t delete_current_context(); - void read_reg_params_and_compare(RegistrationType type); - void read_reg_params(RegistrationType type, RegistrationStatus ®_status, int &lac, int &cell_id, int &act); // calls network callback only if status was changed, updates local connection status void call_network_cb(nsapi_connection_status_t status); + + void read_reg_params_and_compare(RegistrationType type); + void read_reg_params(registration_params_t ®_params); + + // Returns active time(Table 10.5.163/3GPP TS 24.008: GPRS Timer 2 information element) in seconds + int calculate_active_time(const char *active_time_string, int active_time_length); + // Returns periodic tau(Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element) in seconds + int calculate_periodic_tau(const char *periodic_tau_string, int periodic_tau_length); + #if NSAPI_PPP_AVAILABLE void ppp_status_cb(nsapi_event_t, intptr_t); #endif @@ -190,12 +200,12 @@ protected: Callback _connection_status_cb; RadioAccessTechnology _op_act; AuthenticationType _authentication_type; - int _cell_id; nsapi_connection_status_t _connect_status; bool _new_context_set; bool _is_context_active; - RegistrationStatus _reg_status; - RadioAccessTechnology _current_act; + + registration_params_t _reg_params; + mbed::Callback _urc_funcs[C_MAX]; }; diff --git a/features/cellular/framework/AT/AT_CellularPower.cpp b/features/cellular/framework/AT/AT_CellularPower.cpp index ce508e3a4d..29b9045df4 100644 --- a/features/cellular/framework/AT/AT_CellularPower.cpp +++ b/features/cellular/framework/AT/AT_CellularPower.cpp @@ -49,14 +49,10 @@ nsapi_error_t AT_CellularPower::set_at_mode() _at.lock(); _at.flush(); _at.cmd_start("ATE0"); // echo off - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.cmd_start("AT+CMEE=1"); // verbose responses - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -66,9 +62,7 @@ nsapi_error_t AT_CellularPower::set_power_level(int func_level, int do_reset) _at.cmd_start("AT+CFUN="); _at.write_int(func_level); _at.write_int(do_reset); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -78,9 +72,7 @@ nsapi_error_t AT_CellularPower::reset() _at.cmd_start("AT+CFUN=");// reset to full power levels _at.write_int(1); _at.write_int(1); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -92,9 +84,7 @@ nsapi_error_t AT_CellularPower::opt_power_save_mode(int periodic_time, int activ // disable PSM _at.cmd_start("AT+CPSMS="); _at.write_int(0); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); } else { /** Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element @@ -199,10 +189,7 @@ nsapi_error_t AT_CellularPower::opt_power_save_mode(int periodic_time, int activ _at.write_string(at); _at.write_string(pt); _at.write_string(at); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); - + _at.cmd_stop_read_resp(); if (_at.get_last_error() != NSAPI_ERROR_OK) { tr_warn("Power save mode not enabled!"); @@ -227,9 +214,7 @@ nsapi_error_t AT_CellularPower::opt_receive_period(int mode, EDRXAccessTechnolog _at.write_int(mode); _at.write_int(act_type); _at.write_string(edrx); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -238,17 +223,13 @@ nsapi_error_t AT_CellularPower::is_device_ready() { _at.lock(); _at.cmd_start("AT"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); // we need to do this twice because for example after data mode the first 'AT' command will give modem a // stimulus that we are back to command mode. _at.clear_error(); _at.cmd_start("AT"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } diff --git a/features/cellular/framework/AT/AT_CellularSIM.cpp b/features/cellular/framework/AT/AT_CellularSIM.cpp index fb18a0109f..86425a852a 100644 --- a/features/cellular/framework/AT/AT_CellularSIM.cpp +++ b/features/cellular/framework/AT/AT_CellularSIM.cpp @@ -90,9 +90,7 @@ nsapi_error_t AT_CellularSIM::set_pin(const char *sim_pin) _at.lock(); _at.cmd_start("AT+CPIN="); _at.write_string(sim_pin); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -103,9 +101,7 @@ nsapi_error_t AT_CellularSIM::change_pin(const char *sim_pin, const char *new_pi _at.write_string("SC"); _at.write_string(sim_pin); _at.write_string(new_pin); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -118,18 +114,14 @@ nsapi_error_t AT_CellularSIM::set_pin_query(const char *sim_pin, bool query_pin) _at.write_string("SC"); _at.write_int(1); _at.write_string(sim_pin); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); } else { /* use the SIM unlocked */ _at.cmd_start("AT+CLCK="); _at.write_string("SC"); _at.write_int(0); _at.write_string(sim_pin); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); } return _at.unlock_return_error(); } diff --git a/features/cellular/framework/AT/AT_CellularSMS.cpp b/features/cellular/framework/AT/AT_CellularSMS.cpp index 3dab1509f9..45d831f22f 100644 --- a/features/cellular/framework/AT/AT_CellularSMS.cpp +++ b/features/cellular/framework/AT/AT_CellularSMS.cpp @@ -41,7 +41,7 @@ const uint8_t SMS_MAX_GSM7_CONCATENATED_SINGLE_SMS_SIZE = 153; #define NVAM '?' // Not Valid ascii, ISO-8859-1 mark // mapping table from 7-bit GSM to ascii (ISO-8859-1) -static const int gsm_to_ascii[] = { +static const char gsm_to_ascii[] = { 64, // 0 163, // 1 36, // 2 @@ -212,9 +212,7 @@ nsapi_error_t AT_CellularSMS::set_cnmi() { _at.lock(); _at.cmd_start("AT+CNMI=2,1"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -223,9 +221,7 @@ nsapi_error_t AT_CellularSMS::set_cmgf(int msg_format) _at.lock(); _at.cmd_start("AT+CMGF="); _at.write_int(msg_format); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -237,9 +233,7 @@ nsapi_error_t AT_CellularSMS::set_csmp(int fo, int vp, int pid, int dcs) _at.write_int(vp); _at.write_int(pid); _at.write_int(dcs); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -248,16 +242,14 @@ nsapi_error_t AT_CellularSMS::set_csdh(int show_header) _at.lock(); _at.cmd_start("AT+CSDH="); _at.write_int(show_header); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } nsapi_error_t AT_CellularSMS::initialize(CellularSMSMmode mode) { if (NSAPI_ERROR_OK != _at.set_urc_handler("+CMTI:", callback(this, &AT_CellularSMS::cmti_urc)) || - NSAPI_ERROR_OK != _at.set_urc_handler("+CMT:", callback(this, &AT_CellularSMS::cmt_urc))) { + NSAPI_ERROR_OK != _at.set_urc_handler("+CMT:", callback(this, &AT_CellularSMS::cmt_urc))) { return NSAPI_ERROR_NO_MEMORY; } @@ -546,9 +538,7 @@ nsapi_error_t AT_CellularSMS::set_cpms(const char *memr, const char *memw, const _at.write_string(memr); _at.write_string(memw); _at.write_string(mems); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -559,9 +549,7 @@ nsapi_error_t AT_CellularSMS::set_csca(const char *sca, int type) _at.cmd_start("AT+CSCA="); _at.write_string(sca); _at.write_int(type); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -571,9 +559,7 @@ nsapi_size_or_error_t AT_CellularSMS::set_cscs(const char *chr_set) _at.lock(); _at.cmd_start("AT+CSCS="); _at.write_string(chr_set); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -584,9 +570,7 @@ nsapi_error_t AT_CellularSMS::delete_sms(sms_info_t *sms) for (int i = 0; i < sms->parts; i++) { _at.cmd_start("AT+CMGD="); _at.write_int(sms->msg_index[i]); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); } return _at.unlock_return_error(); @@ -600,9 +584,7 @@ nsapi_error_t AT_CellularSMS::delete_all_messages() { _at.lock(); _at.cmd_start("AT+CMGD=1,4"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } @@ -643,7 +625,7 @@ nsapi_size_or_error_t AT_CellularSMS::read_sms_from_index(int msg_index, char *b int len = _at.read_string(time_stamp, SMS_MAX_TIME_STAMP_SIZE); if (len < (SMS_MAX_TIME_STAMP_SIZE - 2)) { time_stamp[len++] = ','; - _at.read_string(&time_stamp[len], SMS_MAX_TIME_STAMP_SIZE-len); + _at.read_string(&time_stamp[len], SMS_MAX_TIME_STAMP_SIZE - len); } } (void)_at.consume_to_stop_tag(); // consume until diff --git a/features/cellular/framework/AT/AT_CellularStack.h b/features/cellular/framework/AT/AT_CellularStack.h index 5ae020b546..7a61409862 100644 --- a/features/cellular/framework/AT/AT_CellularStack.h +++ b/features/cellular/framework/AT/AT_CellularStack.h @@ -83,6 +83,21 @@ protected: class CellularSocket { public: + CellularSocket() : + id(-1), + connected(false), + proto(NSAPI_UDP), + remoteAddress("", 0), + localAddress("", 0), + _cb(NULL), + _data(NULL), + created(false), + started(false), + tx_ready(false), + rx_avail(false), + pending_bytes(0) + { + } // Socket id from cellular device int id; // Being connected means remote ip address and port are set diff --git a/features/cellular/framework/common/CellularTargets.h b/features/cellular/framework/common/CellularTargets.h index 5bfb1b45c1..04f3b3337e 100644 --- a/features/cellular/framework/common/CellularTargets.h +++ b/features/cellular/framework/common/CellularTargets.h @@ -30,14 +30,16 @@ namespace mbed { #elif TARGET_MTB_MTS_DRAGONFLY #define CELLULAR_DEVICE TELIT_HE910 #elif TARGET_UBLOX_C030 -#ifdef TARGET_UBLOX_C030_N211 +#if defined(TARGET_UBLOX_C030_N211) || defined(TARGET_UBLOX_C030_R410M) #define CELLULAR_DEVICE UBLOX_AT #else #define CELLULAR_DEVICE UBLOX_PPP #endif #elif TARGET_UBLOX_C027 #define CELLULAR_DEVICE UBLOX_PPP -#else +#elif TARGET_MTS_DRAGONFLY_L471QG +#define CELLULAR_DEVICE SARA4_PPP +//#else //#error Cellular target not defined, see cellular/targets.h //#define CELLULAR_TARGET //#define MDMTXD diff --git a/features/cellular/framework/common/CellularUtil.cpp b/features/cellular/framework/common/CellularUtil.cpp index c68dec2925..b1cdc2a0c8 100644 --- a/features/cellular/framework/common/CellularUtil.cpp +++ b/features/cellular/framework/common/CellularUtil.cpp @@ -300,6 +300,26 @@ void uint_to_binary_str(uint32_t num, char *str, int str_size, int bit_cnt) } } +uint32_t binary_str_to_uint(const char *binary_string, int binary_string_length) +{ + if (!binary_string || !binary_string_length) { + return 0; + } + + int integer_output = 0, base_exp = 1; + + for (int i = binary_string_length - 1; i >= 0; i--) { + if (binary_string[i] == '1') { + integer_output += base_exp; + } + if (binary_string[i] != '\0') { + base_exp <<= 1; + } + } + + return integer_output; +} + int char_str_to_hex_str(const char *str, uint16_t len, char *buf, bool omit_leading_zero) { if (!str || !buf) { diff --git a/features/cellular/framework/common/CellularUtil.h b/features/cellular/framework/common/CellularUtil.h index 46f66162e7..b9b0db95da 100644 --- a/features/cellular/framework/common/CellularUtil.h +++ b/features/cellular/framework/common/CellularUtil.h @@ -105,6 +105,15 @@ int hex_str_to_char_str(const char *str, uint16_t len, char *buf); */ void uint_to_binary_str(uint32_t num, char *str, int str_size, int bit_cnt); +/** Converts the given binary string to uint. + * For example binary_str_to_uint("0000001001", 10) would return 9 + * + * @param binary_string binary string from where chars are converted to uint + * @param binary_string_length length of the param binary_string + * @return uint represented by the binary string + */ +uint32_t binary_str_to_uint(const char *binary_string, int binary_string_length); + /** Get dynamic port for socket * * @return next port number above 49152 diff --git a/features/cellular/framework/device/CellularDevice.cpp b/features/cellular/framework/device/CellularDevice.cpp index 0a4856731b..1f7a53de06 100644 --- a/features/cellular/framework/device/CellularDevice.cpp +++ b/features/cellular/framework/device/CellularDevice.cpp @@ -40,7 +40,7 @@ MBED_WEAK CellularDevice *CellularDevice::get_default_instance() #endif // CELLULAR_DEVICE CellularDevice::CellularDevice() : _network_ref_count(0), _sms_ref_count(0), _power_ref_count(0), _sim_ref_count(0), - _info_ref_count(0) + _info_ref_count(0) { } diff --git a/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp b/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp index 2799055f23..a6ab513086 100644 --- a/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp +++ b/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp @@ -24,6 +24,8 @@ using namespace mbed; using namespace events; +const uint16_t RESPONSE_TO_SEND_DELAY = 100; // response-to-send delay in milliseconds at bit-rate over 9600 + GEMALTO_CINTERION::GEMALTO_CINTERION(EventQueue &queue) : AT_CellularDevice(queue) { } @@ -52,3 +54,8 @@ nsapi_error_t GEMALTO_CINTERION::init_module(FileHandle *fh) } return GEMALTO_CINTERION_Module::detect_model(model); } + +uint16_t GEMALTO_CINTERION::get_send_delay() +{ + return RESPONSE_TO_SEND_DELAY; +} diff --git a/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION.h b/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION.h index 68efa1fcc0..f21b1251fd 100644 --- a/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION.h +++ b/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION.h @@ -30,8 +30,10 @@ public: protected: // AT_CellularDevice virtual AT_CellularNetwork *open_network_impl(ATHandler &at); -public: + +public: // CellularDevice virtual nsapi_error_t init_module(FileHandle *fh); + virtual uint16_t get_send_delay(); }; } // namespace mbed diff --git a/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularNetwork.cpp b/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularNetwork.cpp index d1d7c4154c..4096b8ac0c 100644 --- a/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularNetwork.cpp +++ b/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularNetwork.cpp @@ -41,14 +41,10 @@ NetworkStack *GEMALTO_CINTERION_CellularNetwork::get_stack() bool GEMALTO_CINTERION_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack) { -#if NSAPI_PPP_AVAILABLE - return (requested_stack == IPV4_STACK || requested_stack == IPV6_STACK); -#else if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) { return (requested_stack == IPV4_STACK); } return (requested_stack == IPV4_STACK || requested_stack == IPV6_STACK); -#endif } AT_CellularNetwork::RegistrationMode GEMALTO_CINTERION_CellularNetwork::has_registration(RegistrationType reg_type) diff --git a/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp b/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp index 5613ffb2a1..79c501ef27 100644 --- a/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +++ b/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp @@ -39,6 +39,9 @@ GEMALTO_CINTERION_CellularStack::GEMALTO_CINTERION_CellularStack(ATHandler &atHa GEMALTO_CINTERION_CellularStack::~GEMALTO_CINTERION_CellularStack() { + _at.remove_urc_handler("^SIS:"); + _at.remove_urc_handler("^SISW:"); + _at.remove_urc_handler("^SISR:"); } GEMALTO_CINTERION_CellularStack::CellularSocket *GEMALTO_CINTERION_CellularStack::find_socket(int sock_id) @@ -62,14 +65,12 @@ void GEMALTO_CINTERION_CellularStack::urc_sis() int urc_code = _at.read_int(); CellularSocket *sock = find_socket(sock_id); if (sock) { - if (urc_code == 5) { // data available + if (urc_code == 5) { // The service is ready to use (ELS61 and EMS31). if (sock->_cb) { sock->started = true; sock->tx_ready = true; sock->_cb(sock->_data); } - } else if (urc_code == 2) { // socket closed - sock->created = false; } } } @@ -78,18 +79,21 @@ void GEMALTO_CINTERION_CellularStack::urc_sisw() { int sock_id = _at.read_int(); int urc_code = _at.read_int(); + sisw_urc_handler(sock_id, urc_code); +} + +void GEMALTO_CINTERION_CellularStack::sisw_urc_handler(int sock_id, int urc_code) +{ CellularSocket *sock = find_socket(sock_id); if (sock) { if (urc_code == 1) { // ready if (sock->_cb) { sock->tx_ready = true; - if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) { + if (sock->proto == NSAPI_TCP || GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) { sock->started = true; } sock->_cb(sock->_data); } - } else if (urc_code == 2) { // socket closed - sock->created = false; } } } @@ -98,6 +102,11 @@ void GEMALTO_CINTERION_CellularStack::urc_sisr() { int sock_id = _at.read_int(); int urc_code = _at.read_int(); + sisr_urc_handler(sock_id, urc_code); +} + +void GEMALTO_CINTERION_CellularStack::sisr_urc_handler(int sock_id, int urc_code) +{ CellularSocket *sock = find_socket(sock_id); if (sock) { if (urc_code == 1) { // data available @@ -105,8 +114,6 @@ void GEMALTO_CINTERION_CellularStack::urc_sisr() sock->rx_avail = true; sock->_cb(sock->_data); } - } else if (urc_code == 2) { // socket closed - sock->created = false; } } } @@ -114,12 +121,23 @@ void GEMALTO_CINTERION_CellularStack::urc_sisr() nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_stack_init() { _at.lock(); - if (create_connection_profile()) { + int connection_profile_id = CONNECTION_PROFILE_ID; + nsapi_error_t err = create_connection_profile(connection_profile_id); + if (!err) { _at.set_urc_handler("^SIS:", mbed::Callback(this, &GEMALTO_CINTERION_CellularStack::urc_sis)); _at.set_urc_handler("^SISW:", mbed::Callback(this, &GEMALTO_CINTERION_CellularStack::urc_sisw)); _at.set_urc_handler("^SISR:", mbed::Callback(this, &GEMALTO_CINTERION_CellularStack::urc_sisr)); + } else { // recovery cleanup + // close all Internet and connection profiles + for (int i = 0; i < SOCKET_MAX; i++) { + _at.clear_error(); + socket_close_impl(i); + } + _at.clear_error(); + close_connection_profile(connection_profile_id); } - return _at.unlock_return_error(); + _at.unlock(); + return err; } int GEMALTO_CINTERION_CellularStack::get_max_socket_count() @@ -129,27 +147,27 @@ int GEMALTO_CINTERION_CellularStack::get_max_socket_count() bool GEMALTO_CINTERION_CellularStack::is_protocol_supported(nsapi_protocol_t protocol) { - return (protocol == NSAPI_UDP); + return (protocol == NSAPI_UDP || protocol == NSAPI_TCP); } nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id) { - CellularSocket *socket = find_socket(sock_id); - if (!socket) { - return NSAPI_ERROR_NO_SOCKET; - } _at.set_at_timeout(FAILURE_TIMEOUT); + _at.cmd_start("AT^SISC="); _at.write_int(sock_id); + _at.cmd_stop_read_resp(); + + _at.clear_error(); // clear SISS even though SISC fails + _at.cmd_start("AT^SISS="); + _at.write_int(sock_id); + _at.write_string("srvType"); + _at.write_string("none"); _at.cmd_stop(); _at.resp_start(); _at.resp_stop(); - _at.restore_at_timeout(); - socket->started = false; - socket->created = false; - socket->tx_ready = false; - socket->rx_avail = false; + _at.restore_at_timeout(); tr_debug("Closed socket %d (err %d)", sock_id, _at.get_last_error()); return _at.get_last_error(); @@ -158,26 +176,32 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id) nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_open_defer(CellularSocket *socket, const SocketAddress *address) { // host address (IPv4) and local+remote port is needed only for BGS2 which does not support UDP server socket - char sock_addr[sizeof("sockudp://") - 1 + NSAPI_IPv4_SIZE + sizeof(":12345;port=12345") - 1 + 1]; - if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) { - std::sprintf(sock_addr, "sockudp://%s:%u", address ? address->get_ip_address() : "", socket->localAddress.get_port()); + char sock_addr[sizeof("sockudp://") - 1 + NSAPI_IPv6_SIZE + sizeof("[]:12345;port=12345") - 1 + 1]; + + if (socket->proto == NSAPI_UDP) { + if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) { + std::sprintf(sock_addr, "sockudp://%s:%u", address ? address->get_ip_address() : "", socket->localAddress.get_port()); + } else { + std::sprintf(sock_addr, "sockudp://%s:%u;port=%u", address->get_ip_address(), address->get_port(), socket->localAddress.get_port()); + } } else { - std::sprintf(sock_addr, "sockudp://%s:%u;port=%u", address->get_ip_address(), address->get_port(), socket->localAddress.get_port()); + if (address->get_ip_version() == NSAPI_IPv4) { + std::sprintf(sock_addr, "socktcp://%s:%u", address->get_ip_address(), address->get_port()); + } else { + std::sprintf(sock_addr, "socktcp://[%s]:%u", address->get_ip_address(), address->get_port()); + } } _at.cmd_start("AT^SISS="); _at.write_int(socket->id); _at.write_string("address", false); _at.write_string(sock_addr); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.cmd_start("AT^SISO="); _at.write_int(socket->id); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); + if (_at.get_last_error()) { tr_error("Socket %d open failed!", socket->id); _at.clear_error(); @@ -252,9 +276,7 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket _at.write_int(internet_service_id); _at.write_string("srvType"); _at.write_string("Socket"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); } if (!foundConIdType) { @@ -262,16 +284,17 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket _at.write_int(internet_service_id); _at.write_string("conId"); _at.write_int(connection_profile_id); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); } - tr_debug("Internet service %d created (err %d)", internet_service_id, _at.get_last_error()); + tr_debug("Internet service %d (err %d)", internet_service_id, _at.get_last_error()); - if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) { - return socket_open_defer(socket); + if (socket->proto == NSAPI_UDP) { + if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) { + return socket_open_defer(socket); + } } + return _at.get_last_error(); } @@ -280,20 +303,27 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul { tr_debug("Socket %d, sendto %s, len %d", socket->id, address.get_ip_address(), size); - int ip_version = address.get_ip_version(); - if ((ip_version == NSAPI_IPv4 && _stack_type != IPV4_STACK) || - (ip_version == NSAPI_IPv6 && _stack_type != IPV6_STACK)) { - tr_warn("No IP route for %s", address.get_ip_address()); - return NSAPI_ERROR_NO_SOCKET; + if (socket->proto == NSAPI_UDP) { + const int ip_version = address.get_ip_version(); + if ((ip_version == NSAPI_IPv4 && _stack_type != IPV4_STACK) || + (ip_version == NSAPI_IPv6 && _stack_type != IPV6_STACK)) { + tr_warn("No IP route for %s", address.get_ip_address()); + return NSAPI_ERROR_NO_SOCKET; + } } - if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) { - tr_error("Send addr %s, prev addr %s", address.get_ip_address(), socket->remoteAddress.get_ip_address()); + + if (socket->proto == NSAPI_UDP && GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) { + tr_debug("Send addr %s, prev addr %s", address.get_ip_address(), socket->remoteAddress.get_ip_address()); if (address != socket->remoteAddress) { if (socket->started) { socket_close_impl(socket->id); _at.clear_error(); } + if (create_socket_impl(socket) != NSAPI_ERROR_OK) { + tr_error("Failed to create socket %d", socket->id); + return NSAPI_ERROR_NO_SOCKET; + } if (socket_open_defer(socket, &address) != NSAPI_ERROR_OK) { tr_error("Failed to open socket %d", socket->id); return NSAPI_ERROR_NO_SOCKET; @@ -324,16 +354,22 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul _at.cmd_start("AT^SISW="); _at.write_int(socket->id); _at.write_int(size); + if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) { _at.write_int(0); - char socket_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1]; - if (address.get_ip_version() == NSAPI_IPv4) { - std::sprintf(socket_address, "%s:%u", address.get_ip_address(), address.get_port()); - } else { - std::sprintf(socket_address, "[%s]:%u", address.get_ip_address(), address.get_port()); + + // UDP requires Udp_RemClient + if (socket->proto == NSAPI_UDP) { + char socket_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1]; + if (address.get_ip_version() == NSAPI_IPv4) { + std::sprintf(socket_address, "%s:%u", address.get_ip_address(), address.get_port()); + } else { + std::sprintf(socket_address, "[%s]:%u", address.get_ip_address(), address.get_port()); + } + _at.write_string(socket_address); } - _at.write_string(socket_address); } + _at.cmd_stop(); sisw_retry: @@ -343,29 +379,30 @@ sisw_retry: _at.restore_at_timeout(); return NSAPI_ERROR_DEVICE_ERROR; } - _at.restore_at_timeout(); int socket_id = _at.read_int(); if (socket_id != socket->id) { + // We might have read the SISW URC so let's try to handle it + const int urc_code = _at.read_int(); + const int extra = _at.read_int(); + if (urc_code != -1 && extra == -1) { + sisw_urc_handler(socket_id, urc_code); + goto sisw_retry; + } + _at.restore_at_timeout(); tr_error("Socket id %d != %d", socket_id, socket->id); return NSAPI_ERROR_DEVICE_ERROR; } int accept_len = _at.read_int(); if (accept_len == -1) { tr_error("Socket %d send failed", socket->id); + _at.restore_at_timeout(); return NSAPI_ERROR_DEVICE_ERROR; } - int unack_len = _at.read_int(); - if (unack_len != 0) { - tr_warn("Socket %d unack_len %d", socket->id, unack_len); - if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) { - // assume that an URC was received when unackData is not received - _at.resp_stop(); - goto sisw_retry; - } - } + _at.skip_param(); // unackData _at.write_bytes((uint8_t *)data, accept_len); _at.resp_stop(); + _at.restore_at_timeout(); tr_debug("Socket %d sendto %s, %d bytes (err %d)", socket->id, address.get_ip_address(), accept_len, _at.get_last_error()); @@ -381,11 +418,8 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell { tr_debug("Socket %d recvfrom %d bytes", socket->id, size); - if (size > UDP_PACKET_SIZE) { - tr_debug("Socket recvfrom size %d > %d", size, UDP_PACKET_SIZE); - size = UDP_PACKET_SIZE; - } - + // we must use this flag, otherwise ^SISR URC can come while we are reading response and there is + // no way to detect if that is really an URC or response if (!socket->rx_avail) { _at.process_oob(); // check for ^SISR URC if (!socket->rx_avail) { @@ -394,21 +428,35 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell } } + if (size > UDP_PACKET_SIZE) { + tr_debug("Socket recvfrom size %d > %d", size, UDP_PACKET_SIZE); + size = UDP_PACKET_SIZE; + } + _at.cmd_start("AT^SISR="); _at.write_int(socket->id); _at.write_int(size); _at.cmd_stop(); +sisr_retry: _at.resp_start("^SISR:"); if (!_at.info_resp()) { tr_error("Socket %d not responding", socket->id); return NSAPI_ERROR_DEVICE_ERROR; } + int socket_id = _at.read_int(); if (socket_id != socket->id) { + const int urc_code = _at.read_int(); + const int extra = _at.read_int(); // should be -1 if URC + if (urc_code != -1 && extra == -1) { + sisr_urc_handler(socket_id, urc_code); + goto sisr_retry; + } tr_error("Socket recvfrom id %d != %d", socket_id, socket->id); return NSAPI_ERROR_DEVICE_ERROR; } + nsapi_size_or_error_t len = _at.read_int(); if (len == 0) { tr_warn("Socket %d no data", socket->id); @@ -426,7 +474,9 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell socket->rx_avail = true; } } - if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) { + + // UDP Udp_RemClient + if (socket->proto == NSAPI_UDP && GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) { char ip_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1]; int ip_len = _at.read_string(ip_address, sizeof(ip_address)); if (ip_len <= 0) { @@ -454,7 +504,7 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell port_start++; // skip ':' int port = std::strtol(port_start, NULL, 10); address->set_port(port); - tr_debug("IP address %s:%d", address->get_ip_address(), address->get_port()); + tr_debug("IP address %s, port %d", address->get_ip_address(), address->get_port()); *ip_stop = tmp_ch; // restore original IP string } } @@ -468,30 +518,27 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell _at.resp_stop(); - tr_debug("Socket %d, recvfrom %s, %d bytes (err %d)", socket->id, address, len, _at.get_last_error()); + tr_debug("Socket %d, recvfrom %s, %d bytes (err %d)", socket->id, socket->remoteAddress.get_ip_address(), len, _at.get_last_error()); - return (_at.get_last_error() == NSAPI_ERROR_OK) ? recv_len : NSAPI_ERROR_DEVICE_ERROR; + return (_at.get_last_error() == NSAPI_ERROR_OK) ? (recv_len ? recv_len : NSAPI_ERROR_WOULD_BLOCK) : NSAPI_ERROR_DEVICE_ERROR; } // setup internet connection profile for sockets -bool GEMALTO_CINTERION_CellularStack::create_connection_profile() +nsapi_error_t GEMALTO_CINTERION_CellularStack::create_connection_profile(int connection_profile_id) { if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelEMS31) { // EMS31 connection has only DNS settings and there is no need to modify those here for now - return true; + return NSAPI_ERROR_OK; } - char conParamType[12]; + char conParamType[sizeof("GPRS0") + 1]; std::sprintf(conParamType, "GPRS%d", (_stack_type == IPV4_STACK) ? 0 : 6); _at.cmd_start("AT^SICS?"); _at.cmd_stop(); - bool foundConnection = false; - bool foundAPN = false; - int connection_profile_id = CONNECTION_PROFILE_ID; + bool found_connection = false; _at.resp_start("^SICS:"); while (_at.info_resp()) { int id = _at.read_int(); - tr_debug("SICS %d", id); if (id == connection_profile_id) { char paramTag[16]; int paramTagLen = _at.read_string(paramTag, sizeof(paramTag)); @@ -500,17 +547,10 @@ bool GEMALTO_CINTERION_CellularStack::create_connection_profile() char paramValue[100 + 1]; // APN may be up to 100 chars int paramValueLen = _at.read_string(paramValue, sizeof(paramValue)); if (paramValueLen >= 0) { - tr_debug("paramValue %s", paramValue); if (strcmp(paramTag, "conType") == 0) { - tr_debug("conType %s", paramValue); if (strcmp(paramValue, conParamType) == 0) { - foundConnection = true; - } - } - if (strcmp(paramTag, "apn") == 0) { - tr_debug("apn %s", paramValue); - if (strcmp(paramValue, _apn ? _apn : "") == 0) { - foundAPN = true; + found_connection = true; + break; } } } @@ -519,34 +559,82 @@ bool GEMALTO_CINTERION_CellularStack::create_connection_profile() } _at.resp_stop(); - if (!foundConnection) { - tr_debug("Socket conType %s", conParamType); + // connection profile is bound to a PDP context and it can not be changed + if (!found_connection) { _at.cmd_start("AT^SICS="); _at.write_int(connection_profile_id); _at.write_string("conType"); _at.write_string(conParamType); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); - } + _at.cmd_stop_read_resp(); - if (!foundAPN && _apn) { - tr_debug("Socket APN %s", _apn ? _apn : ""); + if (_apn && strlen(_apn) > 0) { + _at.cmd_start("AT^SICS="); + _at.write_int(connection_profile_id); + _at.write_string("apn"); + _at.write_string(_apn); + _at.cmd_stop_read_resp(); + } + + // set maximum inactivity timeout _at.cmd_start("AT^SICS="); _at.write_int(connection_profile_id); - _at.write_string("apn"); - _at.write_string(_apn); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.write_string("inactTO"); + _at.write_int(0xffff); // 2^16-1 + _at.cmd_stop_read_resp(); + + // use URC mode ON + _at.cmd_start("AT^SCFG=\"Tcp/withURCs\",\"on\""); + _at.cmd_stop_read_resp(); } - // use URC mode - _at.cmd_start("AT^SCFG=\"Tcp/withURCs\",\"on\""); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); - - tr_debug("Connection profile %d created, stack_type %d (err %d)", connection_profile_id, _stack_type, _at.get_last_error()); - return _at.get_last_error() == NSAPI_ERROR_OK; + tr_debug("Connection profile %d, stack_type %d (err %d)", connection_profile_id, _stack_type, _at.get_last_error()); + return _at.get_last_error(); +} + +void GEMALTO_CINTERION_CellularStack::close_connection_profile(int connection_profile_id) +{ + if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelEMS31) { + return; + } + + // To clear connection profile need to detach from packet data. + // After detach modem sends PDP disconnected event to network class, + // which propagates network disconnected to upper layer to start reconnecting. + _at.cmd_start("AT+CGATT=0"); + _at.cmd_stop_read_resp(); + _at.clear_error(); + + _at.cmd_start("AT^SICS="); + _at.write_int(connection_profile_id); + _at.write_string("conType"); + _at.write_string("none"); + _at.cmd_stop_read_resp(); + + _at.clear_error(); +} + +nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &address) +{ + int err = NSAPI_ERROR_DEVICE_ERROR; + + struct CellularSocket *socket = (struct CellularSocket *)handle; + if (!socket) { + return err; + } + + _at.lock(); + err = create_socket_impl(socket); + if (err != NSAPI_ERROR_OK) { + _at.unlock(); + return err; + } + err = socket_open_defer(socket, &address); + _at.unlock(); + + if (err == NSAPI_ERROR_OK) { + socket->remoteAddress = address; + socket->connected = true; + } + + return err; } diff --git a/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h b/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h index 0d5dd1fddf..aab3c436e3 100644 --- a/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h +++ b/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h @@ -45,6 +45,8 @@ protected: virtual nsapi_size_or_error_t socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address, void *buffer, nsapi_size_t size); + virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address); + private: // find the socket handle based on socket identifier CellularSocket *find_socket(int sock_id); @@ -52,10 +54,13 @@ private: // socket URC handlers as per Cinterion AT manuals void urc_sis(); void urc_sisw(); + void sisw_urc_handler(int sock_id, int urc_code); void urc_sisr(); + void sisr_urc_handler(int sock_id, int urc_code); // sockets need a connection profile, one profile is enough to support single stack sockets - bool create_connection_profile(); + nsapi_error_t create_connection_profile(int connection_profile_id); + void close_connection_profile(int connection_profile_id); // socket open need to be deferred until sendto due to BGS2 does not support UDP server endpoint nsapi_error_t socket_open_defer(CellularSocket *socket, const SocketAddress *address = NULL); diff --git a/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP.cpp b/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP.cpp new file mode 100644 index 0000000000..ce4849eeae --- /dev/null +++ b/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, 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. + */ + +#include "SARA4_PPP.h" +#include "SARA4_PPP_CellularNetwork.h" +#include "SARA4_PPP_CellularPower.h" + +using namespace mbed; +using namespace events; + +static const AT_CellularBase::SupportedFeature unsupported_features[] = { + AT_CellularBase::AT_CGSN_WITH_TYPE, + AT_CellularBase::AT_CGDATA, + AT_CellularBase::SUPPORTED_FEATURE_END_MARK +}; + +SARA4_PPP::SARA4_PPP(EventQueue &queue) : AT_CellularDevice(queue) +{ + AT_CellularBase::set_unsupported_features(unsupported_features); +} + +SARA4_PPP::~SARA4_PPP() +{ +} + +AT_CellularNetwork *SARA4_PPP::open_network_impl(ATHandler &at) +{ + return new SARA4_PPP_CellularNetwork(at); +} + +AT_CellularPower *SARA4_PPP::open_power_impl(ATHandler &at) +{ + return new SARA4_PPP_CellularPower(at); +} + diff --git a/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP.h b/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP.h new file mode 100644 index 0000000000..ad00cba149 --- /dev/null +++ b/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef SARA4_PPP_H_ +#define SARA4_PPP_H_ + +#include "AT_CellularDevice.h" + +namespace mbed { + +class SARA4_PPP : public AT_CellularDevice { + +public: + SARA4_PPP(events::EventQueue &queue); + virtual ~SARA4_PPP(); + +public: // CellularDevice + virtual AT_CellularNetwork *open_network_impl(ATHandler &at); + virtual AT_CellularPower *open_power_impl(ATHandler &at); +}; + +} // namespace mbed + +#endif // SARA4_PPP_H_ diff --git a/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularNetwork.cpp b/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularNetwork.cpp new file mode 100644 index 0000000000..9c77e2c65c --- /dev/null +++ b/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularNetwork.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, 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. + */ + +#include "SARA4_PPP_CellularNetwork.h" + +using namespace mbed; + +SARA4_PPP_CellularNetwork::SARA4_PPP_CellularNetwork(ATHandler &atHandler) : AT_CellularNetwork(atHandler) +{ +} + +SARA4_PPP_CellularNetwork::~SARA4_PPP_CellularNetwork() +{ +} + +bool SARA4_PPP_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack) +{ + return requested_stack == IPV4_STACK ? true : false; +} + +AT_CellularNetwork::RegistrationMode SARA4_PPP_CellularNetwork::has_registration(RegistrationType reg_type) +{ + return (reg_type == C_REG || reg_type == C_GREG) ? RegistrationModeLAC : RegistrationModeDisable; +} + +nsapi_error_t SARA4_PPP_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opRat) +{ + _op_act = RAT_CATM1; + return NSAPI_ERROR_OK; +} diff --git a/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularNetwork.h b/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularNetwork.h new file mode 100644 index 0000000000..32b5ff5d06 --- /dev/null +++ b/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularNetwork.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef SARA4_PPP_CELLULAR_NETWORK_H_ +#define SARA4_PPP_CELLULAR_NETWORK_H_ + +#include "AT_CellularNetwork.h" + +namespace mbed { + +class SARA4_PPP_CellularNetwork : public AT_CellularNetwork { +public: + SARA4_PPP_CellularNetwork(ATHandler &atHandler); + virtual ~SARA4_PPP_CellularNetwork(); + +protected: + virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack); + + virtual RegistrationMode has_registration(RegistrationType rat); + + virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat); +}; + +} // namespace mbed + +#endif // SARA4_PPP_CELLULAR_NETWORK_H_ diff --git a/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularPower.cpp b/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularPower.cpp new file mode 100644 index 0000000000..7cb1684481 --- /dev/null +++ b/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularPower.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, 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. + */ + +#include "SARA4_PPP_CellularPower.h" + +#include "onboard_modem_api.h" + +using namespace mbed; + +SARA4_PPP_CellularPower::SARA4_PPP_CellularPower(ATHandler &atHandler) : AT_CellularPower(atHandler) +{ + +} + +SARA4_PPP_CellularPower::~SARA4_PPP_CellularPower() +{ + +} + +nsapi_error_t SARA4_PPP_CellularPower::on() +{ +#if MODEM_ON_BOARD + ::onboard_modem_init(); + ::onboard_modem_power_up(); +#endif + return NSAPI_ERROR_OK; +} + +nsapi_error_t SARA4_PPP_CellularPower::off() +{ +#if MODEM_ON_BOARD + ::onboard_modem_power_down(); +#endif + return NSAPI_ERROR_OK; +} diff --git a/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularPower.h b/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularPower.h new file mode 100644 index 0000000000..39abd60fad --- /dev/null +++ b/features/cellular/framework/targets/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularPower.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef SARA4_PPP_CELLULARPOWER_H_ +#define SARA4_PPP_CELLULARPOWER_H_ + +#include "AT_CellularPower.h" + +namespace mbed { + +class SARA4_PPP_CellularPower : public AT_CellularPower { +public: + SARA4_PPP_CellularPower(ATHandler &atHandler); + virtual ~SARA4_PPP_CellularPower(); + +public: //from CellularPower + + virtual nsapi_error_t on(); + + virtual nsapi_error_t off(); +}; + +} // namespace mbed + +#endif // SARA4_PPP_CELLULARPOWER_H_ diff --git a/features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularPower.cpp b/features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularPower.cpp index c19e75e822..fc27d257e8 100644 --- a/features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularPower.cpp +++ b/features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularPower.cpp @@ -34,15 +34,12 @@ nsapi_error_t QUECTEL_BC95_CellularPower::set_at_mode() _at.lock(); _at.flush(); _at.cmd_start("AT"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.cmd_start("AT+CMEE="); // verbose responses _at.write_int(1); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); + return _at.unlock_return_error(); } diff --git a/features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularStack.cpp b/features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularStack.cpp index ff49bcd41a..1cb87db365 100644 --- a/features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularStack.cpp +++ b/features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularStack.cpp @@ -41,6 +41,36 @@ nsapi_error_t QUECTEL_BC95_CellularStack::socket_accept(void *server, void **soc return NSAPI_ERROR_UNSUPPORTED; } +nsapi_error_t QUECTEL_BC95_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &address) +{ + CellularSocket *socket = (CellularSocket *)handle; + + _at.lock(); + if (!socket->created) { + const nsapi_error_t error_create = create_socket_impl(socket); + if (error_create != NSAPI_ERROR_OK) { + return error_create; + } + } + + _at.cmd_start("AT+NSOCO="); + _at.write_int(socket->id); + _at.write_string(address.get_ip_address(), false); + _at.write_int(address.get_port()); + _at.cmd_stop(); + _at.resp_start(); + _at.resp_stop(); + _at.unlock(); + + if (_at.get_last_error() == NSAPI_ERROR_OK) { + socket->remoteAddress = address; + socket->connected = true; + return NSAPI_ERROR_OK; + } + + return NSAPI_ERROR_NO_CONNECTION; +} + void QUECTEL_BC95_CellularStack::urc_nsonmi() { int sock_id = _at.read_int(); @@ -63,16 +93,14 @@ int QUECTEL_BC95_CellularStack::get_max_socket_count() bool QUECTEL_BC95_CellularStack::is_protocol_supported(nsapi_protocol_t protocol) { - return (protocol == NSAPI_UDP); + return (protocol == NSAPI_UDP || protocol == NSAPI_TCP); } nsapi_error_t QUECTEL_BC95_CellularStack::socket_close_impl(int sock_id) { _at.cmd_start("AT+NSOCL="); _at.write_int(sock_id); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); tr_info("Close socket: %d error: %d", sock_id, _at.get_last_error()); @@ -85,8 +113,30 @@ nsapi_error_t QUECTEL_BC95_CellularStack::create_socket_impl(CellularSocket *soc bool socketOpenWorking = false; if (socket->proto == NSAPI_UDP) { - _at.cmd_start("AT+NSOCR=DGRAM,17,"); + } else if (socket->proto == NSAPI_TCP) { + _at.cmd_start("AT+NSOCR=STREAM,6,"); + } else { + return NSAPI_ERROR_PARAMETER; + } + _at.write_int(socket->localAddress.get_port()); + _at.write_int(1); + _at.cmd_stop(); + _at.resp_start(); + sock_id = _at.read_int(); + _at.resp_stop(); + + socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK); + + if (!socketOpenWorking) { + _at.cmd_start("AT+NSOCL=0"); + _at.cmd_stop_read_resp(); + + if (socket->proto == NSAPI_UDP) { + _at.cmd_start("AT+NSOCR=DGRAM,17,"); + } else if (socket->proto == NSAPI_TCP) { + _at.cmd_start("AT+NSOCR=STREAM,6,"); + } _at.write_int(socket->localAddress.get_port()); _at.write_int(1); _at.cmd_stop(); @@ -95,23 +145,6 @@ nsapi_error_t QUECTEL_BC95_CellularStack::create_socket_impl(CellularSocket *soc _at.resp_stop(); socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK); - - if (!socketOpenWorking) { - _at.cmd_start("AT+NSOCL=0"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); - - _at.cmd_start("AT+NSOCR=DGRAM,17,"); - _at.write_int(socket->localAddress.get_port()); - _at.write_int(1); - _at.cmd_stop(); - _at.resp_start(); - sock_id = _at.read_int(); - _at.resp_stop(); - - socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK); - } } if (!socketOpenWorking || (sock_id == -1)) { @@ -145,11 +178,22 @@ nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_sendto_impl(CellularSoc int hexlen = char_str_to_hex_str((const char *)data, size, hexstr); // NULL terminated for write_string hexstr[hexlen] = 0; - _at.cmd_start("AT+NSOST="); - _at.write_int(socket->id); - _at.write_string(address.get_ip_address(), false); - _at.write_int(address.get_port()); - _at.write_int(size); + + if (socket->proto == NSAPI_UDP) { + _at.cmd_start("AT+NSOST="); + _at.write_int(socket->id); + _at.write_string(address.get_ip_address(), false); + _at.write_int(address.get_port()); + _at.write_int(size); + } else if (socket->proto == NSAPI_TCP) { + _at.cmd_start("AT+NSOSD="); + _at.write_int(socket->id); + _at.write_int(size); + } else { + delete hexstr; + return NSAPI_ERROR_PARAMETER; + } + _at.write_string(hexstr, false); _at.cmd_stop(); _at.resp_start(); diff --git a/features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularStack.h b/features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularStack.h index b4967edd37..9d2b6fe1a1 100644 --- a/features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularStack.h +++ b/features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularStack.h @@ -36,6 +36,8 @@ protected: // NetworkStack virtual nsapi_error_t socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address = 0); + virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address); + protected: // AT_CellularStack virtual int get_max_socket_count(); diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.cpp b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.cpp index 6ed0bbd9e8..9ffd6d3fb1 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.cpp +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.cpp @@ -52,58 +52,36 @@ nsapi_error_t QUECTEL_BG96_CellularNetwork::set_access_technology_impl(RadioAcce switch (opsAct) { case RAT_CATM1: _at.cmd_start("AT+QCFG=\"nwscanseq\",020301"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.cmd_start("AT+QCFG=\"nwscanmode\",3,1"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.cmd_start("AT+QCFG=\"iotopmode\",0,1"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); break; case RAT_NB1: _at.cmd_start("AT+QCFG=\"nwscanseq\",030201"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.cmd_start("AT+QCFG=\"nwscanmode\",3,1"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.cmd_start("AT+QCFG=\"iotopmode\",1,1"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); break; case RAT_GSM: case RAT_GSM_COMPACT: case RAT_UTRAN: case RAT_EGPRS: _at.cmd_start("AT+QCFG=\"nwscanseq\",010203"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.cmd_start("AT+QCFG=\"nwscanmode\",1,1"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); break; default: _at.cmd_start("AT+QCFG=\"nwscanseq\",020301"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.cmd_start("AT+QCFG=\"nwscanmode\",0,1"); //auto mode - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.cmd_start("AT+QCFG=\"iotopmode\",2,1"); //auto mode - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.unlock(); _op_act = RAT_UNKNOWN; return NSAPI_ERROR_UNSUPPORTED; @@ -122,9 +100,7 @@ nsapi_error_t QUECTEL_BG96_CellularNetwork::do_user_authentication() _at.write_string(_uname); _at.write_string(_pwd); _at.write_int(_authentication_type); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); if (_at.get_last_error() != NSAPI_ERROR_OK) { return NSAPI_ERROR_AUTH_FAILURE; } diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularPower.cpp b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularPower.cpp index 019f728721..f6e35196a0 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularPower.cpp +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularPower.cpp @@ -32,5 +32,5 @@ nsapi_error_t QUECTEL_BG96_CellularPower::set_device_ready_urc_cb(mbed::Callback void QUECTEL_BG96_CellularPower::remove_device_ready_urc_cb(mbed::Callback callback) { - _at.remove_urc_handler(DEVICE_READY_URC, callback); + _at.remove_urc_handler(DEVICE_READY_URC); } diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp index bc570afa12..8d79fa6c74 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp @@ -39,6 +39,71 @@ nsapi_error_t QUECTEL_BG96_CellularStack::socket_accept(void *server, void **soc return NSAPI_ERROR_UNSUPPORTED; } +nsapi_error_t QUECTEL_BG96_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &address) +{ + CellularSocket *socket = (CellularSocket *)handle; + + int modem_connect_id = -1; + int request_connect_id = socket->id; + int err = -1; + + _at.lock(); + if (socket->proto == NSAPI_TCP) { + _at.cmd_start("AT+QIOPEN="); + _at.write_int(_cid); + _at.write_int(request_connect_id); + _at.write_string("TCP"); + _at.write_string(address.get_ip_address()); + _at.write_int(address.get_port()); + _at.write_int(socket->localAddress.get_port()); + _at.write_int(0); + _at.cmd_stop(); + + handle_open_socket_response(modem_connect_id, err); + + if ((_at.get_last_error() == NSAPI_ERROR_OK) && err) { + _at.cmd_start("AT+QICLOSE="); + _at.write_int(modem_connect_id); + _at.cmd_stop(); + _at.resp_start(); + _at.resp_stop(); + + _at.cmd_start("AT+QIOPEN="); + _at.write_int(_cid); + _at.write_int(request_connect_id); + _at.write_string("TCP"); + _at.write_string(address.get_ip_address()); + _at.write_int(address.get_port()); + _at.write_int(socket->localAddress.get_port()); + _at.write_int(0); + _at.cmd_stop(); + + handle_open_socket_response(modem_connect_id, err); + } + } + + // If opened successfully BUT not requested one, close it + if (!err && (modem_connect_id != request_connect_id)) { + _at.cmd_start("AT+QICLOSE="); + _at.write_int(modem_connect_id); + _at.cmd_stop(); + _at.resp_start(); + _at.resp_stop(); + } + + nsapi_error_t ret_val = _at.get_last_error(); + _at.unlock(); + + if ((ret_val == NSAPI_ERROR_OK) && (modem_connect_id == request_connect_id)) { + socket->created = true; + socket->remoteAddress = address; + socket->connected = true; + return NSAPI_ERROR_OK; + } + + return NSAPI_ERROR_NO_CONNECTION; +} + void QUECTEL_BG96_CellularStack::urc_qiurc() { int sock_id = 0; @@ -66,16 +131,16 @@ int QUECTEL_BG96_CellularStack::get_max_socket_count() bool QUECTEL_BG96_CellularStack::is_protocol_supported(nsapi_protocol_t protocol) { - return (protocol == NSAPI_UDP); + return (protocol == NSAPI_UDP || protocol == NSAPI_TCP); } nsapi_error_t QUECTEL_BG96_CellularStack::socket_close_impl(int sock_id) { + _at.set_at_timeout(BG96_CLOSE_SOCKET_TIMEOUT); _at.cmd_start("AT+QICLOSE="); _at.write_int(sock_id); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); + _at.restore_at_timeout(); return _at.get_last_error(); } @@ -115,9 +180,7 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc if ((_at.get_last_error() == NSAPI_ERROR_OK) && err) { _at.cmd_start("AT+QICLOSE="); _at.write_int(modem_connect_id); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.cmd_start("AT+QIOPEN="); _at.write_int(_cid); @@ -145,9 +208,7 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc if ((_at.get_last_error() == NSAPI_ERROR_OK) && err) { _at.cmd_start("AT+QICLOSE="); _at.write_int(modem_connect_id); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.cmd_start("AT+QIOPEN="); _at.write_int(_cid); @@ -165,9 +226,7 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc if (!err && (modem_connect_id != request_connect_id)) { _at.cmd_start("AT+QICLOSE="); _at.write_int(modem_connect_id); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); } nsapi_error_t ret_val = _at.get_last_error(); @@ -198,8 +257,10 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSoc _at.cmd_start("AT+QISEND="); _at.write_int(socket->id); _at.write_int(size); - _at.write_string(address.get_ip_address()); - _at.write_int(address.get_port()); + if (socket->proto == NSAPI_UDP) { + _at.write_string(address.get_ip_address()); + _at.write_int(address.get_port()); + } _at.cmd_stop(); _at.resp_start(">"); diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.h b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.h index cbc870f695..1b8e547530 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.h +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.h @@ -24,6 +24,7 @@ namespace mbed { #define BG96_SOCKET_MAX 12 #define BG96_CREATE_SOCKET_TIMEOUT 150000 //150 seconds +#define BG96_CLOSE_SOCKET_TIMEOUT 20000 // TCP socket max timeout is >10sec class QUECTEL_BG96_CellularStack : public AT_CellularStack { public: @@ -37,6 +38,8 @@ protected: // NetworkStack virtual nsapi_error_t socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address = 0); + virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address); + protected: // AT_CellularStack virtual int get_max_socket_count(); diff --git a/features/cellular/framework/targets/TELIT/HE910/TELIT_HE910_CellularPower.cpp b/features/cellular/framework/targets/TELIT/HE910/TELIT_HE910_CellularPower.cpp index 63a2b42027..68a397743d 100644 --- a/features/cellular/framework/targets/TELIT/HE910/TELIT_HE910_CellularPower.cpp +++ b/features/cellular/framework/targets/TELIT/HE910/TELIT_HE910_CellularPower.cpp @@ -61,9 +61,7 @@ nsapi_error_t TELIT_HE910_CellularPower::set_at_mode() } _at.lock(); _at.cmd_start("AT&K0;&C1;&D0"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } diff --git a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT.cpp b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT.cpp index 1064743f54..9d76da2167 100644 --- a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT.cpp +++ b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT.cpp @@ -22,8 +22,18 @@ using namespace mbed; using namespace events; +#ifdef TARGET_UBLOX_C030_R410M +static const AT_CellularBase::SupportedFeature unsupported_features[] = { + AT_CellularBase::AT_CGSN_WITH_TYPE, + AT_CellularBase::SUPPORTED_FEATURE_END_MARK +}; +#endif + UBLOX_AT::UBLOX_AT(EventQueue &queue) : AT_CellularDevice(queue) { +#ifdef TARGET_UBLOX_C030_R410M + AT_CellularBase::set_unsupported_features(unsupported_features); +#endif } UBLOX_AT::~UBLOX_AT() diff --git a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT.h b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT.h index 2b12557651..a2a0beefa5 100644 --- a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT.h +++ b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT.h @@ -20,8 +20,7 @@ #include "AT_CellularDevice.h" -namespace mbed -{ +namespace mbed { class UBLOX_AT : public AT_CellularDevice { public: diff --git a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularNetwork.cpp b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularNetwork.cpp index f7d7cbbcb2..aa4e229409 100644 --- a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularNetwork.cpp +++ b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularNetwork.cpp @@ -54,7 +54,7 @@ AT_CellularNetwork::RegistrationMode UBLOX_AT_CellularNetwork::has_registration( nsapi_error_t UBLOX_AT_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opRat) { - switch(opRat) { + switch (opRat) { #if defined(TARGET_UBLOX_C030_U201) || defined(TARGET_UBLOX_C027) case RAT_GSM: case RAT_GSM_COMPACT: @@ -119,9 +119,9 @@ nsapi_error_t UBLOX_AT_CellularNetwork::open_data_channel() { bool success = false; int active = 0; - char * config = NULL; + char *config = NULL; nsapi_error_t err = NSAPI_ERROR_NO_CONNECTION; - char imsi[MAX_IMSI_LENGTH+1]; + char imsi[MAX_IMSI_LENGTH + 1]; // do check for stack to validate that we have support for stack _stack = get_stack(); @@ -142,14 +142,14 @@ nsapi_error_t UBLOX_AT_CellularNetwork::open_data_channel() if (_apn == NULL) { err = get_imsi(imsi); if (err == NSAPI_ERROR_OK) { - config = (char*)apnconfig(imsi); + config = (char *)apnconfig(imsi); } } // Attempt to connect do { get_next_credentials(&config); - if(_uname && _pwd) { + if (_uname && _pwd) { _auth = (*_uname && *_pwd) ? _auth : NSAPI_SECURITY_NONE; } else { _auth = NSAPI_SECURITY_NONE; @@ -166,9 +166,9 @@ nsapi_error_t UBLOX_AT_CellularNetwork::open_data_channel() return err; } -bool UBLOX_AT_CellularNetwork::activate_profile(const char* apn, - const char* username, - const char* password) +bool UBLOX_AT_CellularNetwork::activate_profile(const char *apn, + const char *username, + const char *password) { bool activated = false; bool success = false; @@ -178,9 +178,7 @@ bool UBLOX_AT_CellularNetwork::activate_profile(const char* apn, success = false; _at.cmd_start("AT+UPSD=0,1,"); _at.write_string(apn); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); if (_at.get_last_error() == NSAPI_ERROR_OK) { success = true; @@ -191,9 +189,7 @@ bool UBLOX_AT_CellularNetwork::activate_profile(const char* apn, success = false; _at.cmd_start("AT+UPSD=" PROFILE ",2,"); _at.write_string(username); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); if (_at.get_last_error() == NSAPI_ERROR_OK) { success = true; @@ -204,9 +200,7 @@ bool UBLOX_AT_CellularNetwork::activate_profile(const char* apn, success = false; _at.cmd_start("AT+UPSD=" PROFILE ",3,"); _at.write_string(password); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); if (_at.get_last_error() == NSAPI_ERROR_OK) { success = true; @@ -215,9 +209,7 @@ bool UBLOX_AT_CellularNetwork::activate_profile(const char* apn, if (success) { _at.cmd_start("AT+UPSD=" PROFILE ",7,\"0.0.0.0\""); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); // Set up the authentication protocol // 0 = none @@ -228,17 +220,13 @@ bool UBLOX_AT_CellularNetwork::activate_profile(const char* apn, if ((_auth == NSAPI_SECURITY_UNKNOWN) || (nsapi_security_to_modem_security(_auth) == protocol)) { _at.cmd_start("AT+UPSD=0,6,"); _at.write_int(protocol); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); if (_at.get_last_error() == NSAPI_ERROR_OK) { // Activate, wait upto 30 seconds for the connection to be made _at.set_at_timeout(30000); _at.cmd_start("AT+UPSDA=0,3"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.restore_at_timeout(); if (_at.get_last_error() == NSAPI_ERROR_OK) { @@ -285,9 +273,7 @@ bool UBLOX_AT_CellularNetwork::disconnect_modem_stack() if (get_ip_address() != NULL) { _at.cmd_start("AT+UPSDA=" PROFILE ",4"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); if (_at.get_last_error() == NSAPI_ERROR_OK) { success = true; @@ -297,7 +283,7 @@ bool UBLOX_AT_CellularNetwork::disconnect_modem_stack() return success; } -nsapi_error_t UBLOX_AT_CellularNetwork::get_imsi(char* imsi) +nsapi_error_t UBLOX_AT_CellularNetwork::get_imsi(char *imsi) { _at.lock(); _at.cmd_start("AT+CIMI"); @@ -313,7 +299,7 @@ nsapi_error_t UBLOX_AT_CellularNetwork::get_imsi(char* imsi) } // Get the next set of credentials, based on IMSI. -void UBLOX_AT_CellularNetwork::get_next_credentials(char ** config) +void UBLOX_AT_CellularNetwork::get_next_credentials(char **config) { if (*config) { _apn = _APN_GET(*config); diff --git a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularNetwork.h b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularNetwork.h index 130c3710f5..a8ba6149cf 100644 --- a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularNetwork.h +++ b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularNetwork.h @@ -21,11 +21,9 @@ #include "AT_CellularNetwork.h" #include "APN_db.h" -namespace mbed -{ +namespace mbed { -class UBLOX_AT_CellularNetwork : public AT_CellularNetwork -{ +class UBLOX_AT_CellularNetwork : public AT_CellularNetwork { public: UBLOX_AT_CellularNetwork(ATHandler &atHandler); virtual ~UBLOX_AT_CellularNetwork(); @@ -69,7 +67,7 @@ private: * NSAPI_SECURITY_CHAP or NSAPI_SECURITY_UNKNOWN). * @return True if successful, otherwise false. */ - bool activate_profile(const char* apn, const char* username, const char* password); + bool activate_profile(const char *apn, const char *username, const char *password); /** Convert nsapi_security_t to the modem security numbers. * @@ -86,11 +84,11 @@ private: /** Read IMSI of modem. */ - nsapi_error_t get_imsi(char* imsi); + nsapi_error_t get_imsi(char *imsi); /** Get the next set of credentials from the database. */ - void get_next_credentials(char ** config); + void get_next_credentials(char **config); }; } // namespace mbed diff --git a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularPower.h b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularPower.h index 7ac016a1bf..b321822506 100644 --- a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularPower.h +++ b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularPower.h @@ -20,11 +20,9 @@ #include "AT_CellularPower.h" -namespace mbed -{ +namespace mbed { -class UBLOX_AT_CellularPower : public AT_CellularPower -{ +class UBLOX_AT_CellularPower : public AT_CellularPower { public: UBLOX_AT_CellularPower(ATHandler &atHandler); virtual ~UBLOX_AT_CellularPower(); diff --git a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularStack.cpp b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularStack.cpp index e35c49046c..ff13b4279e 100644 --- a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularStack.cpp +++ b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularStack.cpp @@ -47,11 +47,11 @@ nsapi_error_t UBLOX_AT_CellularStack::socket_accept(void *server, void **socket, // Callback for Socket Read URC. void UBLOX_AT_CellularStack::UUSORD_URC() { - int a,b; + int a, b; CellularSocket *socket; - a =_at.read_int(); - b =_at.read_int(); + a = _at.read_int(); + b = _at.read_int(); socket = find_socket(a); if (socket != NULL) { @@ -67,11 +67,11 @@ void UBLOX_AT_CellularStack::UUSORD_URC() // Callback for Socket Read From URC. void UBLOX_AT_CellularStack::UUSORF_URC() { - int a,b; + int a, b; CellularSocket *socket; - a =_at.read_int(); - b =_at.read_int(); + a = _at.read_int(); + b = _at.read_int(); socket = find_socket(a); if (socket != NULL) { @@ -90,7 +90,7 @@ void UBLOX_AT_CellularStack::UUSOCL_URC() int a; CellularSocket *socket; - a =_at.read_int(); + a = _at.read_int(); socket = find_socket(a); clear_socket(socket); } @@ -101,7 +101,7 @@ void UBLOX_AT_CellularStack::UUPSDD_URC() int a; CellularSocket *socket; - a =_at.read_int(); + a = _at.read_int(); socket = find_socket(a); clear_socket(socket); } @@ -119,7 +119,6 @@ bool UBLOX_AT_CellularStack::is_protocol_supported(nsapi_protocol_t protocol) nsapi_error_t UBLOX_AT_CellularStack::create_socket_impl(CellularSocket *socket) { int sock_id = 0; - bool socketOpenWorking = false; _at.lock(); if (socket->proto == NSAPI_UDP) { @@ -129,7 +128,7 @@ nsapi_error_t UBLOX_AT_CellularStack::create_socket_impl(CellularSocket *socket) _at.resp_start("+USOCR:"); sock_id = _at.read_int(); _at.resp_stop(); - } else if(socket->proto == NSAPI_TCP) { + } else if (socket->proto == NSAPI_TCP) { _at.cmd_start("AT+USOCR=6"); _at.cmd_stop(); @@ -137,12 +136,12 @@ nsapi_error_t UBLOX_AT_CellularStack::create_socket_impl(CellularSocket *socket) sock_id = _at.read_int(); _at.resp_stop(); } // Unsupported protocol is checked in "is_protocol_supported" function - _at.unlock(); - socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK); - if (!socketOpenWorking) { + if ((_at.get_last_error() != NSAPI_ERROR_OK) || (sock_id == -1)) { + _at.unlock(); return NSAPI_ERROR_NO_SOCKET; } + _at.unlock(); // Check for duplicate socket id delivered by modem for (int i = 0; i < UBLOX_MAX_SOCKET; i++) { @@ -162,8 +161,15 @@ nsapi_error_t UBLOX_AT_CellularStack::socket_connect(nsapi_socket_t handle, cons { CellularSocket *socket = (CellularSocket *)handle; - if (!socket->created) { - create_socket_impl(socket); + if (socket) { + if (!socket->created) { + nsapi_error_t err = create_socket_impl(socket); + if (err != NSAPI_ERROR_OK) { + return err; + } + } + } else { + return NSAPI_ERROR_DEVICE_ERROR; } _at.lock(); @@ -171,9 +177,7 @@ nsapi_error_t UBLOX_AT_CellularStack::socket_connect(nsapi_socket_t handle, cons _at.write_int(socket->id); _at.write_string(addr.get_ip_address()); _at.write_int(addr.get_port()); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); _at.unlock(); if (_at.get_last_error() == NSAPI_ERROR_OK) { @@ -186,7 +190,7 @@ nsapi_error_t UBLOX_AT_CellularStack::socket_connect(nsapi_socket_t handle, cons } nsapi_size_or_error_t UBLOX_AT_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address, - const void *data, nsapi_size_t size) + const void *data, nsapi_size_t size) { int sent_len = 0; uint8_t ch = 0, cont = 50; @@ -258,7 +262,7 @@ nsapi_size_or_error_t UBLOX_AT_CellularStack::socket_sendto_impl(CellularSocket } nsapi_size_or_error_t UBLOX_AT_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address, - void *buffer, nsapi_size_t size) + void *buffer, nsapi_size_t size) { nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR; bool success = true; @@ -401,15 +405,13 @@ nsapi_error_t UBLOX_AT_CellularStack::socket_close_impl(int sock_id) _at.lock(); _at.cmd_start("AT+USOCL="); _at.write_int(sock_id); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.cmd_stop_read_resp(); return _at.unlock_return_error(); } // Find or create a socket from the list. -UBLOX_AT_CellularStack::CellularSocket * UBLOX_AT_CellularStack::find_socket(int id) +UBLOX_AT_CellularStack::CellularSocket *UBLOX_AT_CellularStack::find_socket(int id) { CellularSocket *socket = NULL; @@ -426,7 +428,7 @@ UBLOX_AT_CellularStack::CellularSocket * UBLOX_AT_CellularStack::find_socket(int // Clear out the storage for a socket -void UBLOX_AT_CellularStack::clear_socket(CellularSocket * socket) +void UBLOX_AT_CellularStack::clear_socket(CellularSocket *socket) { if (socket != NULL) { socket->id = SOCKET_UNUSED; @@ -437,7 +439,7 @@ void UBLOX_AT_CellularStack::clear_socket(CellularSocket * socket) } } -const char * UBLOX_AT_CellularStack::get_ip_address() +const char *UBLOX_AT_CellularStack::get_ip_address() { _at.lock(); _at.cmd_start("AT+UPSND=" PROFILE ",0"); @@ -447,7 +449,7 @@ const char * UBLOX_AT_CellularStack::get_ip_address() if (_at.info_resp()) { _at.skip_param(); _at.skip_param(); - int len = _at.read_string(_ip, NSAPI_IPv4_SIZE-1); + int len = _at.read_string(_ip, NSAPI_IPv4_SIZE - 1); if (len == -1) { _ip[0] = '\0'; _at.unlock(); @@ -457,7 +459,7 @@ const char * UBLOX_AT_CellularStack::get_ip_address() // in case stack type is not IPV4 only, try to look also for IPV6 address if (_stack_type != IPV4_STACK) { - len = _at.read_string(_ip, PDP_IPV6_SIZE-1); + len = _at.read_string(_ip, PDP_IPV6_SIZE - 1); } } _at.resp_stop(); diff --git a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularStack.h b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularStack.h index 45d5b3846c..ef08660008 100644 --- a/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularStack.h +++ b/features/cellular/framework/targets/UBLOX/AT/UBLOX_AT_CellularStack.h @@ -23,11 +23,9 @@ #include "drivers/Timer.h" -namespace mbed -{ +namespace mbed { -class UBLOX_AT_CellularStack : public AT_CellularStack -{ +class UBLOX_AT_CellularStack : public AT_CellularStack { public: UBLOX_AT_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type); virtual ~UBLOX_AT_CellularStack(); @@ -41,7 +39,7 @@ protected: virtual nsapi_error_t socket_listen(nsapi_socket_t handle, int backlog); virtual nsapi_error_t socket_accept(nsapi_socket_t server, - nsapi_socket_t *handle, SocketAddress *address=0); + nsapi_socket_t *handle, SocketAddress *address = 0); protected: // AT_CellularStack @@ -78,10 +76,10 @@ protected: // AT_CellularStack virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address); virtual nsapi_size_or_error_t socket_sendto_impl(CellularSocket *socket, const SocketAddress &address, - const void *data, nsapi_size_t size); + const void *data, nsapi_size_t size); virtual nsapi_size_or_error_t socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address, - void *buffer, nsapi_size_t size); + void *buffer, nsapi_size_t size); virtual nsapi_error_t socket_close_impl(int sock_id); @@ -97,14 +95,14 @@ private: * @param id Socket ID. * @return Socket if True, otherwise NULL. */ - CellularSocket * find_socket(int id = SOCKET_UNUSED); + CellularSocket *find_socket(int id = SOCKET_UNUSED); /** Clear out the storage for a socket. * * @param id Cellular Socket. * @return None */ - void clear_socket(CellularSocket * socket); + void clear_socket(CellularSocket *socket); }; } // namespace mbed #endif /* UBLOX_AT_CELLULARSTACK_H_ */ diff --git a/features/cellular/framework/targets/UBLOX/PPP/UBLOX_PPP.cpp b/features/cellular/framework/targets/UBLOX/PPP/UBLOX_PPP.cpp index 3aa486f752..12b1b6467b 100644 --- a/features/cellular/framework/targets/UBLOX/PPP/UBLOX_PPP.cpp +++ b/features/cellular/framework/targets/UBLOX/PPP/UBLOX_PPP.cpp @@ -22,8 +22,18 @@ using namespace mbed; using namespace events; +#ifdef TARGET_UBLOX_C027 +static const AT_CellularBase::SupportedFeature unsupported_features[] = { + AT_CellularBase::AT_CGSN_WITH_TYPE, + AT_CellularBase::SUPPORTED_FEATURE_END_MARK +}; +#endif + UBLOX_PPP::UBLOX_PPP(EventQueue &queue) : AT_CellularDevice(queue) { +#ifdef TARGET_UBLOX_C027 + AT_CellularBase::set_unsupported_features(unsupported_features); +#endif } UBLOX_PPP::~UBLOX_PPP() diff --git a/features/cryptocell/FEATURE_CRYPTOCELL310/TARGET_MCU_NRF52840/crypto_platform.c b/features/cryptocell/FEATURE_CRYPTOCELL310/TARGET_MCU_NRF52840/crypto_platform.c index 7a5781fc43..8fccaebc93 100644 --- a/features/cryptocell/FEATURE_CRYPTOCELL310/TARGET_MCU_NRF52840/crypto_platform.c +++ b/features/cryptocell/FEATURE_CRYPTOCELL310/TARGET_MCU_NRF52840/crypto_platform.c @@ -30,7 +30,7 @@ int crypto_platform_setup( crypto_platform_ctx *ctx ) NRF_CRYPTOCELL->ENABLE = 1; if( SaSi_LibInit( &ctx->rndState, &rndWorkBuff ) != 0 ) - return ( MBEDTLS_ERR_PLATFORM_HW_FAILED ); + return ( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); return ( 0 ); } diff --git a/features/deprecated_warnings/FEATURE_LWIP/feature_lwip_is_deprecated.c b/features/deprecated_warnings/FEATURE_LWIP/feature_lwip_is_deprecated.c index 010cfd14f8..729da247b9 100644 --- a/features/deprecated_warnings/FEATURE_LWIP/feature_lwip_is_deprecated.c +++ b/features/deprecated_warnings/FEATURE_LWIP/feature_lwip_is_deprecated.c @@ -21,4 +21,7 @@ MBED_DEPRECATED_SINCE("5.10", "FEATURE_LWIP is deprecated. You do not need to enable it anymore in mbed_app.json") static void feature_lwip(void) { } -void dummy_feature_lwip_is_deprecated(void) { feature_lwip(); } +void dummy_feature_lwip_is_deprecated(void) +{ + feature_lwip(); +} diff --git a/features/deprecated_warnings/FEATURE_NANOSTACK/feature_nanostack_is_deprecated.c b/features/deprecated_warnings/FEATURE_NANOSTACK/feature_nanostack_is_deprecated.c index 03367cba72..a612dc1a9e 100644 --- a/features/deprecated_warnings/FEATURE_NANOSTACK/feature_nanostack_is_deprecated.c +++ b/features/deprecated_warnings/FEATURE_NANOSTACK/feature_nanostack_is_deprecated.c @@ -21,4 +21,7 @@ MBED_DEPRECATED_SINCE("5.10", "FEATURE_NANOSTACK is deprecated. You do not need to enable it anymore in mbed_app.json") static void feature_nanostack(void) { } -void dummy_feature_nanostack_is_deprecated(void) { feature_nanostack(); } +void dummy_feature_nanostack_is_deprecated(void) +{ + feature_nanostack(); +} diff --git a/features/device_key/TESTS/device_key/functionality/main.cpp b/features/device_key/TESTS/device_key/functionality/main.cpp index 7afd66442a..0837884ccb 100644 --- a/features/device_key/TESTS/device_key/functionality/main.cpp +++ b/features/device_key/TESTS/device_key/functionality/main.cpp @@ -25,6 +25,7 @@ #endif using namespace utest::v1; +using namespace mbed; #define MSG_VALUE_DUMMY "0" #define MSG_VALUE_LEN 32 @@ -51,7 +52,7 @@ int inject_dummy_rot_key() memcpy(key, "1234567812345678", DEVICE_KEY_16BYTE); int size = DEVICE_KEY_16BYTE; - DeviceKey& devkey = DeviceKey::get_instance(); + DeviceKey &devkey = DeviceKey::get_instance(); return devkey.device_inject_root_of_trust(key, size); #else return DEVICEKEY_SUCCESS; @@ -85,8 +86,8 @@ void generate_derived_key_consistency_16_byte_key_long_consistency_test(char *ke unsigned char salt[] = "Once upon a time, I worked for the circus and I lived in Omaha."; int key_type = DEVICE_KEY_16BYTE; uint16_t actual_size = 0; - DeviceKey& devkey = DeviceKey::get_instance(); - NVStore& nvstore = NVStore::get_instance(); + DeviceKey &devkey = DeviceKey::get_instance(); + NVStore &nvstore = NVStore::get_instance(); size_t salt_size = sizeof(salt); if (strcmp(key, MSG_KEY_DEVICE_TEST_STEP1) == 0) { @@ -144,8 +145,8 @@ void generate_derived_key_consistency_32_byte_key_long_consistency_test(char *ke unsigned char salt[] = "The quick brown fox jumps over the lazy dog"; int key_type = DEVICE_KEY_32BYTE; uint16_t actual_size = 0; - DeviceKey& devkey = DeviceKey::get_instance(); - NVStore& nvstore = NVStore::get_instance(); + DeviceKey &devkey = DeviceKey::get_instance(); + NVStore &nvstore = NVStore::get_instance(); size_t salt_size = sizeof(salt); if (strcmp(key, MSG_KEY_DEVICE_TEST_STEP3) == 0) { @@ -197,7 +198,7 @@ void generate_derived_key_consistency_32_byte_key_long_consistency_test(char *ke */ void device_inject_root_of_trust_wrong_size_test() { - DeviceKey& devkey = DeviceKey::get_instance(); + DeviceKey &devkey = DeviceKey::get_instance(); uint32_t key[DEVICE_KEY_32BYTE / sizeof(uint32_t)]; memcpy(key, "12345678123456788765432187654321", DEVICE_KEY_32BYTE); @@ -216,11 +217,11 @@ void device_inject_root_of_trust_wrong_size_test() */ void device_inject_root_of_trust_16_byte_size_test() { - DeviceKey& devkey = DeviceKey::get_instance(); + DeviceKey &devkey = DeviceKey::get_instance(); uint32_t rkey[DEVICE_KEY_16BYTE / sizeof(uint32_t)]; uint16_t actual_size; uint32_t key[DEVICE_KEY_16BYTE / sizeof(uint32_t)]; - NVStore& nvstore = NVStore::get_instance(); + NVStore &nvstore = NVStore::get_instance(); int ret = nvstore.reset(); TEST_ASSERT_EQUAL_INT(DEVICEKEY_SUCCESS, ret); @@ -242,11 +243,11 @@ void device_inject_root_of_trust_16_byte_size_test() */ void device_inject_root_of_trust_32_byte_size_test() { - DeviceKey& devkey = DeviceKey::get_instance(); + DeviceKey &devkey = DeviceKey::get_instance(); uint32_t rkey[DEVICE_KEY_32BYTE / sizeof(uint32_t)]; uint16_t actual_size; uint32_t key[DEVICE_KEY_32BYTE / sizeof(uint32_t)]; - NVStore& nvstore = NVStore::get_instance(); + NVStore &nvstore = NVStore::get_instance(); int ret = nvstore.reset(); TEST_ASSERT_EQUAL_INT(DEVICEKEY_SUCCESS, ret); @@ -268,9 +269,9 @@ void device_inject_root_of_trust_32_byte_size_test() */ void device_inject_root_of_trust_several_times_test() { - DeviceKey& devkey = DeviceKey::get_instance(); + DeviceKey &devkey = DeviceKey::get_instance(); uint32_t key[DEVICE_KEY_32BYTE / sizeof(uint32_t)]; - NVStore& nvstore = NVStore::get_instance(); + NVStore &nvstore = NVStore::get_instance(); int ret = nvstore.reset(); TEST_ASSERT_EQUAL_INT(DEVICEKEY_SUCCESS, ret); @@ -298,8 +299,8 @@ void generate_derived_key_consistency_16_byte_key_test() unsigned char empty_buffer[DEVICE_KEY_16BYTE]; unsigned char salt[] = "Once upon a time, I worked for the circus and I lived in Omaha."; int key_type = DEVICE_KEY_16BYTE; - DeviceKey& devkey = DeviceKey::get_instance(); - NVStore& nvstore = NVStore::get_instance(); + DeviceKey &devkey = DeviceKey::get_instance(); + NVStore &nvstore = NVStore::get_instance(); int ret = nvstore.reset(); TEST_ASSERT_EQUAL_INT(DEVICEKEY_SUCCESS, ret); @@ -333,8 +334,8 @@ void generate_derived_key_consistency_32_byte_key_test() unsigned char empty_buffer[DEVICE_KEY_32BYTE]; unsigned char salt[] = "The quick brown fox jumps over the lazy dog"; int key_type = DEVICE_KEY_32BYTE; - DeviceKey& devkey = DeviceKey::get_instance(); - NVStore& nvstore = NVStore::get_instance(); + DeviceKey &devkey = DeviceKey::get_instance(); + NVStore &nvstore = NVStore::get_instance(); int ret = nvstore.reset(); TEST_ASSERT_EQUAL_INT(DEVICEKEY_SUCCESS, ret); @@ -368,8 +369,8 @@ void generate_derived_key_key_type_16_test() unsigned char expectedString[] = "Some String"; int key_type = DEVICE_KEY_16BYTE; size_t salt_size = sizeof(salt); - DeviceKey& devkey = DeviceKey::get_instance(); - NVStore& nvstore = NVStore::get_instance(); + DeviceKey &devkey = DeviceKey::get_instance(); + NVStore &nvstore = NVStore::get_instance(); int ret = nvstore.reset(); TEST_ASSERT_EQUAL_INT(DEVICEKEY_SUCCESS, ret); @@ -399,8 +400,8 @@ void generate_derived_key_key_type_32_test() int key_type = DEVICE_KEY_32BYTE; size_t salt_size = sizeof(salt); unsigned char expectedString[] = "Some String"; - DeviceKey& devkey = DeviceKey::get_instance(); - NVStore& nvstore = NVStore::get_instance(); + DeviceKey &devkey = DeviceKey::get_instance(); + NVStore &nvstore = NVStore::get_instance(); int ret = nvstore.reset(); TEST_ASSERT_EQUAL_INT(DEVICEKEY_SUCCESS, ret); @@ -428,8 +429,8 @@ void generate_derived_key_wrong_key_type_test() unsigned char output[DEVICE_KEY_16BYTE]; unsigned char salt[] = "The quick brown fox jumps over the lazy dog"; size_t salt_size = sizeof(salt); - DeviceKey& devkey = DeviceKey::get_instance(); - NVStore& nvstore = NVStore::get_instance(); + DeviceKey &devkey = DeviceKey::get_instance(); + NVStore &nvstore = NVStore::get_instance(); nvstore.init(); int ret = nvstore.reset(); diff --git a/features/device_key/source/DeviceKey.cpp b/features/device_key/source/DeviceKey.cpp index 284d3ce2f4..c61d1b7643 100644 --- a/features/device_key/source/DeviceKey.cpp +++ b/features/device_key/source/DeviceKey.cpp @@ -117,7 +117,7 @@ int DeviceKey::write_key_to_nvstore(uint32_t *input, size_t isize) return ret; } - NVStore& nvstore = NVStore::get_instance(); + NVStore &nvstore = NVStore::get_instance(); ret = nvstore.set(NVSTORE_DEVICEKEY_KEY, (uint16_t)isize, input); if (NVSTORE_WRITE_ERROR == ret || NVSTORE_BUFF_TOO_SMALL == ret) { return DEVICEKEY_SAVE_FAILED; @@ -130,15 +130,15 @@ int DeviceKey::write_key_to_nvstore(uint32_t *input, size_t isize) return DEVICEKEY_SUCCESS; } -int DeviceKey::read_key_from_nvstore(uint32_t *output, size_t& size) +int DeviceKey::read_key_from_nvstore(uint32_t *output, size_t &size) { - if (size > (uint16_t)-1) { + if (size > (uint16_t) -1) { return DEVICEKEY_INVALID_PARAM; } uint16_t in_size = size; uint16_t out_size = 0; - NVStore& nvstore = NVStore::get_instance(); + NVStore &nvstore = NVStore::get_instance(); int nvStatus = nvstore.get(NVSTORE_DEVICEKEY_KEY, in_size, output, out_size); if (NVSTORE_NOT_FOUND == nvStatus) { return DEVICEKEY_NOT_FOUND; @@ -179,18 +179,18 @@ int DeviceKey::get_derived_key(uint32_t *ikey_buff, size_t ikey_size, const unsi do { - mbedtls_cipher_init(&ctx); - ret = mbedtls_cipher_setup(&ctx, cipher_info); - if (ret != 0) { - goto finish; - } + mbedtls_cipher_init(&ctx); + ret = mbedtls_cipher_setup(&ctx, cipher_info); + if (ret != 0) { + goto finish; + } ret = mbedtls_cipher_cmac_starts(&ctx, (unsigned char *)ikey_buff, ikey_size * 8); if (ret != 0) { goto finish; } - DEVKEY_WRITE_UINT8_LE(counter_enc, (counter+1)); + DEVKEY_WRITE_UINT8_LE(counter_enc, (counter + 1)); ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)counter_enc, sizeof(counter_enc)); if (ret != 0) { @@ -217,7 +217,7 @@ int DeviceKey::get_derived_key(uint32_t *ikey_buff, size_t ikey_size, const unsi goto finish; } - mbedtls_cipher_free( &ctx ); + mbedtls_cipher_free(&ctx); counter++; @@ -225,7 +225,7 @@ int DeviceKey::get_derived_key(uint32_t *ikey_buff, size_t ikey_size, const unsi finish: if (DEVICEKEY_SUCCESS != ret) { - mbedtls_cipher_free( &ctx ); + mbedtls_cipher_free(&ctx); return DEVICEKEY_ERR_CMAC_GENERIC_FAILURE; } diff --git a/features/device_key/source/DeviceKey.h b/features/device_key/source/DeviceKey.h index 08dbb4fcde..c9485b23de 100644 --- a/features/device_key/source/DeviceKey.h +++ b/features/device_key/source/DeviceKey.h @@ -56,36 +56,36 @@ public: /** * @brief As a singleton, return the single instance of the class. * Reason for this class being a singleton is the following: - * - Ease the use for users of this class not having to coordinate instantiations. + * - Ease of use for users of this class not having to coordinate instantiations. * - Lazy instantiation of internal data (which we can't achieve with simple static classes). * * @returns Singleton instance reference. */ - static DeviceKey& get_instance() + static DeviceKey &get_instance() { // Use this implementation of singleton (Meyer's) rather than the one that allocates // the instance on the heap, as it ensures destruction at program end (preventing warnings - // from memory checking tools such as valgrind). + // from memory checking tools, such as valgrind). static DeviceKey instance; return instance; } ~DeviceKey(); - /** Derive a new key based on the salt string. key type can be with values 16 bytes and 32 bytes - * @param isalt input buffer used to create the new key. Same input will generate always the same key - * @param isalt_size size of the data in salt buffer - * @param output buffer to receive the derived key. Size must be 16 bytes or 32 bytes + /** Derive a new key based on the salt string. + * @param isalt Input buffer used to create the new key. Same input always generates the same key + * @param isalt_size Size of the data in salt buffer. + * @param output Buffer to receive the derived key. Size must be 16 bytes or 32 bytes * according to the ikey_type parameter - * @param ikey_type type of the required key. Type must be 16 bytes or 32 bytes. + * @param ikey_type Type of the required key. Must be 16 bytes or 32 bytes. * @return 0 on success, negative error code on failure */ int generate_derived_key(const unsigned char *isalt, size_t isalt_size, unsigned char *output, uint16_t ikey_type); - /** Set a device key into the NVStore. In case TRNG support is missing, Call this method + /** Set a device key into the NVStore. If TRNG support is missing, call this method * before calling device_key_derived_key. This method should be called only once! - * @param value input buffer contain the key. - * @param isize size of the supplied key. Must be 16 bytes or 32 bytes. + * @param value Input buffer contain the key. + * @param isize Size of the supplied key. Must be 16 bytes or 32 bytes. * @return 0 on success, negative error code on failure */ int device_inject_root_of_trust(uint32_t *value, size_t isize); @@ -95,40 +95,40 @@ private: DeviceKey(); /** Read a device key from the NVStore - * @param output buffer for the returned key. - * @param size input: the size of the output buffer. - * output: the actual size of the written data + * @param output Buffer for the returned key. + * @param size Input: The size of the output buffer. + * Output: The actual size of the written data * @return 0 on success, negative error code on failure */ - int read_key_from_nvstore(uint32_t *output, size_t& size); + int read_key_from_nvstore(uint32_t *output, size_t &size); /** Set a device key into the NVStore - * @param input input buffer contain the key. - * @param isize the size of the input buffer. + * @param input Input buffer contain the key. + * @param isize The size of the input buffer. * @return 0 on success, negative error code on failure */ int write_key_to_nvstore(uint32_t *input, size_t isize); - /** Get a derived key base on a salt string. The methods implements - * Section 5.1 in NIST SP 800-108, Recommendation for Key Derivation Using Pseudorandom Functions - * @param ikey_buff input buffer holding the ROT key - * @param ikey_size size of the input key. Must be 16 bytes or 32 bytes. - * @param isalt input buffer contain some string. - * @param isalt_size size of the supplied input string. - * @param output buffer for the derived key result. - * @param ikey_type the requested key size. Must be 16 bytes or 32 bytes. + /** Get a derived key base on a salt string. The methods implements Section 5.1 + * in NIST SP 800-108, Recommendation for Key Derivation Using Pseudorandom Functions + * @param ikey_buff Input buffer holding the ROT key + * @param ikey_size Size of the input key. Must be 16 bytes or 32 bytes. + * @param isalt Input buffer contain some string. + * @param isalt_size Size of the supplied input string. + * @param output Buffer for the derived key result. + * @param ikey_type The requested key size. Must be 16 bytes or 32 bytes. * @return 0 on success, negative error code on failure */ int get_derived_key(uint32_t *ikey_buff, size_t ikey_size, const unsigned char *isalt, size_t isalt_size, unsigned char *output, uint32_t ikey_type); /** Generate a random ROT key by using TRNG - * @param output output buffer for the generated key. - * @param size input: the size of the buffer. if size is less - * then 16 bytes the method will generate an - * error. 16-31 bytes will create a 16 byte key. - * 32 or higher will generate a 32 bytes key - * output: the actual written size to the buffer + * @param output Output buffer for the generated key. + * @param size Input: The size of the buffer. If size is less + * than 16 bytes, the method generates an + * error. 16-31 bytes creates a 16-byte key. + * 32 or higher generates a 32-byte key + * Output: The actual written size to the buffer * @return 0 on success, negative error code on failure */ int generate_key_by_trng(uint32_t *output, size_t size); diff --git a/features/frameworks/greentea-client/source/greentea_metrics.cpp b/features/frameworks/greentea-client/source/greentea_metrics.cpp index 35cfb271e8..6b2be0da50 100644 --- a/features/frameworks/greentea-client/source/greentea_metrics.cpp +++ b/features/frameworks/greentea-client/source/greentea_metrics.cpp @@ -15,14 +15,10 @@ * limitations under the License. */ -#include "mbed.h" -#include "rtos.h" -#include "mbed_stats.h" -#include "cmsis_os2.h" #include "greentea-client/test_env.h" #include "greentea-client/greentea_metrics.h" -#include "SingletonPtr.h" -#include "CircularBuffer.h" +#include "platform/mbed_stats.h" +#include #define THREAD_BUF_COUNT 16 @@ -33,6 +29,21 @@ typedef struct { } thread_info_t; #if defined(MBED_STACK_STATS_ENABLED) && MBED_STACK_STATS_ENABLED + +#if !defined(MBED_CONF_RTOS_PRESENT) || !(MBED_CONF_RTOS_PRESENT) +#error "RTOS required for Stack stats" +#endif + +#include "rtos/Mutex.h" +#include "rtos/Thread.h" +#include "rtos/Kernel.h" +#include "mbed_stats.h" +#include "cmsis_os2.h" +#include "platform/SingletonPtr.h" +#include "platform/CircularBuffer.h" +using namespace mbed; +using namespace rtos; + // Mutex to protect "buf" static SingletonPtr mutex; static char buf[128]; @@ -43,7 +54,9 @@ static SingletonPtr > queue; static void send_CPU_info(void); #endif +#if defined(MBED_HEAP_STATS_ENABLED ) && MBED_HEAP_STATS_ENABLED static void send_heap_info(void); +#endif #if defined(MBED_STACK_STATS_ENABLED) && MBED_STACK_STATS_ENABLED static void send_stack_info(void); static void on_thread_terminate(osThreadId_t id); @@ -58,16 +71,18 @@ static uint32_t print_dec(char *buf, uint32_t value); void greentea_metrics_setup() { #if defined(MBED_STACK_STATS_ENABLED) && MBED_STACK_STATS_ENABLED - Thread::attach_terminate_hook(on_thread_terminate); + Kernel::attach_thread_terminate_hook(on_thread_terminate); #endif } void greentea_metrics_report() { +#if defined(MBED_HEAP_STATS_ENABLED ) && MBED_HEAP_STATS_ENABLED send_heap_info(); +#endif #if defined(MBED_STACK_STATS_ENABLED) && MBED_STACK_STATS_ENABLED send_stack_info(); - Thread::attach_terminate_hook(NULL); + Kernel::attach_thread_terminate_hook(NULL); #endif #if defined(MBED_CPU_STATS_ENABLED) send_CPU_info(); @@ -87,6 +102,7 @@ static void send_CPU_info() } #endif +#if defined(MBED_HEAP_STATS_ENABLED ) && MBED_HEAP_STATS_ENABLED static void send_heap_info() { mbed_stats_heap_t heap_stats; @@ -94,6 +110,7 @@ static void send_heap_info() greentea_send_kv("max_heap_usage",heap_stats.max_size); greentea_send_kv("reserved_heap",heap_stats.reserved_size); } +#endif #if defined(MBED_STACK_STATS_ENABLED) && MBED_STACK_STATS_ENABLED MBED_UNUSED static void send_stack_info() diff --git a/features/frameworks/greentea-client/source/greentea_test_env.cpp b/features/frameworks/greentea-client/source/greentea_test_env.cpp index 08e43fc917..2a5dda1b8f 100644 --- a/features/frameworks/greentea-client/source/greentea_test_env.cpp +++ b/features/frameworks/greentea-client/source/greentea_test_env.cpp @@ -18,7 +18,6 @@ #include #include #include -#include "mbed.h" #include "greentea-client/test_env.h" #include "greentea-client/greentea_serial.h" #include "greentea-client/greentea_metrics.h" diff --git a/features/frameworks/mbed-client-cli/mbed-client-cli/ns_cmdline.h b/features/frameworks/mbed-client-cli/mbed-client-cli/ns_cmdline.h index 09a0e68606..5a8c8db6f7 100644 --- a/features/frameworks/mbed-client-cli/mbed-client-cli/ns_cmdline.h +++ b/features/frameworks/mbed-client-cli/mbed-client-cli/ns_cmdline.h @@ -129,7 +129,7 @@ uint8_t cmd_history_size(uint8_t max); * \param fmt console print function (like printf) */ #if defined(__GNUC__) || defined(__CC_ARM) -void cmd_printf(const char *fmt, ...) __attribute__ ((__format__(__printf__, 1, 2))); +void cmd_printf(const char *fmt, ...) __attribute__((__format__(__printf__, 1, 2))); #else void cmd_printf(const char *fmt, ...); #endif @@ -139,7 +139,7 @@ void cmd_printf(const char *fmt, ...); * \param ap list of parameters needed by format string. This must correspond properly with the conversion specifier. */ #if defined(__GNUC__) || defined(__CC_ARM) -void cmd_vprintf(const char *fmt, va_list ap) __attribute__ ((__format__(__printf__, 1, 0))); +void cmd_vprintf(const char *fmt, va_list ap) __attribute__((__format__(__printf__, 1, 0))); #else void cmd_vprintf(const char *fmt, va_list ap); #endif @@ -273,6 +273,26 @@ void cmd_alias_add(const char *alias, const char *value); * \param value Value for variable. Values can contains white spaces and '"' or '"' characters. */ void cmd_variable_add(char *variable, char *value); +/** + * Add integer variable to interpreter. + * Variables are replaced with values before executing a command. + * \code + cmd_variable_add_int("world", 2); + cmd_exe("echo $world"); // this is now same as 'echo 2' . + * \endcode + * \param variable Variable name, which will be replaced in interpreter. + * \param value Value for variable + + */ +void cmd_variable_add_int(char *variable, int value); +/** + * Request screen size from host + * Response are stored to variables: + * COLUMNS and LINES - as integer values. + * Note: Require terminal that handle request codes, like screen. + */ +void cmd_request_screen_size(void); + /** find command parameter index by key. * e.g. diff --git a/features/frameworks/mbed-client-cli/source/ns_cmdline.c b/features/frameworks/mbed-client-cli/source/ns_cmdline.c index 55e4d000a1..828b0f8bbd 100644 --- a/features/frameworks/mbed-client-cli/source/ns_cmdline.c +++ b/features/frameworks/mbed-client-cli/source/ns_cmdline.c @@ -20,7 +20,7 @@ #include #include -#if defined(_WIN32) || defined(__unix__) || defined(__unix) || defined(unix) || defined(YOTTA_CFG) +#if defined(_WIN32) || defined(__unix__) || defined(__unix) || defined(unix) || defined(MBED_CONF_RTOS_PRESENT) || defined(__APPLE__) #include //malloc #ifndef MEM_ALLOC #define MEM_ALLOC malloc @@ -59,8 +59,9 @@ #define tr_debug(...) printf( __VA_ARGS__);printf("\r\n") #endif +// #define MBED_CLIENT_CLI_TRACE_ENABLE // MBED_CLIENT_CLI_TRACE_ENABLE is to enable the traces for debugging, -// default all debug traces are disabled. +// By default all debug traces are disabled. #ifndef MBED_CLIENT_CLI_TRACE_ENABLE #undef tr_error #define tr_error(...) @@ -80,14 +81,39 @@ #define TRACE_GROUP "cmdL" +#ifndef MBED_CMDLINE_BOOT_MESSAGE +#define MBED_CMDLINE_BOOT_MESSAGE "ARM Ltd\r\n" +#endif +#define ESCAPE(x) "\x1b" x +#define CR_S "\r" +#define LF_S "\n" +#define CLEAR_ENTIRE_LINE ESCAPE("[2K") +#define CLEAR_ENTIRE_SCREEN ESCAPE("[2J") +#define ENABLE_AUTO_WRAP_MODE ESCAPE("[7h") +#define MOVE_CURSOR_LEFT_N_CHAR ESCAPE("[%dD") + +#define SET_TOP_AND_BOTTOM_LINES ESCAPE("[;r") +#define MOVE_CURSOR_TO_BOTTOM_RIGHT ESCAPE("[999;999H") +#define STORE_CURSOR_POS ESCAPE("7") +#define RESTORE_CURSOR_POS ESCAPE("8") +#define GET_CURSOR_POSITION ESCAPE("[6n") + +#define REQUEST_SCREEN_SIZE STORE_CURSOR_POS SET_TOP_AND_BOTTOM_LINES MOVE_CURSOR_TO_BOTTOM_RIGHT GET_CURSOR_POSITION RESTORE_CURSOR_POS + /*ASCII defines*/ #define ESC 0x1B #define DEL 0x7F #define BS 0x08 #define ETX 0x03 +#define ETB 0x17 #define TAB 0x09 #define CAN 0x18 +#define DEFAULT_RETFMT "retcode: %i\r\n" +#define DEFAULT_PROMPT "/>" +#define VAR_PROMPT "PS1" +#define VAR_RETFMT "RETFMT" + // Maximum length of input line #ifdef MBED_CMDLINE_MAX_LINE_LENGTH #define MAX_LINE MBED_CMDLINE_MAX_LINE_LENGTH @@ -106,9 +132,10 @@ #else #define HISTORY_MAX_COUNT 32 #endif - //include manuals or not (save memory a little when not include) -#define INCLUDE_MAN +#ifndef MBED_CMDLINE_INCLUDE_MAN +#define MBED_CMDLINE_INCLUDE_MAN 1 +#endif typedef struct cmd_history_s { @@ -131,9 +158,19 @@ typedef struct cmd_alias_s { ns_list_link_t link; } cmd_alias_t; +union Data { + char *ptr; + int i; +}; +typedef enum value_type_s { + VALUE_TYPE_STR, + VALUE_TYPE_INT +} value_type_t; + typedef struct cmd_variable_s { char *name_ptr; - char *value_ptr; + union Data value; + value_type_t type; ns_list_link_t link; } cmd_variable_t; @@ -173,10 +210,9 @@ typedef struct cmd_class_s { int tab_lookup; // originally lookup characters count int tab_lookup_cmd_n; // index in command list int tab_lookup_n; // + bool prev_cr; // indicate if cr was last char bool echo; // echo inputs - char *retcode_fmt; // retcode format - bool print_retcode; // print retcode after command is executed - cmd_ready_cb_f *ready_cb; // ready cb function + cmd_ready_cb_f *ready_cb; // ready cb function cmd_list_t cmd_buffer; cmd_exe_t *cmd_buffer_ptr; cmd_command_t *cmd_ptr; @@ -191,7 +227,13 @@ typedef struct cmd_class_s { input_passthrough_func_t passthrough_fnc; // input passthrough cb function } cmd_class_t; -cmd_class_t cmd = { .init = false, .retcode_fmt = NULL, .cmd_ptr = NULL, .mutex_wait_fnc = NULL, .mutex_release_fnc = NULL, .passthrough_fnc = NULL }; +cmd_class_t cmd = { + .init = false, + .cmd_ptr = NULL, + .mutex_wait_fnc = NULL, + .mutex_release_fnc = NULL, + .passthrough_fnc = NULL +}; /* Function prototypes */ @@ -208,6 +250,9 @@ static void cmd_history_clean(void); static void cmd_echo(bool on); static cmd_history_t *cmd_history_find(int16_t index); static bool cmd_tab_lookup(void); +static void cmd_clear_last_word(void); +static void cmd_move_cursor_to_last_space(void); +static void cmd_move_cursor_to_next_space(void); static const char *cmd_input_lookup(char *name, int namelength, int n); static char *cmd_input_lookup_var(char *name, int namelength, int n); static cmd_command_t *cmd_find(const char *name); @@ -220,7 +265,6 @@ static void cmd_print_man(cmd_command_t *command_ptr); static void goto_end_of_history(void); static void goto_beginning_of_history(void); static void cmd_set_input(const char *str, int cur); -static void cmd_set_retfmt(char *fmt); static char *next_command(char *string_ptr, operator_t *mode); /** Run single command through cmd intepreter * \param string_ptr command string with parameters @@ -233,13 +277,23 @@ static void cmd_push(char *cmd_str, operator_t oper); /*internal shell commands */ +int true_command(int argc, char *argv[]); +int false_command(int argc, char *argv[]); int echo_command(int argc, char *argv[]); int alias_command(int argc, char *argv[]); +int unset_command(int argc, char *argv[]); int set_command(int argc, char *argv[]); int clear_command(int argc, char *argv[]); int help_command(int argc, char *argv[]); int history_command(int argc, char *argv[]); +/** Internal helper functions + */ +static const char *find_last_space(const char *from, const char *to); +static int replace_string( + char *str, int str_len, + const char *old_str, const char *new_str); + void default_cmd_response_out(const char *fmt, va_list ap) { vprintf(fmt, ap); @@ -277,10 +331,10 @@ void cmd_init(cmd_print_t *outf) cmd.out = outf ? outf : default_cmd_response_out; cmd.ctrl_fnc = NULL; cmd.echo = true; - cmd.print_retcode = false; cmd.escaping = false; cmd.insert = true; cmd.cursor = 0; + cmd.prev_cr = false; cmd.vt100_on = true; cmd.history_max_count = HISTORY_MAX_COUNT; cmd.tab_lookup = 0; @@ -290,21 +344,39 @@ void cmd_init(cmd_print_t *outf) cmd.idle = true; cmd.ready_cb = cmd_next; cmd.passthrough_fnc = NULL; - cmd_set_retfmt("retcode: %i\r\n"); + cmd_variable_add(VAR_PROMPT, DEFAULT_PROMPT); + cmd_variable_add_int("?", 0); + //cmd_alias_add("auto-on", "set PS1=\r\nretcode=$?\r\n&&echo off"); + //cmd_alias_add("auto-off", "set PS1="DEFAULT_PROMPT"&&echo on"); cmd_line_clear(0); // clear line cmd_history_save(0); // the current line is the 0 item - //cmd_free(); cmd_init_base_commands(); cmd_init_screen(); return; } +void cmd_request_screen_size(void) +{ + cmd_printf(REQUEST_SCREEN_SIZE); +} -#ifdef INCLUDE_MAN +const char *cmdline_get_prompt(void) +{ + cmd_variable_t *var_ptr = variable_find(VAR_PROMPT); + return var_ptr && var_ptr->type == VALUE_TYPE_STR ? var_ptr->value.ptr : ""; +} +const char *cmd_get_retfmt(void) +{ + cmd_variable_t *var_ptr = variable_find(VAR_RETFMT); + return var_ptr && var_ptr->type == VALUE_TYPE_STR ? var_ptr->value.ptr : 0; +} + +#if MBED_CMDLINE_INCLUDE_MAN == 1 #define MAN_ECHO "Displays messages, or turns command echoing on or off\r\n"\ "echo \r\n"\ "some special parameters:\r\n"\ " On/Off echo input characters\r\n" #define MAN_ALIAS "alias \r\n" +#define MAN_UNSET "unset \r\n" #define MAN_SET "set \r\n"\ "some special parameters\r\n"\ "--vt100 On/Off vt100 controls\r\n"\ @@ -328,9 +400,12 @@ static void cmd_init_base_commands(void) cmd_add("help", help_command, "This help", NULL); cmd_add("echo", echo_command, "Echo controlling", MAN_ECHO); cmd_add("alias", alias_command, "Handle aliases", MAN_ALIAS); - cmd_add("set", set_command, "Handle variables", MAN_SET); + cmd_add("unset", unset_command, "unset variables", MAN_UNSET); + cmd_add("set", set_command, "print or set variables", MAN_SET); cmd_add("clear", clear_command, "Clears the display", MAN_CLEAR); cmd_add("history", history_command, "View your command Line History", MAN_HISTORY); + cmd_add("true", true_command, 0, 0); + cmd_add("false", false_command, 0, 0); } void cmd_reset(void) { @@ -346,7 +421,9 @@ void cmd_free(void) cmd_alias_add(cur_ptr->name_ptr, NULL); } ns_list_foreach_safe(cmd_variable_t, cur_ptr, &cmd.variable_list) { - cmd_variable_add(cur_ptr->name_ptr, NULL); + if (cur_ptr->type == VALUE_TYPE_STR) { + cmd_variable_add(cur_ptr->value.ptr, NULL); + } } ns_list_foreach_safe(cmd_history_t, cur_ptr, &cmd.history_list) { MEM_FREE(cur_ptr->command_ptr); @@ -379,8 +456,7 @@ void cmd_set_ready_cb(cmd_ready_cb_f *cb) } void cmd_ready(int retcode) { - if( cmd.cmd_ptr && cmd.cmd_ptr->busy ) - { + if (cmd.cmd_ptr && cmd.cmd_ptr->busy) { //execution finished cmd.cmd_ptr->busy = false; } @@ -412,9 +488,8 @@ void cmd_next(int retcode) //yep there was some -> lets execute it retcode = cmd_run(cmd.cmd_buffer_ptr->cmd_s); //check if execution goes to the backend or not - if (retcode == CMDLINE_RETCODE_EXCUTING_CONTINUE ) { - if( (NULL != cmd.cmd_buffer_ptr) && cmd.cmd_buffer_ptr->operator == OPERATOR_BACKGROUND ) - { + if (retcode == CMDLINE_RETCODE_EXCUTING_CONTINUE) { + if ((NULL != cmd.cmd_buffer_ptr) && cmd.cmd_buffer_ptr->operator == OPERATOR_BACKGROUND) { //execution continue in background, but operator say that it's "ready" cmd_ready(CMDLINE_RETCODE_SUCCESS); } else { @@ -426,8 +501,9 @@ void cmd_next(int retcode) cmd_ready(retcode); } } else { - if (cmd.print_retcode) { - cmd_printf(cmd.retcode_fmt, retcode); + const char *retfmt = cmd_get_retfmt(); + if (retfmt) { + cmd_printf(retfmt, retcode); } cmd_line_clear(0); if (cmd.echo) { @@ -441,7 +517,7 @@ static cmd_exe_t *cmd_pop(void) *next_cmd = ns_list_get_next(&cmd.cmd_buffer, cmd_ptr); if (cmd.cmd_buffer_ptr == 0) { - //was first in bool-- + //was first in bool next_cmd = ns_list_get_first(&cmd.cmd_buffer); } else { MEM_FREE(cmd_ptr->cmd_s); @@ -460,7 +536,6 @@ static cmd_exe_t *cmd_next_ptr(int retcode) if (cmd.cmd_buffer_ptr == NULL) { return cmd_pop(); } - retcode = retcode; switch (cmd.cmd_buffer_ptr->operator) { case (OPERATOR_AND): if (retcode != CMDLINE_RETCODE_SUCCESS) { @@ -482,7 +557,9 @@ static cmd_exe_t *cmd_next_ptr(int retcode) next_cmd = cmd_pop(); break; case (OPERATOR_PIPE): - /// @TODO + cmd_printf("pipe is not supported\r\n"); + while ((next_cmd = cmd_pop()) != 0); + break; case (OPERATOR_SEMI_COLON): default: //get next command to be execute (might be null if there is no more) @@ -511,7 +588,16 @@ static void cmd_push(char *cmd_str, operator_t oper) { //store this command to the stack cmd_exe_t *cmd_ptr = MEM_ALLOC(sizeof(cmd_exe_t)); + if (cmd_ptr == NULL) { + tr_error("mem alloc failed in cmd_push"); + return; + } cmd_ptr->cmd_s = MEM_ALLOC(strlen(cmd_str) + 1); + if (cmd_ptr->cmd_s == NULL) { + MEM_FREE(cmd_ptr); + tr_error("mem alloc failed in cmd_push cmd_s"); + return; + } strcpy(cmd_ptr->cmd_s, cmd_str); cmd_ptr->operator = oper; ns_list_add_to_end(&cmd.cmd_buffer, cmd_ptr); @@ -547,14 +633,13 @@ void cmd_mutex_unlock() cmd.mutex_release_fnc(); } } - void cmd_init_screen() { if (cmd.vt100_on) { - cmd_printf("\r\x1b[2J"); /* Clear screen */ - cmd_printf("\x1b[7h"); /* enable line wrap */ + cmd_printf(CR_S CLEAR_ENTIRE_SCREEN); /* Clear screen */ + cmd_printf(ENABLE_AUTO_WRAP_MODE); /* enable line wrap */ } - cmd_printf("ARM Ltd\r\n"); + cmd_printf(MBED_CMDLINE_BOOT_MESSAGE); cmd_output(); } uint8_t cmd_history_size(uint8_t max) @@ -576,8 +661,8 @@ bool cmd_echo_state(void) static cmd_command_t *cmd_find_n(char *name, int nameLength, int n) { cmd_command_t *cmd_ptr = NULL; - int i = 0; if (name != NULL && nameLength != 0) { + int i = 0; ns_list_foreach(cmd_command_t, cur_ptr, &cmd.command_list) { if (strncmp(name, cur_ptr->name_ptr, nameLength) == 0) { if (i == n) { @@ -601,7 +686,7 @@ static const char *cmd_input_lookup(char *name, int namelength, int n) n -= cmd.tab_lookup_n; cmd_alias_t *alias = alias_find_n(name, namelength, n); if (alias) { - str = (const char*)alias->name_ptr; + str = (const char *)alias->name_ptr; } } @@ -642,9 +727,17 @@ void cmd_add(const char *name, cmd_run_cb *callback, const char *info, const cha return; } cmd_ptr = (cmd_command_t *)MEM_ALLOC(sizeof(cmd_command_t)); + if (cmd_ptr == NULL) { + tr_error("mem alloc failed in cmd_add"); + return; + } cmd_ptr->name_ptr = name; cmd_ptr->info_ptr = info; +#if MBED_CMDLINE_INCLUDE_MAN == 1 cmd_ptr->man_ptr = man; +#else + cmd_ptr->man_ptr = 0; +#endif cmd_ptr->run_cb = callback; cmd_ptr->busy = false; ns_list_add_to_end(&cmd.command_list, cmd_ptr); @@ -662,9 +755,16 @@ void cmd_delete(const char *name) MEM_FREE(cmd_ptr); return; } - +static void replace_escapes(char *string_ptr) +{ + while ((string_ptr = strchr(string_ptr, '\\')) != NULL) { + memmove(string_ptr, string_ptr + 1, strlen(string_ptr + 1) + 1); + string_ptr++; + } +} static int cmd_parse_argv(char *string_ptr, char **argv) { + tr_deep("cmd_parse_argv(%s, ..)\r\n", string_ptr); int argc = 0; char *str_ptr, *end_quote_ptr = NULL; @@ -675,28 +775,44 @@ static int cmd_parse_argv(char *string_ptr, char **argv) str_ptr = string_ptr; do { argv[argc] = str_ptr; - if (*str_ptr == '"') { - // check if end quote - end_quote_ptr = strstr(str_ptr + 1, "\""); - } - if (*str_ptr == '"' && end_quote_ptr != NULL) { - // remove quotes give as one parameter - argv[argc]++; - str_ptr = end_quote_ptr; + // tr_deep("parsing.. argv[%d]: %s\r\n", argc, str_ptr); + if (*str_ptr != '\\') { + if (*str_ptr == '"') { + // check if end quote + end_quote_ptr = str_ptr; + do { + end_quote_ptr = strchr(end_quote_ptr + 1, '\"'); + if (end_quote_ptr == NULL) { + break; + } + } while (*(end_quote_ptr - 1) == '\\'); + if (end_quote_ptr != NULL) { + // remove quotes give as one parameter + argv[argc]++; + str_ptr = end_quote_ptr; + } else { + str_ptr = strchr(str_ptr, ' '); + } + } else { + str_ptr = strchr(str_ptr, ' '); + } } else { - str_ptr = strstr(str_ptr, " "); + str_ptr = strchr(str_ptr, ' '); } - argc++; + argc++; // one argument parsed if (str_ptr == NULL) { break; } if (argc > MAX_ARGUMENTS) { + tr_warn("Maximum arguments (%d) reached", MAX_ARGUMENTS); break; } *str_ptr++ = 0; + replace_escapes(argv[argc - 1]); + // tr_deep("parsed argv[%d]: %s\r\n", argc-1, argv[argc-1]); while (*str_ptr == ' ') { - str_ptr++; // skip spaces - } + str_ptr++; // skip spaces + }; } while (*str_ptr != 0); return argc; } @@ -754,7 +870,6 @@ static char *next_command(char *string_ptr, operator_t *oper) } case ('|'): if (ptr[1] == '|') { - tr_warn("or operator not supported"); if (oper) { *oper = OPERATOR_OR; *ptr = 0; @@ -784,6 +899,10 @@ static int cmd_run(char *string_ptr) tr_info("Executing cmd: '%s'", string_ptr); char *command_str = MEM_ALLOC(MAX_LINE); + if (command_str == NULL) { + tr_error("mem alloc failed in cmd_run"); + return CMDLINE_RETCODE_FAIL; + } while (isspace((unsigned char) *string_ptr) && *string_ptr != '\n' && *string_ptr != 0) { @@ -817,7 +936,7 @@ static int cmd_run(char *string_ptr) return CMDLINE_RETCODE_SUCCESS; } - if( cmd.cmd_ptr->busy ) { + if (cmd.cmd_ptr->busy) { MEM_FREE(command_str); return CMDLINE_RETCODE_COMMAND_BUSY; } @@ -825,9 +944,8 @@ static int cmd_run(char *string_ptr) // Run the actual callback cmd.cmd_ptr->busy = true; ret = cmd.cmd_ptr->run_cb(argc, argv); -#ifndef TEST - cmd_alias_add("_", command_str); // last executed command -#endif + cmd_variable_add_int("?", ret); + cmd_alias_add("_", string_ptr); // last executed command MEM_FREE(command_str); switch (ret) { case (CMDLINE_RETCODE_COMMAND_NOT_IMPLEMENTED): @@ -843,100 +961,87 @@ static int cmd_run(char *string_ptr) } return ret; } - void cmd_escape_start(void) { cmd.escaping = true; memset(cmd.escape, 0, sizeof(cmd.escape)); cmd.escape_index = 0; } -char *strrevchr(const char *begin, const char *end, char ch) +static void cmd_arrow_right() { - char *ptr = (char *)end; - while (begin <= ptr) { - if (*ptr == ch) { - return ptr; - } - if (*ptr == 0) { - return ptr; - } - ptr--; + /* @todo handle shift + if(strncmp(cmd.escape+1, "1;2", 3) == 0) { + tr_debug("Shift pressed"); + shift = true; + } + */ + if ((cmd.escape_index == 1 && cmd.escape[0] == 'O') || + (cmd.escape_index == 4 && strncmp(cmd.escape + 1, "1;5", 3) == 0)) { + cmd_move_cursor_to_next_space(); + } else { + cmd.cursor ++; + } + if ((int)cmd.cursor > (int)strlen(cmd.input)) { + cmd.cursor = strlen(cmd.input); + } +} +static void cmd_arrow_left() +{ + /* @todo handle shift + if(strncmp(cmd.escape+1, "1;2", 3) == 0) { + tr_debug("Shift pressed"); + shift = true; + } + */ + if ((cmd.escape_index == 1 && cmd.escape[0] == 'O') || + (cmd.escape_index == 4 && strncmp(cmd.escape + 1, "1;5", 3) == 0)) { + cmd_move_cursor_to_last_space(); + } else { + cmd.cursor --; + } + if (cmd.cursor < 0) { + cmd.cursor = 0; + } +} +static void cmd_arrow_up() +{ + int16_t old_entry = cmd.history++; + if (NULL == cmd_history_find(cmd.history)) { + cmd.history = old_entry; + } + if (old_entry != cmd.history) { + cmd_history_save(old_entry); + cmd_history_get(cmd.history); + } +} +static void cmd_arrow_down(void) +{ + int16_t old_entry = cmd.history--; + if (cmd.history < 0) { + cmd.history = 0; + } + + if (old_entry != cmd.history) { + cmd_history_save(old_entry); + cmd_history_get(cmd.history); } - return 0; } void cmd_escape_read(int16_t u_data) { - int16_t old_entry; + tr_debug("cmd_escape_read: %02x '%c' escape_index: %d: %s", + u_data, + (isprint(u_data) ? u_data : '?'), + cmd.escape_index, + cmd.escape); - tr_debug("cmd_escape_read: %02x '%c'", u_data, (isprint(u_data) ? u_data : '?')); - - if (u_data == '[') { - /*first character for longer escape sequence ends in character*/ - cmd.escape[cmd.escape_index++] = '['; - return; - } if (u_data == 'D') { - /* Arrow left*/ - if ((cmd.escape_index == 1 && cmd.escape[0] == 'O') || - (cmd.escape_index == 4 && strncmp(cmd.escape + 1, "1;5", 3) == 0)) { - - char *ptr = cmd.input + cmd.cursor; - if (*ptr == ' ' || *ptr == 0) { - ptr--; - } - ptr = strrevchr(cmd.input, ptr, ' '); //@todo not working way that we want - if (ptr) { - cmd.cursor = ptr - cmd.input; - } else { - cmd.cursor = 0; - } - } else { - cmd.cursor --; - } - if (cmd.cursor < 0) { - cmd.cursor = 0; - } + cmd_arrow_left(); } else if (u_data == 'C') { - /* Arrow Right*/ - if ((cmd.escape_index == 1 && cmd.escape[0] == 'O') || - (cmd.escape_index == 4 && strncmp(cmd.escape + 1, "1;5", 3) == 0)) { - char *ptr = cmd.input + cmd.cursor; - if (*ptr == ' ') { - ptr++; - } - ptr = strchr(ptr, ' '); - if (ptr) { - cmd.cursor = ptr - cmd.input; - } else { - cmd.cursor = strlen(cmd.input); - } - } else { - cmd.cursor ++; - } - if ((int)cmd.cursor > (int)strlen(cmd.input)) { - cmd.cursor = strlen(cmd.input); - } + cmd_arrow_right(); } else if (u_data == 'A') { - /* Arrow Up*/ - old_entry = cmd.history++; - if (NULL == cmd_history_find(cmd.history)) { - cmd.history = old_entry; - } - if (old_entry != cmd.history) { - cmd_history_save(old_entry); - cmd_history_get(cmd.history); - } + cmd_arrow_up(); } else if (u_data == 'B') { - /* Arrow Down*/ - old_entry = cmd.history--; - if (cmd.history < 0) { - cmd.history = 0; - } - - if (old_entry != cmd.history) { - cmd_history_save(old_entry); - cmd_history_get(cmd.history); - } + cmd_arrow_down(); } else if (u_data == 'Z') { // Shift+TAB if (cmd.tab_lookup > 0) { @@ -947,6 +1052,32 @@ void cmd_escape_read(int16_t u_data) } } cmd_tab_lookup(); + } else if (u_data == 'b') { + cmd_move_cursor_to_last_space(); + } else if (u_data == 'f') { + cmd_move_cursor_to_next_space(); + } else if (u_data == 'n') { + if (cmd.escape[1] == '5') { + // Device status report + // Response: terminal is OK + cmd_printf("%c0n", ESC); + } else if (cmd.escape[1] == '6') { + // Get cursor position + cmd_printf(ESCAPE("%d%d"), 0, cmd.cursor); + } + } else if (u_data == 'R') { + // response for Get cursor position ([6n) + // [;R + char *ptr; + int lines = strtol(cmd.escape + 1, &ptr, 10); + if (ptr == NULL) { + tr_warn("Invalid response: %s%c", cmd.escape, u_data); + } else { + int cols = strtol(ptr + 1, 0, 10); + tr_debug("Lines: %d, cols: %d", lines, cols); + cmd_variable_add_int("LINES", lines); + cmd_variable_add_int("COLUMNS", cols); + } } else if (u_data == 'H') { // Xterm support cmd.cursor = 0; @@ -1029,21 +1160,28 @@ static void cmd_reset_tab(void) } void cmd_char_input(int16_t u_data) { + if (cmd.prev_cr && u_data == '\n') { + // ignore \n if previous character was \r -> + // that triggers execute so \n does not need to anymore + cmd.prev_cr = false; // unset to ensure we doesn't go here anymore + return; + } /*Handle passthrough*/ if (cmd.passthrough_fnc != NULL) { cmd.passthrough_fnc(u_data); return; } - /*handle ecape command*/ if (cmd.escaping == true) { cmd_escape_read(u_data); return; } + tr_debug("input char: %02x '%c', cursor: %i, input: \"%s\"", u_data, (isprint(u_data) ? u_data : ' '), cmd.cursor, cmd.input); /*Normal character input*/ if (u_data == '\r' || u_data == '\n') { + cmd.prev_cr = u_data == '\r'; cmd_reset_tab(); if (strlen(cmd.input) == 0) { if (cmd.echo) { @@ -1079,6 +1217,13 @@ void cmd_char_input(int16_t u_data) if (cmd.echo) { cmd_output(); } + } else if (u_data == ETB) { + //ctrl+w (End of xmit block) + tr_debug("ctrl+w - remove last word to cursor"); + cmd_clear_last_word(); + if (cmd.echo) { + cmd_output(); + } } else if (u_data == TAB) { bool inc = false; if (cmd.tab_lookup > 0) { @@ -1106,7 +1251,7 @@ void cmd_char_input(int16_t u_data) } } else { cmd_reset_tab(); - tr_deep("cursor: %d, inputlen: %d, u_data: %c\r\n", cmd.cursor, strlen(cmd.input), u_data); + tr_deep("cursor: %d, inputlen: %lu, u_data: %c\r\n", cmd.cursor, strlen(cmd.input), u_data); if ((strlen(cmd.input) >= MAX_LINE - 1) || (cmd.cursor >= MAX_LINE - 1)) { tr_warn("input buffer full"); if (cmd.echo) { @@ -1151,7 +1296,6 @@ bool cmd_tab_lookup(void) if (len == 0) { return false; } - char *variable_keypart; int lookupSize; int varpos = check_variable_keylookup_size(&variable_keypart, &lookupSize); @@ -1170,27 +1314,69 @@ bool cmd_tab_lookup(void) return true; } } - return false; } +static void cmd_move_cursor_to_last_space(void) +{ + if (cmd.cursor) { + cmd.cursor--; + } else { + return; + } + const char *last_space = find_last_space(cmd.input + cmd.cursor, cmd.input); + if (last_space) { + cmd.cursor = last_space - cmd.input; + } else { + cmd.cursor = 0; + } +} +static void cmd_move_cursor_to_next_space(void) +{ + while (cmd.input[cmd.cursor] == ' ') { + cmd.cursor++; + } + const char *next_space = strchr(cmd.input + cmd.cursor, ' '); + if (next_space) { + cmd.cursor = next_space - cmd.input; + } else { + cmd.cursor = (int)strlen(cmd.input); + } +} +static void cmd_clear_last_word() +{ + if (!cmd.cursor) { + return; + } + char *ptr = cmd.input + cmd.cursor - 1; + while (*ptr == ' ' && ptr >= cmd.input) { + ptr--; + } + const char *last_space = find_last_space(ptr, cmd.input); + if (last_space) { + memmove((void *)last_space, &cmd.input[cmd.cursor], strlen(cmd.input + cmd.cursor) + 1); + cmd.cursor = last_space - cmd.input; + } else { + memmove((void *)cmd.input, &cmd.input[cmd.cursor], strlen(cmd.input + cmd.cursor) + 1); + cmd.cursor = 0; + } +} void cmd_output(void) { if (cmd.vt100_on && cmd.idle) { - cmd_printf("\r\x1b[2K/>%s \x1b[%dD", cmd.input, (int)strlen(cmd.input) - cmd.cursor + 1); + int curpos = (int)strlen(cmd.input) - cmd.cursor + 1; + cmd_printf(CR_S CLEAR_ENTIRE_LINE "%s%s " MOVE_CURSOR_LEFT_N_CHAR, + cmdline_get_prompt(), cmd.input, curpos); } } void cmd_echo_off(void) { - cmd.echo = false; + cmd_echo(false); } void cmd_echo_on(void) { - cmd.echo = true; + cmd_echo(true); } // alias -#ifndef TEST -static -#endif int replace_alias(char *str, const char *old_str, const char *new_str) { int old_len = strlen(old_str), @@ -1211,28 +1397,32 @@ static void cmd_replace_alias(char *input) } } //variable -#ifndef TEST -static -#endif -void replace_variable(char *str, const char *old_str, const char *new_str) +static void replace_variable(char *str, cmd_variable_t *variable_ptr) { - char *ptr = str; - int old_len = strlen(old_str), - new_len = strlen(new_str); - if (old_len > 0) { - while ((ptr = strstr(ptr, old_str)) != 0) { - if (ptr > str && *(ptr - 1) == '$') { - memmove(ptr + new_len - 1, ptr + old_len, strlen(ptr + old_len) + 1); - memcpy(ptr - 1, new_str, new_len); - } - ptr++; - } + const char *name = variable_ptr->name_ptr; + int name_len = strlen(variable_ptr->name_ptr); + char *value; + char valueLocal[11]; + if (variable_ptr->type == VALUE_TYPE_STR) { + value = variable_ptr->value.ptr; + } else { + value = valueLocal; + snprintf(value, 11, "%d", variable_ptr->value.i); } + char *tmp = MEM_ALLOC(name_len + 2); + if (tmp == NULL) { + tr_error("mem alloc failed in replace_variable"); + return; + } + tmp[0] = '$'; + strcpy(tmp + 1, name); + replace_string(str, MAX_LINE, tmp, value); + MEM_FREE(tmp); } -void cmd_replace_variables(char *input) +static void cmd_replace_variables(char *input) { ns_list_foreach(cmd_variable_t, cur_ptr, &cmd.variable_list) { - replace_variable(input, cur_ptr->name_ptr, cur_ptr->value_ptr); + replace_variable(input, cur_ptr); } } //history @@ -1286,6 +1476,10 @@ static void cmd_history_save(int16_t index) if (entry_ptr == NULL) { /*new entry*/ entry_ptr = (cmd_history_t *)MEM_ALLOC(sizeof(cmd_history_t)); + if (entry_ptr == NULL) { + tr_error("mem alloc failed in cmd_history_save"); + return; + } entry_ptr->command_ptr = NULL; ns_list_add_to_start(&cmd.history_list, entry_ptr); } @@ -1294,6 +1488,11 @@ static void cmd_history_save(int16_t index) MEM_FREE(entry_ptr->command_ptr); } entry_ptr->command_ptr = (char *)MEM_ALLOC(len + 1); + if (entry_ptr->command_ptr == NULL) { + tr_error("mem alloc failed in cmd_history_save command_ptr"); + cmd_history_item_delete(entry_ptr); + return; + } strcpy(entry_ptr->command_ptr, cmd.input); cmd_history_clean_overflow(); @@ -1321,14 +1520,14 @@ static void cmd_line_clear(int from) static void cmd_execute(void) { if (strlen(cmd.input) != 0) { - bool noduplicate = true; + bool noduplicates = true; cmd_history_t *entry_ptr = cmd_history_find(0); if (entry_ptr) { if (strcmp(entry_ptr->command_ptr, cmd.input) == 0) { - noduplicate = false; + noduplicates = false; } } - if (noduplicate) { + if (noduplicates) { cmd_history_save(0); // new is saved to place 0 cmd_history_save(-1); // new is created to the current one } @@ -1425,8 +1624,10 @@ static void cmd_alias_print_all(void) static void cmd_variable_print_all(void) { ns_list_foreach(cmd_variable_t, cur_ptr, &cmd.variable_list) { - if (cur_ptr->name_ptr != NULL) { - cmd_printf("%-18s'%s'\r\n", cur_ptr->name_ptr, cur_ptr->value_ptr ? cur_ptr->value_ptr : ""); + if (cur_ptr->type == VALUE_TYPE_STR) { + cmd_printf("%s='%s'\r\n", cur_ptr->name_ptr, cur_ptr->value.ptr ? cur_ptr->value.ptr : ""); + } else if (cur_ptr->type == VALUE_TYPE_INT) { + cmd_printf("%s=%d\r\n", cur_ptr->name_ptr, cur_ptr->value.i); } } return; @@ -1448,8 +1649,17 @@ void cmd_alias_add(const char *alias, const char *value) return; // no need to add new empty one } alias_ptr = (cmd_alias_t *)MEM_ALLOC(sizeof(cmd_alias_t)); - ns_list_add_to_end(&cmd.alias_list, alias_ptr); + if (alias_ptr == NULL) { + tr_error("Mem alloc fail in cmd_alias_add"); + return; + } alias_ptr->name_ptr = (char *)MEM_ALLOC(strlen(alias) + 1); + if (alias_ptr->name_ptr == NULL) { + MEM_FREE(alias_ptr); + tr_error("Mem alloc fail in cmd_alias_add name_ptr"); + return; + } + ns_list_add_to_end(&cmd.alias_list, alias_ptr); strcpy(alias_ptr->name_ptr, alias); alias_ptr->value_ptr = NULL; } @@ -1465,46 +1675,103 @@ void cmd_alias_add(const char *alias, const char *value) MEM_FREE(alias_ptr->value_ptr); } alias_ptr->value_ptr = (char *)MEM_ALLOC(strlen(value) + 1); + if (alias_ptr->value_ptr == NULL) { + cmd_alias_add(alias, NULL); + tr_error("Mem alloc fail in cmd_alias_add value_ptr"); + return; + } strcpy(alias_ptr->value_ptr, value); } return; } -void cmd_variable_add(char *variable, char *value) +static cmd_variable_t *cmd_variable_add_prepare(char *variable, char *value) { - cmd_variable_t *variable_ptr; - if (variable == NULL || strlen(variable) == 0) { tr_warn("cmd_variable_add invalid parameters"); - return; + return NULL; } - variable_ptr = variable_find(variable); + cmd_variable_t *variable_ptr = variable_find(variable); if (variable_ptr == NULL) { if (value == NULL) { - return; // adding null variable + return NULL; // adding null variable } if (strlen(value) == 0) { - return; // no need to add new empty one + return NULL; // no need to add new empty one } variable_ptr = (cmd_variable_t *)MEM_ALLOC(sizeof(cmd_variable_t)); - ns_list_add_to_end(&cmd.variable_list, variable_ptr); + if (variable_ptr == NULL) { + tr_error("Mem alloc failed cmd_variable_add"); + return NULL; + } variable_ptr->name_ptr = (char *)MEM_ALLOC(strlen(variable) + 1); + if (variable_ptr->name_ptr == NULL) { + MEM_FREE(variable_ptr); + tr_error("Mem alloc failed cmd_variable_add name_ptr"); + return NULL; + } + + ns_list_add_to_end(&cmd.variable_list, variable_ptr); strcpy(variable_ptr->name_ptr, variable); - variable_ptr->value_ptr = NULL; + variable_ptr->value.ptr = NULL; } if (value == NULL || strlen(value) == 0) { // delete this one + tr_debug("Remove variable: %s", variable); ns_list_remove(&cmd.variable_list, variable_ptr); MEM_FREE(variable_ptr->name_ptr); - MEM_FREE(variable_ptr->value_ptr); - MEM_FREE(variable_ptr); - } else { - // add new or modify - if (variable_ptr->value_ptr != NULL) { - MEM_FREE(variable_ptr->value_ptr); + if (variable_ptr->type == VALUE_TYPE_STR) { + MEM_FREE(variable_ptr->value.ptr); } - variable_ptr->value_ptr = (char *)MEM_ALLOC(strlen(value) + 1); - strcpy(variable_ptr->value_ptr, value); + MEM_FREE(variable_ptr); + return NULL; } + return variable_ptr; +} +void cmd_variable_add_int(char *variable, int value) +{ + cmd_variable_t *variable_ptr = cmd_variable_add_prepare(variable, " "); + if (variable_ptr == NULL) { + return; + } + if (variable_ptr->value.ptr != NULL && + variable_ptr->type == VALUE_TYPE_STR) { + // free memory + MEM_FREE(variable_ptr->value.ptr); + } + variable_ptr->type = VALUE_TYPE_INT; + variable_ptr->value.i = value; +} +void cmd_variable_add(char *variable, char *value) +{ + cmd_variable_t *variable_ptr = cmd_variable_add_prepare(variable, value); + if (variable_ptr == NULL) { + return; + } + int value_len = strlen(value); + replace_string(value, value_len, "\\n", "\n"); + replace_string(value, value_len, "\\r", "\r"); + + // add new or modify + int new_len = strlen(value) + 1; + int old_len = 0; + if (variable_ptr->value.ptr != NULL && + variable_ptr->type == VALUE_TYPE_STR) { + // free memory if required + old_len = strlen(variable_ptr->value.ptr) + 1; + if (old_len != new_len) { + MEM_FREE(variable_ptr->value.ptr); + } + } + if (old_len != new_len) { + variable_ptr->value.ptr = (char *)MEM_ALLOC(new_len); + if (variable_ptr->value.ptr == NULL) { + cmd_variable_add(variable, NULL); + tr_error("Mem alloc failed cmd_variable_add value_ptr"); + return; + } + } + variable_ptr->type = VALUE_TYPE_STR; + strcpy(variable_ptr->value.ptr, value); return; } @@ -1519,14 +1786,6 @@ static bool is_cmdline_commands(char *command) } return false; } -static void cmd_set_retfmt(char *fmt) -{ - if (cmd.retcode_fmt) { - MEM_FREE(cmd.retcode_fmt); - } - cmd.retcode_fmt = MEM_ALLOC(strlen(fmt) + 1); - strcpy(cmd.retcode_fmt, fmt); -} /*Basic commands for cmd line * alias * echo @@ -1555,6 +1814,15 @@ int alias_command(int argc, char *argv[]) } return 0; } +int unset_command(int argc, char *argv[]) +{ + if (argc != 2) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + tr_debug("Deleting variable %s", argv[1]); + cmd_variable_add(argv[1], NULL); + return 0; +} int set_command(int argc, char *argv[]) { if (argc == 1) { @@ -1562,9 +1830,12 @@ int set_command(int argc, char *argv[]) cmd_printf("variables:\r\n"); cmd_variable_print_all(); } else if (argc == 2) { - // print alias - tr_debug("Deleting variable %s", argv[1]); - cmd_variable_add(argv[1], NULL); + char *separator_ptr = strchr(argv[1], '='); + if (!separator_ptr) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + *separator_ptr = 0; + cmd_variable_add(argv[1], separator_ptr + 1); } else { // set alias tr_debug("Setting variable %s = %s", argv[1], argv[2]); @@ -1575,12 +1846,12 @@ int set_command(int argc, char *argv[]) return 0; } if (cmd_parameter_bool(argc, argv, "--retcode", &state)) { - cmd.print_retcode = state; + cmd_variable_add(VAR_RETFMT, state ? DEFAULT_RETFMT : NULL); return 0; } char *str; if (cmd_parameter_val(argc, argv, "--retfmt", &str)) { - cmd_set_retfmt(str); + cmd_variable_add(VAR_RETFMT, str); return 0; } cmd_variable_add(argv[1], argv[2]); @@ -1601,7 +1872,7 @@ int echo_command(int argc, char *argv[]) printEcho = true; } } - if( printEcho ) { + if (printEcho) { cmd_printf("ECHO is %s\r\n", cmd.echo ? "on" : "off"); } else { for (int n = 1; n < argc; n++) { @@ -1616,8 +1887,7 @@ int echo_command(int argc, char *argv[]) int clear_command(int argc, char *argv[]) { (void)argc; - (void )argv; - + (void)argv; cmd_echo(true); cmd_init_screen(); return 0; @@ -1644,13 +1914,28 @@ int help_command(int argc, char *argv[]) } return 0; } +int true_command(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + return CMDLINE_RETCODE_SUCCESS; +} +int false_command(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + return CMDLINE_RETCODE_FAIL; +} int history_command(int argc, char *argv[]) { if (argc == 1) { - cmd_printf("History [%i/%i]:\r\n", (int)ns_list_count(&cmd.history_list), cmd.history_max_count); + int history_size = (int)ns_list_count(&cmd.history_list); + cmd_printf("History [%i/%i]:\r\n", history_size - 1, cmd.history_max_count - 1); int i = 0; ns_list_foreach_reverse(cmd_history_t, cur_ptr, &cmd.history_list) { - cmd_printf("[%i]: %s\r\n", i++, cur_ptr->command_ptr); + if (i != history_size - 1) { + cmd_printf("[%i]: %s\r\n", i++, cur_ptr->command_ptr); + } } } else if (argc == 2) { if (strcmp(argv[1], "clear") == 0) { @@ -1719,7 +2004,7 @@ bool cmd_parameter_val(int argc, char *argv[], const char *key, char **value) bool cmd_parameter_int(int argc, char *argv[], const char *key, int32_t *value) { int i = cmd_parameter_index(argc, argv, key); - char* tailptr; + char *tailptr; if (i > 0) { if (argc > (i + 1)) { *value = strtol(argv[i + 1], &tailptr, 10); @@ -1738,7 +2023,7 @@ bool cmd_parameter_int(int argc, char *argv[], const char *key, int32_t *value) bool cmd_parameter_float(int argc, char *argv[], const char *key, float *value) { int i = cmd_parameter_index(argc, argv, key); - char* tailptr; + char *tailptr; if (i > 0) { if (argc > (i + 1)) { *value = strtof(argv[i + 1], &tailptr); @@ -1758,14 +2043,14 @@ bool cmd_parameter_float(int argc, char *argv[], const char *key, float *value) static int string_to_bytes(const char *str, uint8_t *buf, int bytes) { int len = strlen(str); - if( len <= (3*bytes - 1)) { + if (len <= (3 * bytes - 1)) { int i; - for(i=0;i 0) { if (argc > (i + 1)) { - if (strchr(argv[i + 1],',') != 0) { + if (strchr(argv[i + 1], ',') != 0) { // Format seconds,tics const char splitValue[] = ", "; char *token; @@ -1803,13 +2088,13 @@ bool cmd_parameter_timestamp(int argc, char *argv[], const char *key, int64_t *v if (token) { *value |= (0xffff & strtoul(token, 0, 10)); } - } else if (strchr(argv[i + 1],':') != 0 ) { + } else if (strchr(argv[i + 1], ':') != 0) { // Format 00:00:00:00:00:00:00:00 uint8_t buf[8]; if (string_to_bytes(argv[i + 1], buf, 8) == 0) { *value = read_64_bit(buf); } else { - cmd_printf("timestamp should be 8 bytes long\r\n"); + cmd_printf("timestamp should be 8 bytes long\r\n"); } } else { // Format uint64 @@ -1827,3 +2112,53 @@ char *cmd_parameter_last(int argc, char *argv[]) } return NULL; } +/** + * find last space but ignore nulls and first spaces. + * used only internally to find out previous word + * e.g. + * const char str[] = "aaaab aa bbb\0\0"; + * const char* tmp = last_space(str+strlen(str), str); + * printf(tmp); // prints "bbb" + */ +static const char *find_last_space(const char *from, const char *to) +{ + if (from <= to) { + return 0; + } + while ((from > to) && ((*from == 0) || (*from == ' '))) { + from--; + } + while (from > to) { + if (*from == ' ') { + return from + 1; + } + from--; + } + return 0; +} +static int replace_string( + char *str, int str_len, + const char *old_str, const char *new_str) +{ + char *ptr = str; + char *end = str + str_len; + int old_len = strlen(old_str); + int new_len = strlen(new_str); + if (old_len > 0) { + tr_deep("find: '%s'\r\n", old_str); + while ((ptr = strstr(ptr, old_str)) != 0) { + if (ptr + new_len > end) { + tr_warn("Buffer was not enough for replacing\r\n"); + return 1; + } + tr_warn("old_str found\r\n"); + if (old_len != new_len) { + tr_warn("memmove\r\n"); + memmove(ptr + new_len, ptr + old_len, strlen(ptr + old_len) + 1); + } + memcpy(ptr, new_str, new_len); + ptr += new_len; + } + } + return 0; +} diff --git a/features/frameworks/mbed-coap/CHANGELOG.md b/features/frameworks/mbed-coap/CHANGELOG.md index 70c9706541..e47bf91450 100644 --- a/features/frameworks/mbed-coap/CHANGELOG.md +++ b/features/frameworks/mbed-coap/CHANGELOG.md @@ -1,5 +1,20 @@ # Change Log +## [v4.7.1](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.7.1) + +- Fix CoAP stored blockwise message release and list continue + Add re-scan routine goto if message is caused user callback + This will fix hard fault when blockwise message sending timeouts. This happens cause same list is manipulated through rx callback. + +-[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.7.0...v4.7.1) + +## [v4.7.0](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.7.0) + +- Add function that can be used to clear the received blockwise payloads for example in the case of a connection error. +- Silence compiler warning when CoAP duplicate detection is enabled. + +-[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.6.3...v4.7.0) + ## [v4.6.3](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.6.3) - Bug fix: Remove timed out blockwise message from resend queue. If blockwise message was timed out message was still kept in the resend queue which causes unnecessary reconnections on client side. diff --git a/features/frameworks/mbed-coap/mbed-coap/sn_coap_protocol.h b/features/frameworks/mbed-coap/mbed-coap/sn_coap_protocol.h index 7bc83419d2..e045c78aa7 100644 --- a/features/frameworks/mbed-coap/mbed-coap/sn_coap_protocol.h +++ b/features/frameworks/mbed-coap/mbed-coap/sn_coap_protocol.h @@ -268,6 +268,15 @@ extern int8_t sn_coap_protocol_handle_block2_response_internally(struct coap_s * */ extern void sn_coap_protocol_clear_sent_blockwise_messages(struct coap_s *handle); +/** + * \fn void sn_coap_protocol_clear_received_blockwise_messages(struct coap_s *handle) + * + * \brief This function clears all the received blockwise messages from the linked list. + * + * \param *handle Pointer to CoAP library handle + */ +extern void sn_coap_protocol_clear_received_blockwise_messages(struct coap_s *handle); + /** * \fn void sn_coap_protocol_send_rst(struct coap_s *handle, uint16_t msg_id, sn_nsdl_addr_s *addr_ptr, void *param) * diff --git a/features/frameworks/mbed-coap/module.json b/features/frameworks/mbed-coap/module.json index 97bf7341db..0e3d536135 100644 --- a/features/frameworks/mbed-coap/module.json +++ b/features/frameworks/mbed-coap/module.json @@ -1,6 +1,6 @@ { "name": "mbed-coap", - "version": "4.6.3", + "version": "4.7.1", "description": "COAP library", "keywords": [ "coap", diff --git a/features/frameworks/mbed-coap/source/include/sn_coap_protocol_internal.h b/features/frameworks/mbed-coap/source/include/sn_coap_protocol_internal.h index 90147d658b..0eff138331 100644 --- a/features/frameworks/mbed-coap/source/include/sn_coap_protocol_internal.h +++ b/features/frameworks/mbed-coap/source/include/sn_coap_protocol_internal.h @@ -81,19 +81,16 @@ struct sn_coap_hdr_; /* Init value for the maximum count of messages to be stored for duplication detection */ /* Setting of this value to 0 will disable duplication check, also reduce use of ROM memory */ - -// Keep the old flag to maintain backward compatibility -#ifndef SN_COAP_DUPLICATION_MAX_MSGS_COUNT -#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT 0 -#endif - #ifdef YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT #define SN_COAP_DUPLICATION_MAX_MSGS_COUNT YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT #elif defined MBED_CONF_MBED_CLIENT_SN_COAP_DUPLICATION_MAX_MSGS_COUNT #define SN_COAP_DUPLICATION_MAX_MSGS_COUNT MBED_CONF_MBED_CLIENT_SN_COAP_DUPLICATION_MAX_MSGS_COUNT #endif - +// Keep the old flag to maintain backward compatibility +#ifndef SN_COAP_DUPLICATION_MAX_MSGS_COUNT +#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT 0 +#endif /* Maximum allowed number of saved messages for duplicate searching */ #define SN_COAP_MAX_ALLOWED_DUPLICATION_MESSAGE_COUNT 6 diff --git a/features/frameworks/mbed-coap/source/sn_coap_protocol.c b/features/frameworks/mbed-coap/source/sn_coap_protocol.c index 377e341550..8122660f4e 100644 --- a/features/frameworks/mbed-coap/source/sn_coap_protocol.c +++ b/features/frameworks/mbed-coap/source/sn_coap_protocol.c @@ -257,6 +257,21 @@ void sn_coap_protocol_clear_sent_blockwise_messages(struct coap_s *handle) #endif } +void sn_coap_protocol_clear_received_blockwise_messages(struct coap_s *handle) +{ + (void) handle; +#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + if (handle == NULL) { + return; + } + + /* Loop all stored Blockwise messages in Linked list */ + ns_list_foreach_safe(coap_blockwise_payload_s, removed_blockwise_payload_ptr, &handle->linked_list_blockwise_received_payloads) { + sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_blockwise_payload_ptr); + } +#endif +} + int8_t sn_coap_protocol_set_duplicate_buffer_size(struct coap_s *handle, uint8_t message_count) { (void) handle; @@ -1546,9 +1561,11 @@ static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct c static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle) { /* Loop all outgoing blockwise messages */ + /* foreach_safe isn't sufficient because callback routine could remove messages. */ +rescan: ns_list_foreach_safe(coap_blockwise_msg_s, removed_blocwise_msg_ptr, &handle->linked_list_blockwise_sent_msgs) { if ((handle->system_time - removed_blocwise_msg_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) { - + bool callback_called = false; // Item must be removed from the list before calling the rx_callback function. // Callback could actually clear the list and free the item and cause a use after free when callback returns. ns_list_remove(&handle->linked_list_blockwise_sent_msgs, removed_blocwise_msg_ptr); @@ -1561,6 +1578,7 @@ static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle) removed_blocwise_msg_ptr->coap_msg_ptr->msg_id = removed_blocwise_msg_ptr->msg_id; sn_coap_protocol_delete_retransmission(handle, removed_blocwise_msg_ptr->msg_id); handle->sn_coap_rx_callback(removed_blocwise_msg_ptr->coap_msg_ptr, NULL, removed_blocwise_msg_ptr->param); + callback_called = true; } handle->sn_coap_protocol_free(removed_blocwise_msg_ptr->coap_msg_ptr->payload_ptr); @@ -1568,6 +1586,12 @@ static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle) } handle->sn_coap_protocol_free(removed_blocwise_msg_ptr); + + if (callback_called) { + /* Callback routine could have wiped the list already */ + /* Be super cautious and rescan from the start */ + goto rescan; + } } } diff --git a/features/frameworks/nanostack-libservice/mbed-client-libservice/ip6string.h b/features/frameworks/nanostack-libservice/mbed-client-libservice/ip6string.h index bf1f339c76..0f3cec5613 100644 --- a/features/frameworks/nanostack-libservice/mbed-client-libservice/ip6string.h +++ b/features/frameworks/nanostack-libservice/mbed-client-libservice/ip6string.h @@ -58,9 +58,10 @@ uint_fast8_t ip6_prefix_tos(const void *prefix, uint_fast8_t prefix_len, char *p * * \param ip6addr IPv6 address in string format. * \param len Lenght of ipv6 string, maximum of 41. - * \param dest buffer for address. MUST be 16 bytes. + * \param dest buffer for address. MUST be 16 bytes. Filled with 0 on error. + * \return boolean set to true if conversion succeed, false if it didn't */ -void stoip6(const char *ip6addr, size_t len, void *dest); +bool stoip6(const char *ip6addr, size_t len, void *dest); /** * Find out numeric IPv6 address prefix length. * @@ -69,6 +70,19 @@ void stoip6(const char *ip6addr, size_t len, void *dest); */ unsigned char sipv6_prefixlength(const char *ip6addr); +/** + * Convert numeric IPv6 address string with prefix to a binary. + * + * IPv4 tunneling addresses are not covered. + * + * \param ip6addr IPv6 address in string format. + * \param dest buffer for address. MUST be 16 bytes. + * \param prefix_len_out length of prefix, is set to -1 if no prefix given + * + * \return 0 on success, negative value otherwise. prefix_len_out contains prefix length. + */ +int stoip6_prefix(const char *ip6addr, void *dest, int_fast16_t *prefix_len_out); + #ifdef __cplusplus } #endif diff --git a/features/frameworks/nanostack-libservice/source/libip6string/stoip6.c b/features/frameworks/nanostack-libservice/source/libip6string/stoip6.c index 8e6f705a54..4b0a4a81d1 100644 --- a/features/frameworks/nanostack-libservice/source/libip6string/stoip6.c +++ b/features/frameworks/nanostack-libservice/source/libip6string/stoip6.c @@ -20,6 +20,7 @@ #include "ip6string.h" static uint16_t hex(const char *p); +static bool is_hex(char c); /** * Convert numeric IPv6 address string to a binary. @@ -27,8 +28,9 @@ static uint16_t hex(const char *p); * \param ip6addr IPv6 address in string format. * \param len Length of ipv6 string. * \param dest buffer for address. MUST be 16 bytes. + * \return boolean set to true if conversion succeed, false if it didn't */ -void stoip6(const char *ip6addr, size_t len, void *dest) +bool stoip6(const char *ip6addr, size_t len, void *dest) { uint8_t *addr; const char *p, *q; @@ -37,23 +39,45 @@ void stoip6(const char *ip6addr, size_t len, void *dest) addr = dest; if (len > 39) { // Too long, not possible. We do not support IPv4-mapped IPv6 addresses - return; + goto error; } // First go forward the string, until end, noting :: position if any - for (field_no = 0, p = ip6addr; (len > (size_t)(p - ip6addr)) && *p && field_no < 8; p = q + 1) { - q = p; - // Seek for ':' or end - while (*q && (*q != ':')) { - q++; + // We're decrementing `len` as we go forward, and stop when it reaches 0 + for (field_no = 0, p = ip6addr; len && *p; p = q + 1) { + + for (q = p; len && *q && (*q != ':'); len -= 1) { // Seek for ':' or end + if (!is_hex(*q++)) { // There must only be hex characters besides ':' + goto error; + } } - //Convert and write this part, (high-endian AKA network byte order) + + if ((q - p) > 4) { // We can't have more than 4 hex digits per segment + goto error; + } + + if (field_no == 8) { // If the address goes farther than 8 segments + goto error; + } + + // Convert and write this part, (high-endian AKA network byte order) addr = common_write_16_bit(hex(p), addr); field_no++; - //Check if we reached "::" - if ((len > (size_t)(q - ip6addr)) && *q && (q[0] == ':') && (q[1] == ':')) { - coloncolon = field_no; - q++; + + // We handle the colons + if (len) { + // Check if we reached "::" + if (q[0] == ':' && q[1] == ':') { + if (coloncolon != -1) { // We are not supposed to see "::" more than once per address + goto error; + } + coloncolon = field_no; + q++; + len -= 2; + } + else { + len -= 1; + } } } @@ -65,12 +89,19 @@ void stoip6(const char *ip6addr, size_t len, void *dest) addr = dest; memmove(addr + head_size + inserted_size, addr + head_size, tail_size); memset(addr + head_size, 0, inserted_size); - } else if (field_no != 8) { - /* Should really report an error if we didn't get 8 fields */ - memset(addr, 0, 16 - field_no * 2); + } else if (field_no != 8) { // Report an error if we didn't get 8 fields + goto error; } + return true; + +error: + // Fill the output buffer with 0 so we stick to the old failure behavior. + // We are however more agressive and wipe the entire address, and do so more often. + memset(dest, 0, 16); + return false; } -unsigned char sipv6_prefixlength(const char *ip6addr) + +unsigned char sipv6_prefixlength(const char *ip6addr) { char *ptr = strchr(ip6addr, '/'); if (ptr) { @@ -78,6 +109,56 @@ unsigned char sipv6_prefixlength(const char *ip6addr) } return 0; } + +int stoip6_prefix(const char *ip6addr, void *dest, int_fast16_t *prefix_len_out) +{ + size_t addr_len, total_len; + int_fast16_t prefix_length; + + if (prefix_len_out) { + *prefix_len_out = -1; + } + + total_len = addr_len = strlen(ip6addr); + const char *ptr = strchr(ip6addr, '/'); + if (ptr) { + addr_len = ptr - ip6addr; + if (prefix_len_out) { + if (total_len - addr_len > 3) { + /* too many digits in prefix */ + return -1; + } + + prefix_length = strtoul(ptr + 1, 0, 10); + if (prefix_length < 0 || prefix_length > 128) { + /* prefix value illegal */ + return -1; + } + + *prefix_len_out = prefix_length; + } + } + + if (!stoip6(ip6addr, addr_len, dest)) { + /* parser failure */ + return -1; + } + + return 0; +} + +static bool is_hex(char c) +{ + // 'A' (0x41) and 'a' (0x61) are mapped in the ASCII table in such a way that masking the 0x20 bit turn 'a' in 'A' + if ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'F') + return true; + + if (c >= '0' && c <= '9') + return true; + + return false; +} + static uint16_t hex(const char *p) { uint16_t val = 0; diff --git a/features/frameworks/nanostack-libservice/test/libService/unittest/stoip6/main.cpp b/features/frameworks/nanostack-libservice/test/libService/unittest/stoip6/main.cpp index 6b3cf41d1a..bfd7ec69c5 100644 --- a/features/frameworks/nanostack-libservice/test/libService/unittest/stoip6/main.cpp +++ b/features/frameworks/nanostack-libservice/test/libService/unittest/stoip6/main.cpp @@ -25,3 +25,4 @@ int main(int ac, char **av) IMPORT_TEST_GROUP(stoip6); IMPORT_TEST_GROUP(stoip6_2); +IMPORT_TEST_GROUP(stoip6_3); diff --git a/features/frameworks/nanostack-libservice/test/libService/unittest/stoip6/stoip6test.cpp b/features/frameworks/nanostack-libservice/test/libService/unittest/stoip6/stoip6test.cpp index b9f7a5ed87..431a0922dc 100644 --- a/features/frameworks/nanostack-libservice/test/libService/unittest/stoip6/stoip6test.cpp +++ b/features/frameworks/nanostack-libservice/test/libService/unittest/stoip6/stoip6test.cpp @@ -42,11 +42,10 @@ TEST(stoip6, TooShort) { char *addr = "FFFF:FFFF:"; uint8_t ip[16]; - uint8_t correct[16] = {0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - // This should sto parsing when too short address given, the buffer hoewever is filled to that long - // So basically there is no error handling. We just check that first FFFF:FFFF gets filled and not trash after that. - // Rest should be filled with zeroes - stoip6(addr, strlen(addr), ip); + uint8_t correct[16] = {0}; + // This should stop parsing when too short address given. + // Despite partial parsing, the entire buffer should be filled with zeroes + CHECK(false == stoip6(addr, strlen(addr), ip)); CHECK(0 == memcmp(ip, correct, 16)); } @@ -58,7 +57,7 @@ TEST(stoip6, TooLongString) uint8_t correct[16] = {0}; // This should not fill anything, too long string. // This is basically only validation we do - stoip6(addr, strlen(addr), ip); + CHECK(false == stoip6(addr, strlen(addr), ip)); CHECK(0 == memcmp(ip, correct, 16)); } @@ -66,12 +65,11 @@ TEST(stoip6, TooManyFields) { // String len must be less than 40 char *addr = "FF:FF:FF:FF:FF:FF:FFFF:FFFF:FFFF:FFFF:"; - uint8_t ip[17] = {0}; - uint8_t correct[17] = { 0, 0xff, 0, 0xff, 0, 0xff, 0, 0xff, 0, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0}; - // Again.. there is not really any error handling (no return value) - // Just make sure that it does not overflow - stoip6(addr, strlen(addr), ip); - CHECK(0 == memcmp(ip, correct, 17)); // Note, we are checking 17, to make sure one byte after address in not touched. + uint8_t ip[16] = {0}; + uint8_t correct[16] = {0}; + + CHECK(false == stoip6(addr, strlen(addr), ip)); + CHECK(0 == memcmp(ip, correct, 16)); } TEST(stoip6, Prefixlen) @@ -96,13 +94,31 @@ TEST(stoip6, RegressionTestForOffByOne) 0x64, 0x3f, 0xf5, 0x4a, 0xec, 0x29, 0xcd, 0xbb }; - stoip6(sourceTemp, sourceTempLen, ip); - + CHECK(true == stoip6(sourceTemp, sourceTempLen, ip)); CHECK(0 == memcmp(ip, correct, 16)); free(sourceTemp); } +// Test various illegal formats to ensure proper rejection +TEST(stoip6, InvalidAddresses) +{ + uint8_t ip[16]; + uint8_t correct[16] = {0}; + + const char *invalidArray[] = + { + "FFFF:FFFF::FFFF::FFFF", // Two :: + "F:F:F:FqF:F:F:F:F", // Non-hex character + "F:F:F:FFFFF:F:F:F:F" // >4 hex characters in a segment + }; + + for (uint8_t i = 0; i < 3; ++i) { + CHECK(false == stoip6(invalidArray[i], strlen(invalidArray[i]), ip)); + CHECK(0 == memcmp(ip, correct, 16)); + } +} + /***********************************************************/ /* Second test group for the old tests that were once lost */ @@ -161,63 +177,122 @@ TEST_GROUP(stoip6_2) TEST(stoip6_2, test_2_1) { i = 0; - stoip6(string_addr[i], strlen(string_addr[i]), buf); + CHECK(true == stoip6(string_addr[i], strlen(string_addr[i]), buf)); CHECK(0 == memcmp(hex_addr[i], buf, strlen(buf))); } TEST(stoip6_2, test_2_2) { - stoip6(string_addr[i], strlen(string_addr[i]), buf); + CHECK(true == stoip6(string_addr[i], strlen(string_addr[i]), buf)); CHECK(0 == memcmp(hex_addr[i], buf, strlen(buf))); } TEST(stoip6_2, test_2_3) { - stoip6(string_addr[i], strlen(string_addr[i]), buf); + CHECK(true == stoip6(string_addr[i], strlen(string_addr[i]), buf)); CHECK(0 == memcmp(hex_addr[i], buf, strlen(buf))); } TEST(stoip6_2, test_2_4) { - stoip6(string_addr[i], strlen(string_addr[i]), buf); + CHECK(true == stoip6(string_addr[i], strlen(string_addr[i]), buf)); CHECK(0 == memcmp(hex_addr[i], buf, strlen(buf))); } TEST(stoip6_2, test_2_5) { - stoip6(string_addr[i], strlen(string_addr[i]), buf); + CHECK(true == stoip6(string_addr[i], strlen(string_addr[i]), buf)); CHECK(0 == memcmp(hex_addr[i], buf, strlen(buf))); } TEST(stoip6_2, test_2_6) { - stoip6(string_addr[i], strlen(string_addr[i]), buf); + CHECK(true == stoip6(string_addr[i], strlen(string_addr[i]), buf)); CHECK(0 == memcmp(hex_addr[i], buf, strlen(buf))); } TEST(stoip6_2, test_2_7) { - stoip6(string_addr[i], strlen(string_addr[i]), buf); + CHECK(true == stoip6(string_addr[i], strlen(string_addr[i]), buf)); CHECK(0 == memcmp(hex_addr[i], buf, strlen(buf))); } TEST(stoip6_2, test_2_8) { - stoip6(string_addr[i], strlen(string_addr[i]), buf); + CHECK(true == stoip6(string_addr[i], strlen(string_addr[i]), buf)); CHECK(0 == memcmp(hex_addr[i], buf, strlen(buf))); } TEST(stoip6_2, test_2_9) { - stoip6(string_addr[i], strlen(string_addr[i]), buf); + CHECK(true == stoip6(string_addr[i], strlen(string_addr[i]), buf)); CHECK(0 == memcmp(hex_addr[i], buf, strlen(buf))); } TEST(stoip6_2, test_2_10) { - stoip6(string_addr[i], strlen(string_addr[i]), buf); + CHECK(true == stoip6(string_addr[i], strlen(string_addr[i]), buf)); CHECK(0 == memcmp(hex_addr[i], buf, 16)); } TEST(stoip6_2, test_2_11) { - stoip6(string_addr[i], strlen(string_addr[i]), buf); + CHECK(true == stoip6(string_addr[i], strlen(string_addr[i]), buf)); CHECK(0 == memcmp(hex_addr[i], buf, 16)); } TEST(stoip6_2, test_2_12) { - stoip6(string_addr[i], strlen(string_addr[i]), buf); + CHECK(true == stoip6(string_addr[i], strlen(string_addr[i]), buf)); CHECK(0 == memcmp(hex_addr[i], buf, 16)); } +/***********************************************************/ +/* Third test group for stoip6_prefix */ + +const char string_prefix_addr[][40] = +{ + "2001:db8::1:0:0:1/64", // 1 + "2001::/60", // 2 + "::1/48", // 3 + "::/00", // 4 + "2002::02/99", // 5 + "2003::03/", // 6 + "2004::04", // 7 + "2005::05/2000", // 8 + "2005::05/-1", // 9 +}; + + +const uint8_t hex_prefix_addr[][16] = +{ + { 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 }, // 1 + { 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2 + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }, // 3 + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, // 4 + { 0x20, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }, // 5 + { 0x20, 0x03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 }, // 6 + { 0x20, 0x04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 }, // 7 + { 0x20, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 }, // 8 + { 0x20, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 }, // 9 +}; + +const int_fast16_t prefix_len_tbl[] = {64, 60, 48, 0, 99, 0, -1, -1, -1}; +const int prefix_status_tbl[] = {0, 0, 0, 0, 0, 0, 0, -1, -1}; + +TEST_GROUP(stoip6_3) +{ + void setup() { + } + + void teardown() { + } +}; + +TEST(stoip6_3, stoip6_prefix_test) +{ + for (int i = 0; i < 9; i++) { + uint8_t ip[16]; + int_fast16_t prefix_len; + int result; + const char *addr = &string_prefix_addr[i][0]; + + result = stoip6_prefix(addr, ip, &prefix_len); + CHECK(result == prefix_status_tbl[i]); + if (result == 0) { + CHECK(0 == memcmp(ip, &hex_prefix_addr[i][0], 16)); + CHECK(prefix_len == prefix_len_tbl[i]) + } + } +} + diff --git a/features/frameworks/nanostack-libservice/test/libService/unittest/stubs/ipv6_test_values.h b/features/frameworks/nanostack-libservice/test/libService/unittest/stubs/ipv6_test_values.h index 418c981311..e9ce71f795 100644 --- a/features/frameworks/nanostack-libservice/test/libService/unittest/stubs/ipv6_test_values.h +++ b/features/frameworks/nanostack-libservice/test/libService/unittest/stubs/ipv6_test_values.h @@ -33,6 +33,7 @@ struct ip6_addresses_and_its_binary_form_t { { "2001:db8::", { 0x20, 0x01, 0xd, 0xb8 }}, { "::aaaa:0:0:1", { 0, 0, 0, 0, 0, 0, 0, 0, 0xaa, 0xaa, 0, 0, 0, 0, 0, 1 }}, { "::1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }}, + { "fe80::1", { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}, { "::", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}, { "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, {NULL, {0}} diff --git a/features/frameworks/utest/mbed-utest-shim.cpp b/features/frameworks/utest/mbed-utest-shim.cpp index b2676ce8dc..38a912e55d 100644 --- a/features/frameworks/utest/mbed-utest-shim.cpp +++ b/features/frameworks/utest/mbed-utest-shim.cpp @@ -15,7 +15,6 @@ * limitations under the License. */ -#include "mbed.h" #include "mbed_critical.h" #include "utest/utest.h" diff --git a/features/frameworks/utest/source/utest_shim.cpp b/features/frameworks/utest/source/utest_shim.cpp index 07a1f82f80..076323e9b1 100644 --- a/features/frameworks/utest/source/utest_shim.cpp +++ b/features/frameworks/utest/source/utest_shim.cpp @@ -58,7 +58,9 @@ utest_v1_scheduler_t utest_v1_get_scheduler() #ifdef YOTTA_MBED_HAL_VERSION_STRING # include "mbed-hal/us_ticker_api.h" #else -# include "mbed.h" +#include "platform/SingletonPtr.h" +#include "Timeout.h" +using mbed::Timeout; #endif // only one callback is active at any given time diff --git a/features/frameworks/utest/source/utest_stack_trace.cpp b/features/frameworks/utest/source/utest_stack_trace.cpp index 83c206f4b8..5c7858be4b 100644 --- a/features/frameworks/utest/source/utest_stack_trace.cpp +++ b/features/frameworks/utest/source/utest_stack_trace.cpp @@ -17,7 +17,6 @@ #ifdef UTEST_STACK_TRACE #include "greentea-client/test_env.h" -#include "mbed.h" #include "utest/utest.h" #include "unity/unity.h" #include "utest/utest_stack_trace.h" diff --git a/features/frameworks/utest/utest/utest_scheduler.h b/features/frameworks/utest/utest/utest_scheduler.h index 9f81edf4e2..d92a3143c9 100644 --- a/features/frameworks/utest/utest/utest_scheduler.h +++ b/features/frameworks/utest/utest/utest_scheduler.h @@ -22,7 +22,7 @@ #ifndef UTEST_SCHEDULER_H #define UTEST_SCHEDULER_H -#include "mbed.h" +#include "hal/ticker_api.h" #include #include #include diff --git a/features/lorawan/LoRaRadio.h b/features/lorawan/LoRaRadio.h index e09560d7d9..bcb6019840 100644 --- a/features/lorawan/LoRaRadio.h +++ b/features/lorawan/LoRaRadio.h @@ -166,11 +166,11 @@ typedef struct radio_events { */ mbed::Callback rx_error; - /** - * FHSS Change Channel callback prototype. - * - * @param current_channel The index number of the current channel. - */ + /** + * FHSS Change Channel callback prototype. + * + * @param current_channel The index number of the current channel. + */ mbed::Callback fhss_change_channel; /** @@ -184,8 +184,7 @@ typedef struct radio_events { /** * Interface for the radios, contains the main functions that a radio needs, and five callback functions. */ -class LoRaRadio -{ +class LoRaRadio { public: @@ -246,7 +245,7 @@ public: * @param rx_continuous Sets the reception in continuous mode. * [false: single mode, true: continuous mode] */ - virtual void set_rx_config (radio_modems_t modem, uint32_t bandwidth, + virtual void set_rx_config(radio_modems_t modem, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint32_t bandwidth_afc, uint16_t preamble_len, uint16_t symb_timeout, bool fix_len, @@ -284,10 +283,10 @@ public: * @param timeout The transmission timeout [ms]. */ virtual void set_tx_config(radio_modems_t modem, int8_t power, uint32_t fdev, - uint32_t bandwidth, uint32_t datarate, - uint8_t coderate, uint16_t preamble_len, - bool fix_len, bool crc_on, bool freq_hop_on, - uint8_t hop_period, bool iq_inverted, uint32_t timeout) = 0; + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preamble_len, + bool fix_len, bool crc_on, bool freq_hop_on, + uint8_t hop_period, bool iq_inverted, uint32_t timeout) = 0; /** * Sends the buffer of size diff --git a/features/lorawan/LoRaWANBase.h b/features/lorawan/LoRaWANBase.h index a57a639806..b4ce27bda4 100644 --- a/features/lorawan/LoRaWANBase.h +++ b/features/lorawan/LoRaWANBase.h @@ -493,6 +493,7 @@ public: * other negative error code if request failed: * LORAWAN_STATUS_NOT_INITIALIZED if system is not initialized with initialize(), * LORAWAN_STATUS_BUSY if the send cannot be canceled + * LORAWAN_STATUS_NO_OP if the operation cannot be completed (nothing to cancel) */ virtual lorawan_status_t cancel_sending(void) = 0; }; diff --git a/features/lorawan/LoRaWANStack.cpp b/features/lorawan/LoRaWANStack.cpp index a73512ebbc..aebe46a774 100644 --- a/features/lorawan/LoRaWANStack.cpp +++ b/features/lorawan/LoRaWANStack.cpp @@ -40,7 +40,7 @@ SPDX-License-Identifier: BSD-3-Clause * Control flags for transient states */ #define IDLE_FLAG 0x00000000 -#define TX_ONGOING_FLAG 0x00000001 +#define RETRY_EXHAUSTED_FLAG 0x00000001 #define MSG_RECVD_FLAG 0x00000002 #define CONNECTED_FLAG 0x00000004 #define USING_OTAA_FLAG 0x00000008 @@ -68,6 +68,7 @@ LoRaWANStack::LoRaWANStack() _tx_metadata(), _rx_metadata(), _num_retry(1), + _qos_cnt(1), _ctrl_flags(IDLE_FLAG), _app_port(INVALID_PORT), _link_check_requested(false), @@ -272,15 +273,16 @@ lorawan_status_t LoRaWANStack::stop_sending(void) return LORAWAN_STATUS_NOT_INITIALIZED; } - if (_loramac.clear_tx_pipe() == LORAWAN_STATUS_OK) { + lorawan_status_t status = _loramac.clear_tx_pipe(); + + if (status == LORAWAN_STATUS_OK) { _ctrl_flags &= ~TX_DONE_FLAG; - _ctrl_flags &= ~TX_ONGOING_FLAG; _loramac.set_tx_ongoing(false); _device_current_state = DEVICE_STATE_IDLE; return LORAWAN_STATUS_OK; } - return LORAWAN_STATUS_BUSY; + return status; } int16_t LoRaWANStack::handle_tx(const uint8_t port, const uint8_t *data, @@ -294,11 +296,6 @@ int16_t LoRaWANStack::handle_tx(const uint8_t port, const uint8_t *data, if (!null_allowed && !data) { return LORAWAN_STATUS_PARAMETER_INVALID; } - // add a link check request with normal data, until the application - // explicitly removes it. - if (_link_check_requested) { - _loramac.setup_link_check_request(); - } if (!_lw_session.active) { return LORAWAN_STATUS_NO_ACTIVE_SESSIONS; @@ -308,6 +305,12 @@ int16_t LoRaWANStack::handle_tx(const uint8_t port, const uint8_t *data, return LORAWAN_STATUS_WOULD_BLOCK; } + // add a link check request with normal data, until the application + // explicitly removes it. + if (_link_check_requested) { + _loramac.setup_link_check_request(); + } + lorawan_status_t status; if (_loramac.nwk_joined() == false) { @@ -380,35 +383,31 @@ int16_t LoRaWANStack::handle_rx(uint8_t *data, uint16_t length, uint8_t &port, i uint16_t base_size = _rx_msg.msg.mcps_indication.buffer_size; bool read_complete = false; + if (_rx_msg.pending_size == 0) { + _rx_msg.pending_size = _rx_msg.msg.mcps_indication.buffer_size; + _rx_msg.prev_read_size = 0; + } + // check the length of received message whether we can fit into user // buffer completely or not - if (_rx_msg.msg.mcps_indication.buffer_size > length - && _rx_msg.prev_read_size == 0) { - // we can't fit into user buffer. Invoke counter measures - _rx_msg.pending_size = _rx_msg.msg.mcps_indication.buffer_size - length; + if (_rx_msg.prev_read_size == 0 && _rx_msg.msg.mcps_indication.buffer_size <= length) { + memcpy(data, base_ptr, base_size); + read_complete = true; + } else if (_rx_msg.pending_size > length) { + _rx_msg.pending_size = _rx_msg.pending_size - length; base_size = length; - _rx_msg.prev_read_size = base_size; - memcpy(data, base_ptr, base_size); - } else if (_rx_msg.prev_read_size == 0) { - _rx_msg.pending_size = 0; - _rx_msg.prev_read_size = 0; - memcpy(data, base_ptr, base_size); + memcpy(data, base_ptr + _rx_msg.prev_read_size, base_size); + _rx_msg.prev_read_size += base_size; + } else { + base_size = _rx_msg.pending_size; + memcpy(data, base_ptr + _rx_msg.prev_read_size, base_size); read_complete = true; } - // If its the pending read then we should copy only the remaining part of - // the buffer. Due to checks above, in case of a pending read, this block - // will be the only one to get invoked - if (_rx_msg.pending_size > 0 && _rx_msg.prev_read_size > 0) { - memcpy(data, base_ptr + _rx_msg.prev_read_size, base_size); - } - - // we are done handing over received buffer to user. check if there is - // anything pending. If not, memset the buffer to zero and indicate - // that no read is in progress if (read_complete) { _rx_msg.msg.mcps_indication.buffer = NULL; _rx_msg.msg.mcps_indication.buffer_size = 0; + _rx_msg.pending_size = 0; _rx_msg.receive_ready = false; } @@ -453,7 +452,8 @@ lorawan_status_t LoRaWANStack::set_device_class(const device_class_t &device_cla if (device_class == CLASS_B) { return LORAWAN_STATUS_UNSUPPORTED; } - _loramac.set_device_class(device_class, mbed::callback(this, &LoRaWANStack::handle_ack_expiry_for_class_c)); + _loramac.set_device_class(device_class, + mbed::callback(this, &LoRaWANStack::post_process_tx_no_reception)); return LORAWAN_STATUS_OK; } @@ -563,7 +563,6 @@ void LoRaWANStack::process_transmission_timeout() // this is a fatal error and should not happen tr_debug("TX Timeout"); _loramac.on_radio_tx_timeout(); - _ctrl_flags &= ~TX_ONGOING_FLAG; _ctrl_flags &= ~TX_DONE_FLAG; if (_device_current_state == DEVICE_STATE_JOINING) { mlme_confirm_handler(); @@ -577,9 +576,6 @@ void LoRaWANStack::process_transmission_timeout() void LoRaWANStack::process_transmission(void) { tr_debug("Transmission completed"); - _loramac.on_radio_tx_done(_tx_timestamp); - - make_tx_metadata_available(); if (_device_current_state == DEVICE_STATE_JOINING) { _device_current_state = DEVICE_STATE_AWAITING_JOIN_ACCEPT; @@ -587,31 +583,103 @@ void LoRaWANStack::process_transmission(void) if (_device_current_state == DEVICE_STATE_SENDING) { if (_loramac.get_mcps_confirmation()->req_type == MCPS_CONFIRMED) { - _ctrl_flags |= TX_ONGOING_FLAG; - _ctrl_flags &= ~TX_DONE_FLAG; tr_debug("Awaiting ACK"); _device_current_state = DEVICE_STATE_AWAITING_ACK; - } else if (_loramac.get_device_class() == CLASS_A) { - // Class A unconfirmed message sent, TX_DONE event will be sent to - // application when RX2 windows is elapsed, i.e., in process_reception_timeout() - _ctrl_flags &= ~TX_ONGOING_FLAG; + } + } + + _loramac.on_radio_tx_done(_tx_timestamp); +} + +void LoRaWANStack::post_process_tx_with_reception() +{ + if (_loramac.get_mcps_confirmation()->req_type == MCPS_CONFIRMED) { + // if ack was not received, we will try retransmission after + // ACK_TIMEOUT. handle_data_frame() already disables ACK_TIMEOUT timer + // if ack was received. Otherwise, following method will be called in + // LoRaMac.cpp, on_ack_timeout_timer_event(). + if (_loramac.get_mcps_indication()->is_ack_recvd) { _ctrl_flags |= TX_DONE_FLAG; - } else if (_loramac.get_device_class() == CLASS_C) { - // In Class C, reception timeout never happens, so we handle the state - // progression for TX_DONE in UNCONFIRMED case here + _ctrl_flags &= ~RETRY_EXHAUSTED_FLAG; + tr_debug("Ack=OK, NbTrials=%d", + _loramac.get_mcps_confirmation()->nb_retries); _loramac.post_process_mcps_req(); + make_tx_metadata_available(); + state_controller(DEVICE_STATE_STATUS_CHECK); + } else { + if (!_loramac.continue_sending_process() + && _loramac.get_current_slot() != RX_SLOT_WIN_1) { + tr_error("Retries exhausted for Class %s device", + _loramac.get_device_class() == CLASS_A ? "A" : "C"); + _ctrl_flags &= ~TX_DONE_FLAG; + _ctrl_flags |= RETRY_EXHAUSTED_FLAG; + state_controller(DEVICE_STATE_STATUS_CHECK); + } + } + } else { + // handle UNCONFIRMED case here, RX slots were turned off due to + // valid packet reception. + uint8_t prev_QOS_level = _loramac.get_prev_QOS_level(); + uint8_t QOS_level = _loramac.get_QOS_level(); + + // We will not apply QOS on the post-processing of the previous + // outgoing message as we would have received QOS instruction in response + // to that particular message + if (QOS_level > LORAWAN_DEFAULT_QOS && _qos_cnt < QOS_level + && (prev_QOS_level == QOS_level)) { + _ctrl_flags &= ~TX_DONE_FLAG; + const int ret = _queue->call(this, &LoRaWANStack::state_controller, + DEVICE_STATE_SCHEDULING); + MBED_ASSERT(ret != 0); + (void) ret; + _qos_cnt++; + tr_info("QOS: repeated transmission #%d queued", _qos_cnt); + } else { + _loramac.post_process_mcps_req(); + _ctrl_flags |= TX_DONE_FLAG; + make_tx_metadata_available(); state_controller(DEVICE_STATE_STATUS_CHECK); - state_machine_run_to_completion(); } } } -void LoRaWANStack::handle_ack_expiry_for_class_c(void) +void LoRaWANStack::post_process_tx_no_reception() { - _ctrl_flags &= ~TX_DONE_FLAG; - _ctrl_flags |= TX_ONGOING_FLAG; - tr_error("Retries exhausted for Class C device"); + if (_loramac.get_mcps_confirmation()->req_type == MCPS_CONFIRMED) { + if (_loramac.continue_sending_process()) { + _ctrl_flags &= ~TX_DONE_FLAG; + _ctrl_flags &= ~RETRY_EXHAUSTED_FLAG; + return; + } + + tr_error("Retries exhausted for Class %s device", + _loramac.get_device_class() == CLASS_A ? "A" : "C"); + _ctrl_flags &= ~TX_DONE_FLAG; + _ctrl_flags |= RETRY_EXHAUSTED_FLAG; + } else { + _ctrl_flags |= TX_DONE_FLAG; + + uint8_t prev_QOS_level = _loramac.get_prev_QOS_level(); + uint8_t QOS_level = _loramac.get_QOS_level(); + + if (QOS_level > LORAWAN_DEFAULT_QOS && (prev_QOS_level == QOS_level)) { + if (_qos_cnt < QOS_level) { + const int ret = _queue->call(this, &LoRaWANStack::state_controller, + DEVICE_STATE_SCHEDULING); + MBED_ASSERT(ret != 0); + (void)ret; + _qos_cnt++; + tr_info("QOS: repeated transmission #%d queued", _qos_cnt); + state_machine_run_to_completion(); + return; + } + } + } + + _loramac.post_process_mcps_req(); + make_tx_metadata_available(); state_controller(DEVICE_STATE_STATUS_CHECK); + state_machine_run_to_completion(); } void LoRaWANStack::handle_scheduling_failure(void) @@ -621,16 +689,18 @@ void LoRaWANStack::handle_scheduling_failure(void) state_machine_run_to_completion(); } + void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size, int16_t rssi, int8_t snr) { _device_current_state = DEVICE_STATE_RECEIVING; + _ctrl_flags &= ~MSG_RECVD_FLAG; + _ctrl_flags &= ~TX_DONE_FLAG; + _ctrl_flags &= ~RETRY_EXHAUSTED_FLAG; _loramac.on_radio_rx_done(payload, size, rssi, snr); - make_rx_metadata_available(); - if (_loramac.get_mlme_confirmation()->pending) { _loramac.post_process_mlme_request(); mlme_confirm_handler(); @@ -646,36 +716,10 @@ void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size return; } - // if the outgoing message was of CONFIRMED type - if (_loramac.get_mcps_confirmation()->req_type == MCPS_CONFIRMED) { - // if ack was not received, we will try retransmission after - // ACK_TIMEOUT. handle_data_frame() already disables ACK_TIMEOUT timer - // if ack was received. Otherwise, following method will be called in - // LoRaMac.cpp, on_ack_timeout_timer_event(). - if (_loramac.get_mcps_indication()->is_ack_recvd) { - tr_debug("Ack=OK, NbTrials=%d", - _loramac.get_mcps_confirmation()->nb_retries); - _loramac.post_process_mcps_req(); - _ctrl_flags |= TX_DONE_FLAG; - _ctrl_flags &= ~TX_ONGOING_FLAG; - state_controller(DEVICE_STATE_STATUS_CHECK); - } else { - if (!_loramac.continue_sending_process() && - _loramac.get_current_slot() != RX_SLOT_WIN_1) { - tr_error("Retries exhausted for Class A device"); - _ctrl_flags &= ~TX_DONE_FLAG; - _ctrl_flags |= TX_ONGOING_FLAG; - state_controller(DEVICE_STATE_STATUS_CHECK); - } - } - } else if (_loramac.get_device_class() == CLASS_A) { - // handle UNCONFIRMED case here, RX slots were turned off due to - // valid packet reception. For Class C, an outgoing UNCONFIRMED message - // gets its handling in process_transmission. - _loramac.post_process_mcps_req(); - _ctrl_flags |= TX_DONE_FLAG; - state_controller(DEVICE_STATE_STATUS_CHECK); - } + make_rx_metadata_available(); + + // Post process transmission in response to the reception + post_process_tx_with_reception(); // handle any pending MCPS indication if (_loramac.get_mcps_indication()->pending) { @@ -684,15 +728,13 @@ void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size state_controller(DEVICE_STATE_STATUS_CHECK); } - // change the state only if a TX cycle completes for Class A - // For class C it's not needed as it will already be in receiving - // state, no matter if the TX cycle completed or not. - if (!(_ctrl_flags & TX_ONGOING_FLAG)) { - // we are done here, update the state + // complete the cycle only if TX_DONE_FLAG is set + if (_ctrl_flags & TX_DONE_FLAG) { state_machine_run_to_completion(); } - if (_loramac.get_mlme_indication()->pending) { + // suppress auto uplink if another auto-uplink is in AWAITING_ACK state + if (_loramac.get_mlme_indication()->pending && !_automatic_uplink_ongoing) { tr_debug("MLME Indication pending"); _loramac.post_process_mlme_ind(); tr_debug("Immediate Uplink requested"); @@ -728,18 +770,7 @@ void LoRaWANStack::process_reception_timeout(bool is_timeout) * never occurs. */ if (slot == RX_SLOT_WIN_2) { - _loramac.post_process_mcps_req(); - - if (_loramac.get_mcps_confirmation()->req_type == MCPS_CONFIRMED) { - if (_loramac.continue_sending_process()) { - return; - } else { - tr_error("Retries exhausted for Class A device"); - } - } - - state_controller(DEVICE_STATE_STATUS_CHECK); - state_machine_run_to_completion(); + post_process_tx_no_reception(); } } @@ -769,7 +800,7 @@ bool LoRaWANStack::is_port_valid(const uint8_t port, bool allow_port_0) //Application should not use reserved and illegal port numbers. if (port == 0) { return allow_port_0; - } else if (port == COMPLIANCE_TESTING_PORT){ + } else if (port == COMPLIANCE_TESTING_PORT) { #if !defined(LORAWAN_COMPLIANCE_TEST) return false; #endif @@ -912,9 +943,9 @@ void LoRaWANStack::mlme_confirm_handler() if (_callbacks.link_check_resp) { const int ret = _queue->call( - _callbacks.link_check_resp, - _loramac.get_mlme_confirmation()->demod_margin, - _loramac.get_mlme_confirmation()->nb_gateways); + _callbacks.link_check_resp, + _loramac.get_mlme_confirmation()->demod_margin, + _loramac.get_mlme_confirmation()->nb_gateways); MBED_ASSERT(ret != 0); (void) ret; } @@ -1026,13 +1057,17 @@ void LoRaWANStack::mcps_indication_handler() if ((_loramac.get_device_class() != CLASS_C && mcps_indication->fpending_status) || (_loramac.get_device_class() == CLASS_C - && mcps_indication->type == MCPS_CONFIRMED)) { + && mcps_indication->type == MCPS_CONFIRMED)) { #if (MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE) - tr_debug("Sending empty uplink message..."); - _automatic_uplink_ongoing = true; - const int ret = _queue->call(this, &LoRaWANStack::send_automatic_uplink_message, mcps_indication->port); - MBED_ASSERT(ret != 0); - (void)ret; + // Do not queue an automatic uplink of there is one already outgoing + // This means we have not received an ack for the previous automatic uplink + if (!_automatic_uplink_ongoing) { + tr_debug("Sending empty uplink message..."); + _automatic_uplink_ongoing = true; + const int ret = _queue->call(this, &LoRaWANStack::send_automatic_uplink_message, mcps_indication->port); + MBED_ASSERT(ret != 0); + (void)ret; + } #else send_event_to_application(UPLINK_REQUIRED); #endif @@ -1067,9 +1102,9 @@ lorawan_status_t LoRaWANStack::state_controller(device_states_t new_state) process_shutdown_state(status); break; default: - tr_debug("state_controller: Unknown state!"); - status = LORAWAN_STATUS_SERVICE_UNKNOWN; - break; + //Because this is internal function only coding error causes this + tr_error("Unknown state: %d:", new_state); + MBED_ASSERT(false); } return status; @@ -1086,8 +1121,7 @@ void LoRaWANStack::process_shutdown_state(lorawan_status_t &op_status) _lw_session.active = false; _device_current_state = DEVICE_STATE_SHUTDOWN; op_status = LORAWAN_STATUS_DEVICE_OFF; - _ctrl_flags &= ~CONNECTED_FLAG; - _ctrl_flags &= ~CONN_IN_PROGRESS_FLAG; + _ctrl_flags = 0; send_event_to_application(DISCONNECTED); } @@ -1103,20 +1137,15 @@ void LoRaWANStack::process_status_check_state() // Another possibility is the case when the stack fails to schedule a // deferred transmission and a scheduling failure handler is invoked. _ctrl_flags &= ~TX_DONE_FLAG; - _ctrl_flags &= ~TX_ONGOING_FLAG; _loramac.set_tx_ongoing(false); _loramac.reset_ongoing_tx(); mcps_confirm_handler(); } else if (_device_current_state == DEVICE_STATE_RECEIVING) { - if ((_ctrl_flags & TX_DONE_FLAG) || (_ctrl_flags & TX_ONGOING_FLAG)) { - // for CONFIRMED case, ack validity is already checked - // If it was a successful transmission, TX_ONGOING_FLAG will not be set. - // If it was indeed set, that means the device was in Class C mode and - // CONFIRMED transmission was in place and the ack retries maxed out. + if ((_ctrl_flags & TX_DONE_FLAG) || (_ctrl_flags & RETRY_EXHAUSTED_FLAG)) { _ctrl_flags &= ~TX_DONE_FLAG; - _ctrl_flags &= ~TX_ONGOING_FLAG; + _ctrl_flags &= ~RETRY_EXHAUSTED_FLAG; _loramac.set_tx_ongoing(false); _loramac.reset_ongoing_tx(); // if an automatic uplink is ongoing, we should not send a TX_DONE @@ -1148,7 +1177,6 @@ void LoRaWANStack::process_scheduling_state(lorawan_status_t &op_status) op_status = _loramac.send_ongoing_tx(); if (op_status == LORAWAN_STATUS_OK) { - _ctrl_flags |= TX_ONGOING_FLAG; _ctrl_flags &= ~TX_DONE_FLAG; _loramac.set_tx_ongoing(true); _device_current_state = DEVICE_STATE_SENDING; @@ -1165,7 +1193,7 @@ void LoRaWANStack::process_joining_state(lorawan_status_t &op_status) } if (_device_current_state == DEVICE_STATE_AWAITING_JOIN_ACCEPT && - _loramac.get_current_slot() != RX_SLOT_WIN_1) { + _loramac.get_current_slot() != RX_SLOT_WIN_1) { _device_current_state = DEVICE_STATE_JOINING; // retry join bool can_continue = _loramac.continue_joining_process(); diff --git a/features/lorawan/LoRaWANStack.h b/features/lorawan/LoRaWANStack.h index d417108b88..6c5ecafd74 100644 --- a/features/lorawan/LoRaWANStack.h +++ b/features/lorawan/LoRaWANStack.h @@ -483,9 +483,11 @@ private: void make_tx_metadata_available(void); void make_rx_metadata_available(void); - void handle_ack_expiry_for_class_c(void); void handle_scheduling_failure(void); + void post_process_tx_with_reception(void); + void post_process_tx_no_reception(void); + private: LoRaMac _loramac; radio_events_t radio_events; @@ -497,6 +499,7 @@ private: lorawan_tx_metadata _tx_metadata; lorawan_rx_metadata _rx_metadata; uint8_t _num_retry; + uint8_t _qos_cnt; uint32_t _ctrl_flags; uint8_t _app_port; bool _link_check_requested; diff --git a/features/lorawan/lorastack/mac/LoRaMac.cpp b/features/lorawan/lorastack/mac/LoRaMac.cpp index b6a9ff238f..f5e602df56 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.cpp +++ b/features/lorawan/lorastack/mac/LoRaMac.cpp @@ -77,9 +77,12 @@ LoRaMac::LoRaMac() _mlme_indication(), _mlme_confirmation(), _is_nwk_joined(false), + _can_cancel_tx(true), _continuous_rx2_window_open(false), - _device_class(CLASS_A) + _device_class(CLASS_A), + _prev_qos_level(LORAWAN_DEFAULT_QOS) { + memset(&_params, 0, sizeof(_params)); _params.keys.dev_eui = NULL; _params.keys.app_eui = NULL; _params.keys.app_key = NULL; @@ -87,6 +90,7 @@ LoRaMac::LoRaMac() memset(_params.keys.nwk_skey, 0, sizeof(_params.keys.nwk_skey)); memset(_params.keys.app_skey, 0, sizeof(_params.keys.app_skey)); memset(&_ongoing_tx_msg, 0, sizeof(_ongoing_tx_msg)); + memset(&_params.sys_params, 0, sizeof(_params.sys_params)); _params.dev_nonce = 0; _params.net_id = 0; @@ -109,6 +113,7 @@ LoRaMac::LoRaMac() _params.multicast_channels = NULL; + _params.sys_params.adr_on = false; _params.sys_params.max_duty_cycle = 0; @@ -173,6 +178,9 @@ void LoRaMac::post_process_mcps_req() if (_params.is_ul_frame_counter_fixed == false) { _params.ul_frame_counter++; _params.adr_ack_counter++; + if (_params.sys_params.nb_trans > 1) { + _mcps_confirmation.nb_retries = _params.ul_nb_rep_counter; + } } } } @@ -281,7 +289,7 @@ void LoRaMac::handle_join_accept_frame(const uint8_t *payload, uint16_t size) void LoRaMac::check_frame_size(uint16_t size) { uint8_t value = _lora_phy->get_max_payload(_mcps_indication.rx_datarate, - _params.is_repeater_supported); + _params.is_repeater_supported); if (MAX(0, (int16_t)((int16_t)size - (int16_t)LORA_MAC_FRMPAYLOAD_OVERHEAD)) > (int32_t) value) { @@ -311,7 +319,7 @@ bool LoRaMac::message_integrity_check(const uint8_t *const payload, mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 2] << 16); mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 3] << 24); - sequence_counter_prev = (uint16_t)*downlink_counter; + sequence_counter_prev = (uint16_t) * downlink_counter; sequence_counter_diff = sequence_counter - sequence_counter_prev; *downlink_counter += sequence_counter_diff; if (sequence_counter < sequence_counter_prev) { @@ -514,10 +522,6 @@ void LoRaMac::handle_data_frame(const uint8_t *const payload, return; } - // message is intended for us and MIC have passed, stop RX2 Window - // Spec: 3.3.4 Receiver Activity during the receive windows - _lora_time.stop(_params.timers.rx_window2_timer); - _mcps_confirmation.ack_received = false; _mcps_indication.is_ack_recvd = false; _mcps_indication.pending = true; @@ -567,6 +571,8 @@ void LoRaMac::handle_data_frame(const uint8_t *const payload, tr_debug("Discarding duplicate frame"); _mcps_indication.pending = false; _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED; + + return; } } else if (msg_type == FRAME_TYPE_DATA_UNCONFIRMED_DOWN) { _params.is_srv_ack_requested = false; @@ -584,6 +590,19 @@ void LoRaMac::handle_data_frame(const uint8_t *const payload, _params.dl_frame_counter = downlink_counter; } + // message is intended for us and MIC have passed, stop RX2 Window + // Spec: 3.3.4 Receiver Activity during the receive windows + if (get_current_slot() == RX_SLOT_WIN_1) { + _lora_time.stop(_params.timers.rx_window2_timer); + } else { + _lora_time.stop(_params.timers.rx_window1_timer); + _lora_time.stop(_params.timers.rx_window2_timer); + } + + if (_device_class == CLASS_C) { + _lora_time.stop(_rx2_closure_timer_for_class_c); + } + if (_params.is_node_ack_requested && fctrl.bits.ack) { _mcps_confirmation.ack_received = fctrl.bits.ack; _mcps_indication.is_ack_recvd = fctrl.bits.ack; @@ -629,17 +648,32 @@ void LoRaMac::on_radio_tx_done(lorawan_time_t timestamp) _lora_phy->put_radio_to_sleep(); } + if ((_mcps_confirmation.req_type == MCPS_UNCONFIRMED) + && (_params.sys_params.nb_trans > 1)) { + _params.ul_nb_rep_counter++; + MBED_ASSERT(_params.ul_nb_rep_counter <= _params.sys_params.nb_trans); + } + if (_params.is_rx_window_enabled == true) { lorawan_time_t time_diff = _lora_time.get_current_time() - timestamp; // start timer after which rx1_window will get opened _lora_time.start(_params.timers.rx_window1_timer, _params.rx_window1_delay - time_diff); - if (_device_class != CLASS_C) { - _lora_time.start(_params.timers.rx_window2_timer, - _params.rx_window2_delay - time_diff); + // start timer after which rx2_window will get opened + _lora_time.start(_params.timers.rx_window2_timer, + _params.rx_window2_delay - time_diff); + + // If class C and an Unconfirmed messgae is outgoing, + // this will start a timer which will invoke rx2 would be + // closure handler + if (get_device_class() == CLASS_C) { + _lora_time.start(_rx2_closure_timer_for_class_c, + (_params.rx_window2_delay - time_diff) + + _params.rx_window2_config.window_timeout); } + // start timer after which ack wait will timeout (for Confirmed messages) if (_params.is_node_ack_requested) { _lora_time.start(_params.timers.ack_timeout_timer, (_params.rx_window2_delay - time_diff) + @@ -663,8 +697,9 @@ void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size, int16_t rssi, int8_t snr) { if (_device_class == CLASS_C && !_continuous_rx2_window_open) { + _lora_time.stop(_rx2_closure_timer_for_class_c); open_rx2_window(); - } else if (_device_class != CLASS_C){ + } else if (_device_class != CLASS_C) { _lora_time.stop(_params.timers.rx_window1_timer); _lora_phy->put_radio_to_sleep(); } @@ -704,6 +739,7 @@ void LoRaMac::on_radio_tx_timeout(void) { _lora_time.stop(_params.timers.rx_window1_timer); _lora_time.stop(_params.timers.rx_window2_timer); + _lora_time.stop(_rx2_closure_timer_for_class_c); _lora_time.stop(_params.timers.ack_timeout_timer); if (_device_class == CLASS_C) { @@ -717,16 +753,19 @@ void LoRaMac::on_radio_tx_timeout(void) _mac_commands.clear_command_buffer(); - _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter; + if (_mcps_confirmation.req_type == MCPS_CONFIRMED) { + _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter; + } else { + _mcps_confirmation.nb_retries = _params.ul_nb_rep_counter; + } + _mcps_confirmation.ack_received = false; _mcps_confirmation.tx_toa = 0; } void LoRaMac::on_radio_rx_timeout(bool is_timeout) { - if (_device_class == CLASS_C && !_continuous_rx2_window_open) { - open_rx2_window(); - } else { + if (_device_class == CLASS_A) { _lora_phy->put_radio_to_sleep(); } @@ -868,7 +907,7 @@ void LoRaMac::open_rx1_window(void) _lora_phy->rx_config(&_params.rx_window1_config); _lora_phy->handle_receive(); - tr_debug("Opening RX1 Window"); + tr_debug("RX1 slot open, Freq = %lu", _params.rx_window1_config.frequency); } void LoRaMac::open_rx2_window() @@ -897,7 +936,7 @@ void LoRaMac::open_rx2_window() _lora_phy->handle_receive(); _params.rx_slot = _params.rx_window2_config.rx_slot; - tr_debug("Opening RX2 Window, Frequency = %lu", _params.rx_window2_config.frequency); + tr_debug("RX2 slot open, Freq = %lu", _params.rx_window2_config.frequency); } void LoRaMac::on_ack_timeout_timer_event(void) @@ -905,12 +944,6 @@ void LoRaMac::on_ack_timeout_timer_event(void) Lock lock(*this); if (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries) { - if (get_device_class() == CLASS_C) { - // no need to use EventQueue as LoRaWANStack and LoRaMac are always - // in same context - _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR; - _ack_expiry_handler_for_class_c.call(); - } return; } @@ -1030,11 +1063,16 @@ int LoRaMac::get_backoff_timer_event_id(void) lorawan_status_t LoRaMac::clear_tx_pipe(void) { + if (!_can_cancel_tx) { + return LORAWAN_STATUS_BUSY; + } + // check if the event is not already queued const int id = get_backoff_timer_event_id(); + if (id == 0) { // No queued send request - return LORAWAN_STATUS_OK; + return LORAWAN_STATUS_NO_OP; } if (_ev_queue->time_left(id) > 0) { @@ -1080,9 +1118,9 @@ lorawan_status_t LoRaMac::schedule_tx() next_channel.last_aggregate_tx_time = _params.timers.aggregated_last_tx_time; lorawan_status_t status = _lora_phy->set_next_channel(&next_channel, - &_params.channel, - &backoff_time, - &_params.timers.aggregated_timeoff); + &_params.channel, + &backoff_time, + &_params.timers.aggregated_timeoff); switch (status) { case LORAWAN_STATUS_NO_CHANNEL_FOUND: @@ -1092,6 +1130,7 @@ lorawan_status_t LoRaMac::schedule_tx() case LORAWAN_STATUS_DUTYCYCLE_RESTRICTED: if (backoff_time != 0) { tr_debug("DC enforced: Transmitting in %lu ms", backoff_time); + _can_cancel_tx = true; _lora_time.start(_params.timers.backoff_timer, backoff_time); } return LORAWAN_STATUS_OK; @@ -1100,20 +1139,20 @@ lorawan_status_t LoRaMac::schedule_tx() } uint8_t rx1_dr = _lora_phy->apply_DR_offset(_params.sys_params.channel_data_rate, - _params.sys_params.rx1_dr_offset); + _params.sys_params.rx1_dr_offset); tr_debug("TX: Channel=%d, TX DR=%d, RX1 DR=%d", _params.channel, _params.sys_params.channel_data_rate, rx1_dr); _lora_phy->compute_rx_win_params(rx1_dr, MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, - MBED_CONF_LORA_MAX_SYS_RX_ERROR, - &_params.rx_window1_config); + MBED_CONF_LORA_MAX_SYS_RX_ERROR, + &_params.rx_window1_config); _lora_phy->compute_rx_win_params(_params.sys_params.rx2_channel.datarate, - MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, - MBED_CONF_LORA_MAX_SYS_RX_ERROR, - &_params.rx_window2_config); + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, + MBED_CONF_LORA_MAX_SYS_RX_ERROR, + &_params.rx_window2_config); if (!_is_nwk_joined) { _params.rx_window1_delay = _params.sys_params.join_accept_delay1 @@ -1138,8 +1177,8 @@ lorawan_status_t LoRaMac::schedule_tx() fopts_len) == false) { tr_error("Allowed FRMPayload = %d, FRMPayload = %d, MAC commands pending = %d", _lora_phy->get_max_payload(_params.sys_params.channel_data_rate, - _params.is_repeater_supported), - _ongoing_tx_msg.f_buffer_size, fopts_len); + _params.is_repeater_supported), + _ongoing_tx_msg.f_buffer_size, fopts_len); return LORAWAN_STATUS_LENGTH_ERROR; } _params.rx_window1_delay = _params.sys_params.recv_delay1 @@ -1154,6 +1193,7 @@ lorawan_status_t LoRaMac::schedule_tx() _params.is_srv_ack_requested = false; } + _can_cancel_tx = false; return send_frame_on_channel(_params.channel); } @@ -1161,7 +1201,7 @@ void LoRaMac::calculate_backOff(uint8_t channel) { lorawan_time_t elapsed_time = _lora_time.get_elapsed_time(_params.timers.mac_init_time); _lora_phy->calculate_backoff(_is_nwk_joined, _params.is_last_tx_join_request, _params.is_dutycycle_on, - channel, elapsed_time, _params.timers.tx_toa); + channel, elapsed_time, _params.timers.tx_toa); // Update aggregated time-off. This must be an assignment and no incremental // update as we do only calculate the time-off based on the last transmission @@ -1238,6 +1278,7 @@ bool LoRaMac::tx_ongoing() void LoRaMac::set_tx_ongoing(bool ongoing) { + _can_cancel_tx = true; _ongoing_tx_msg.tx_ongoing = ongoing; } @@ -1260,7 +1301,7 @@ int16_t LoRaMac::prepare_ongoing_tx(const uint8_t port, _ongoing_tx_msg.port = port; uint8_t max_possible_size = 0; uint8_t fopts_len = _mac_commands.get_mac_cmd_length() - + _mac_commands.get_repeat_commands_length(); + + _mac_commands.get_repeat_commands_length(); // Handles unconfirmed messages if (flags & MSG_UNCONFIRMED_FLAG) { @@ -1280,7 +1321,7 @@ int16_t LoRaMac::prepare_ongoing_tx(const uint8_t port, if (flags & MSG_PROPRIETARY_FLAG) { _ongoing_tx_msg.type = MCPS_PROPRIETARY; _ongoing_tx_msg.fport = port; - _ongoing_tx_msg.nb_trials = 1; + _ongoing_tx_msg.nb_trials = _params.sys_params.nb_trans; // a proprietary frame only includes an MHDR field which contains MTYPE field. // Everything else is at the discretion of the implementer fopts_len = 0; @@ -1365,10 +1406,12 @@ device_class_t LoRaMac::get_device_class() const } void LoRaMac::set_device_class(const device_class_t &device_class, - mbed::Callbackack_expiry_handler) + mbed::Callbackrx2_would_be_closure_handler) { _device_class = device_class; - _ack_expiry_handler_for_class_c = ack_expiry_handler; + _rx2_would_be_closure_for_class_c = rx2_would_be_closure_handler; + + _lora_time.init(_rx2_closure_timer_for_class_c, _rx2_would_be_closure_for_class_c); if (CLASS_A == _device_class) { tr_debug("Changing device class to -> CLASS_A"); @@ -1377,9 +1420,9 @@ void LoRaMac::set_device_class(const device_class_t &device_class, _params.is_node_ack_requested = false; _lora_phy->put_radio_to_sleep(); _lora_phy->compute_rx_win_params(_params.sys_params.rx2_channel.datarate, - MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, - MBED_CONF_LORA_MAX_SYS_RX_ERROR, - &_params.rx_window2_config); + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, + MBED_CONF_LORA_MAX_SYS_RX_ERROR, + &_params.rx_window2_config); } if (CLASS_C == _device_class) { @@ -1564,9 +1607,9 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr, if (_params.sys_params.adr_on) { if (_lora_phy->get_next_ADR(true, - _params.sys_params.channel_data_rate, - _params.sys_params.channel_tx_power, - _params.adr_ack_counter)) { + _params.sys_params.channel_data_rate, + _params.sys_params.channel_tx_power, + _params.adr_ack_counter)) { fctrl->bits.adr_ack_req = 1; } } @@ -1653,7 +1696,7 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr, _params.tx_buffer_len += LORAMAC_MFR_LEN; } - break; + break; case FRAME_TYPE_PROPRIETARY: if ((fbuffer != NULL) && (_params.tx_buffer_len > 0)) { memcpy(_params.tx_buffer + pkt_header_len, (uint8_t *) fbuffer, @@ -1721,21 +1764,6 @@ void LoRaMac::reset_mcps_indication() _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR; } -void LoRaMac::set_tx_continuous_wave(uint8_t channel, int8_t datarate, int8_t tx_power, - float max_eirp, float antenna_gain, uint16_t timeout) -{ - cw_mode_params_t continuous_wave; - - continuous_wave.channel = channel; - continuous_wave.datarate = datarate; - continuous_wave.tx_power = tx_power; - continuous_wave.max_eirp = max_eirp; - continuous_wave.antenna_gain = antenna_gain; - continuous_wave.timeout = timeout; - - _lora_phy->set_tx_cont_mode(&continuous_wave); -} - lorawan_status_t LoRaMac::initialize(EventQueue *queue, mbed::Callbackscheduling_failure_handler) { @@ -1744,6 +1772,8 @@ lorawan_status_t LoRaMac::initialize(EventQueue *queue, _ev_queue = queue; _scheduling_failure_handler = scheduling_failure_handler; + _rx2_closure_timer_for_class_c.callback = NULL; + _rx2_closure_timer_for_class_c.timer_id = -1; _channel_plan.activate_channelplan_subsystem(_lora_phy); @@ -1757,7 +1787,7 @@ lorawan_status_t LoRaMac::initialize(EventQueue *queue, _params.timers.aggregated_timeoff = 0; _lora_phy->reset_to_default_values(&_params, true); - _params.sys_params.retry_num = 1; + _params.sys_params.nb_trans = 1; reset_mac_parameters(); @@ -1829,7 +1859,6 @@ uint8_t LoRaMac::get_max_possible_tx_size(uint8_t fopts_len) max_possible_payload_size = allowed_frm_payload_size - fopts_len; } else { max_possible_payload_size = allowed_frm_payload_size; - fopts_len = 0; _mac_commands.clear_command_buffer(); _mac_commands.clear_repeat_buffer(); } @@ -1937,3 +1966,18 @@ void LoRaMac::bind_phy(LoRaPHY &phy) { _lora_phy = &phy; } + +uint8_t LoRaMac::get_QOS_level() +{ + if (_prev_qos_level != _params.sys_params.nb_trans) { + _prev_qos_level = _params.sys_params.nb_trans; + } + + return _params.sys_params.nb_trans; +} + +uint8_t LoRaMac::get_prev_QOS_level() +{ + return _prev_qos_level; +} + diff --git a/features/lorawan/lorastack/mac/LoRaMac.h b/features/lorawan/lorastack/mac/LoRaMac.h index 8ec5a8793f..1274cabde5 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.h +++ b/features/lorawan/lorastack/mac/LoRaMac.h @@ -295,10 +295,11 @@ public: /** * @brief set_device_class Sets active device class. * @param device_class Device class to use. - * @param ack_expiry_handler callback function to inform about ack expiry + * @param rx2_would_be_closure_handler callback function to inform about + * would be closure of RX2 window */ void set_device_class(const device_class_t &device_class, - mbed::Callbackack_expiry_handler); + mbed::Callbackrx2_would_be_closure_handler); /** * @brief setup_link_check_request Adds link check request command @@ -404,6 +405,17 @@ public: */ rx_slot_t get_current_slot(void); + /** + * Indicates what level of QOS is set by network server. QOS level is set + * in response to a LinkADRReq for UNCONFIRMED messages + */ + uint8_t get_QOS_level(void); + + /** + *Indicates level of QOS used for the previous outgoing message + */ + uint8_t get_prev_QOS_level(void); + /** * These locks trample through to the upper layers and make * the stack thread safe. @@ -632,10 +644,16 @@ private: /** * Class C doesn't timeout in RX2 window as it is a continuous window. - * We use this callback to inform the LoRaWANStack controller that the - * system cannot do more retries. + * We use this callback to inform the LoRaWANStack controller that we did + * not receive a downlink in a time equal to normal Class A type RX2 + * window timeout. This marks a 'would-be' closure for RX2, actual RX2 is + * not closed. Mostly network servers will send right at the beginning of + * RX2 window if they have something to send. So if we didn't receive anything + * in the time period equal to would be RX2 delay (which is a function of + * uplink message length and data rate), we will invoke this callback to let + * the upper layer know. */ - mbed::Callback _ack_expiry_handler_for_class_c; + mbed::Callback _rx2_would_be_closure_for_class_c; /** * Transmission is async, i.e., a call to schedule_tx() may be deferred to @@ -645,6 +663,8 @@ private: */ mbed::Callback _scheduling_failure_handler; + timer_event_t _rx2_closure_timer_for_class_c; + /** * Structure to hold MCPS indication data. */ @@ -669,9 +689,13 @@ private: bool _is_nwk_joined; + bool _can_cancel_tx; + bool _continuous_rx2_window_open; device_class_t _device_class; + + uint8_t _prev_qos_level; }; #endif // MBED_LORAWAN_MAC_H__ diff --git a/features/lorawan/lorastack/mac/LoRaMacChannelPlan.cpp b/features/lorawan/lorastack/mac/LoRaMacChannelPlan.cpp index 5ad159379a..a19bdf7b59 100644 --- a/features/lorawan/lorastack/mac/LoRaMacChannelPlan.cpp +++ b/features/lorawan/lorastack/mac/LoRaMacChannelPlan.cpp @@ -38,7 +38,7 @@ void LoRaMacChannelPlan::activate_channelplan_subsystem(LoRaPHY *phy) _lora_phy = phy; } -lorawan_status_t LoRaMacChannelPlan::set_plan(const lorawan_channelplan_t& plan) +lorawan_status_t LoRaMacChannelPlan::set_plan(const lorawan_channelplan_t &plan) { lorawan_status_t status; @@ -66,8 +66,8 @@ lorawan_status_t LoRaMacChannelPlan::set_plan(const lorawan_channelplan_t& plan) return LORAWAN_STATUS_OK; } -lorawan_status_t LoRaMacChannelPlan::get_plan(lorawan_channelplan_t& plan, - const channel_params_t* channel_list) +lorawan_status_t LoRaMacChannelPlan::get_plan(lorawan_channelplan_t &plan, + const channel_params_t *channel_list) { uint8_t max_num_channels; uint16_t *channel_mask; diff --git a/features/lorawan/lorastack/mac/LoRaMacChannelPlan.h b/features/lorawan/lorastack/mac/LoRaMacChannelPlan.h index 5060ffbfc5..6fd3a44d74 100644 --- a/features/lorawan/lorastack/mac/LoRaMacChannelPlan.h +++ b/features/lorawan/lorastack/mac/LoRaMacChannelPlan.h @@ -67,7 +67,7 @@ public: * @return LORAWAN_STATUS_OK if everything goes well otherwise * a negative error code is returned. */ - lorawan_status_t set_plan(const lorawan_channelplan_t& plan); + lorawan_status_t set_plan(const lorawan_channelplan_t &plan); /** Access the active channel plan * @@ -81,7 +81,7 @@ public: * @return LORAWAN_STATUS_OK if everything goes well otherwise * a negative error code is returned. */ - lorawan_status_t get_plan(lorawan_channelplan_t& plan, const channel_params_t* channel_list); + lorawan_status_t get_plan(lorawan_channelplan_t &plan, const channel_params_t *channel_list); /** Remove the active channel plan * diff --git a/features/lorawan/lorastack/mac/LoRaMacCommand.cpp b/features/lorawan/lorastack/mac/LoRaMacCommand.cpp index 596d0b8720..b3447cde7f 100644 --- a/features/lorawan/lorastack/mac/LoRaMacCommand.cpp +++ b/features/lorawan/lorastack/mac/LoRaMacCommand.cpp @@ -33,7 +33,6 @@ SPDX-License-Identifier: BSD-3-Clause */ static const uint8_t max_eirp_table[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21, 24, 26, 27, 29, 30, 33, 36 }; - LoRaMacCommand::LoRaMacCommand() { sticky_mac_cmd = false; @@ -93,8 +92,9 @@ void LoRaMacCommand::parse_mac_commands_to_repeat() case MOTE_MAC_LINK_CHECK_REQ: { // 0 byte payload break; } - default: - break; + default: { + MBED_ASSERT(false); + } } } @@ -129,7 +129,7 @@ bool LoRaMacCommand::has_sticky_mac_cmd() const lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, uint8_t mac_index, uint8_t commands_size, uint8_t snr, - loramac_mlme_confirm_t& mlme_conf, + loramac_mlme_confirm_t &mlme_conf, lora_mac_system_params_t &mac_sys_params, LoRaPHY &lora_phy) { @@ -145,42 +145,42 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui mlme_conf.nb_gateways = payload[mac_index++]; break; case SRV_MAC_LINK_ADR_REQ: { - adr_req_params_t linkAdrReq; - int8_t linkAdrDatarate = DR_0; - int8_t linkAdrTxPower = TX_POWER_0; - uint8_t linkAdrNbRep = 0; - uint8_t linkAdrNbBytesParsed = 0; + adr_req_params_t link_adr_req; + int8_t link_adr_dr = DR_0; + int8_t link_adr_txpower = TX_POWER_0; + uint8_t link_adr_nbtrans = 0; + uint8_t link_adr_nb_bytes_pasred = 0; // Fill parameter structure - linkAdrReq.payload = &payload[mac_index - 1]; - linkAdrReq.payload_size = commands_size - (mac_index - 1); - linkAdrReq.adr_enabled = mac_sys_params.adr_on; - linkAdrReq.ul_dwell_time = mac_sys_params.uplink_dwell_time; - linkAdrReq.current_datarate = mac_sys_params.channel_data_rate; - linkAdrReq.current_tx_power = mac_sys_params.channel_tx_power; - linkAdrReq.current_nb_rep = mac_sys_params.retry_num; + link_adr_req.payload = &payload[mac_index - 1]; + link_adr_req.payload_size = commands_size - (mac_index - 1); + link_adr_req.adr_enabled = mac_sys_params.adr_on; + link_adr_req.ul_dwell_time = mac_sys_params.uplink_dwell_time; + link_adr_req.current_datarate = mac_sys_params.channel_data_rate; + link_adr_req.current_tx_power = mac_sys_params.channel_tx_power; + link_adr_req.current_nb_trans = mac_sys_params.nb_trans; // Process the ADR requests - status = lora_phy.link_ADR_request(&linkAdrReq, - &linkAdrDatarate, - &linkAdrTxPower, - &linkAdrNbRep, - &linkAdrNbBytesParsed); + status = lora_phy.link_ADR_request(&link_adr_req, + &link_adr_dr, + &link_adr_txpower, + &link_adr_nbtrans, + &link_adr_nb_bytes_pasred); if ((status & 0x07) == 0x07) { - mac_sys_params.channel_data_rate = linkAdrDatarate; - mac_sys_params.channel_tx_power = linkAdrTxPower; - mac_sys_params.retry_num = linkAdrNbRep; + mac_sys_params.channel_data_rate = link_adr_dr; + mac_sys_params.channel_tx_power = link_adr_txpower; + mac_sys_params.nb_trans = link_adr_nbtrans; } // Add the answers to the buffer - for (uint8_t i = 0; i < (linkAdrNbBytesParsed / 5); i++) { + for (uint8_t i = 0; i < (link_adr_nb_bytes_pasred / 5); i++) { ret_value = add_link_adr_ans(status); } // Update MAC index - mac_index += linkAdrNbBytesParsed - 1; + mac_index += link_adr_nb_bytes_pasred - 1; } - break; + break; case SRV_MAC_DUTY_CYCLE_REQ: mac_sys_params.max_duty_cycle = payload[mac_index++]; mac_sys_params.aggregated_duty_cycle = 1 << mac_sys_params.max_duty_cycle; @@ -190,8 +190,7 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui rx_param_setup_req_t rxParamSetupReq; rxParamSetupReq.dr_offset = (payload[mac_index] >> 4) & 0x07; - rxParamSetupReq.datarate = payload[mac_index] & 0x0F; - mac_index++; + rxParamSetupReq.datarate = payload[mac_index++] & 0x0F; rxParamSetupReq.frequency = (uint32_t) payload[mac_index++]; rxParamSetupReq.frequency |= (uint32_t) payload[mac_index++] << 8; @@ -208,7 +207,7 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui } ret_value = add_rx_param_setup_ans(status); } - break; + break; case SRV_MAC_DEV_STATUS_REQ: { uint8_t battery_level = BAT_LEVEL_NO_MEASURE; if (_battery_level_cb) { @@ -232,7 +231,7 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui ret_value = add_new_channel_ans(status); } - break; + break; case SRV_MAC_RX_TIMING_SETUP_REQ: { uint8_t delay = payload[mac_index++] & 0x0F; @@ -243,7 +242,7 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui mac_sys_params.recv_delay2 = mac_sys_params.recv_delay1 + 1000; ret_value = add_rx_timing_setup_ans(); } - break; + break; case SRV_MAC_TX_PARAM_SETUP_REQ: { uint8_t eirpDwellTime = payload[mac_index++]; uint8_t ul_dwell_time; @@ -271,7 +270,7 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui ret_value = add_tx_param_setup_ans(); } } - break; + break; case SRV_MAC_DL_CHANNEL_REQ: { uint8_t channel_id = payload[mac_index++]; uint32_t rx1_frequency; @@ -284,7 +283,7 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui ret_value = add_dl_channel_ans(status); } - break; + break; default: // Unknown command. ABORT MAC commands processing tr_error("Invalid MAC command (0x%X)!", payload[mac_index]); @@ -405,7 +404,7 @@ lorawan_status_t LoRaMacCommand::add_tx_param_setup_ans() lorawan_status_t LoRaMacCommand::add_dl_channel_ans(uint8_t status) { lorawan_status_t ret = LORAWAN_STATUS_LENGTH_ERROR; - if (cmd_buffer_remaining() > 0) { + if (cmd_buffer_remaining() > 1) { mac_cmd_buffer[mac_cmd_buf_idx++] = MOTE_MAC_DL_CHANNEL_ANS; // Status: Uplink frequency exists, Channel frequency OK mac_cmd_buffer[mac_cmd_buf_idx++] = status; diff --git a/features/lorawan/lorastack/mac/LoRaMacCommand.h b/features/lorawan/lorastack/mac/LoRaMacCommand.h index aec31566c4..ce952a4bcd 100644 --- a/features/lorawan/lorastack/mac/LoRaMacCommand.h +++ b/features/lorawan/lorastack/mac/LoRaMacCommand.h @@ -76,7 +76,7 @@ public: uint8_t *get_mac_commands_buffer(); /** - * @brief Parses the MAC commands which must be resent. + * @brief Parses the MAC commands which must be re-sent. */ void parse_mac_commands_to_repeat(); @@ -116,9 +116,9 @@ public: */ lorawan_status_t process_mac_commands(const uint8_t *payload, uint8_t mac_index, uint8_t commands_size, uint8_t snr, - loramac_mlme_confirm_t& mlme_conf, - lora_mac_system_params_t& mac_params, - LoRaPHY& lora_phy); + loramac_mlme_confirm_t &mlme_conf, + lora_mac_system_params_t &mac_params, + LoRaPHY &lora_phy); /** * @brief Adds a new LinkCheckReq MAC command to be sent. diff --git a/features/lorawan/lorastack/mac/LoRaMacCrypto.cpp b/features/lorawan/lorastack/mac/LoRaMacCrypto.cpp index f2afc8dcf5..7b66144bae 100644 --- a/features/lorawan/lorastack/mac/LoRaMacCrypto.cpp +++ b/features/lorawan/lorastack/mac/LoRaMacCrypto.cpp @@ -33,13 +33,7 @@ #if defined(MBEDTLS_CMAC_C) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_CIPHER_C) LoRaMacCrypto::LoRaMacCrypto() - : mic_block_b0(), - computed_mic(), - a_block(), - s_block() { - mic_block_b0[0] = 0x49; - a_block[0] = 0x01; } int LoRaMacCrypto::compute_mic(const uint8_t *buffer, uint16_t size, @@ -47,8 +41,12 @@ int LoRaMacCrypto::compute_mic(const uint8_t *buffer, uint16_t size, uint32_t address, uint8_t dir, uint32_t seq_counter, uint32_t *mic) { + uint8_t computed_mic[16] = {}; + uint8_t mic_block_b0[16] = {}; int ret = 0; + mic_block_b0[0] = 0x49; + mic_block_b0[5] = dir; mic_block_b0[6] = (address) & 0xFF; @@ -65,37 +63,43 @@ int LoRaMacCrypto::compute_mic(const uint8_t *buffer, uint16_t size, mbedtls_cipher_init(aes_cmac_ctx); - const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); + const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); if (NULL != cipher_info) { ret = mbedtls_cipher_setup(aes_cmac_ctx, cipher_info); - if (0 != ret) + if (0 != ret) { goto exit; + } ret = mbedtls_cipher_cmac_starts(aes_cmac_ctx, key, key_length); - if (0 != ret) + if (0 != ret) { goto exit; + } ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, mic_block_b0, sizeof(mic_block_b0)); - if (0 != ret) + if (0 != ret) { goto exit; + } ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, buffer, size & 0xFF); - if (0 != ret) + if (0 != ret) { goto exit; + } ret = mbedtls_cipher_cmac_finish(aes_cmac_ctx, computed_mic); - if (0 != ret) + if (0 != ret) { goto exit; + } - *mic = (uint32_t) ((uint32_t) computed_mic[3] << 24 - | (uint32_t) computed_mic[2] << 16 - | (uint32_t) computed_mic[1] << 8 | (uint32_t) computed_mic[0]); + *mic = (uint32_t)((uint32_t) computed_mic[3] << 24 + | (uint32_t) computed_mic[2] << 16 + | (uint32_t) computed_mic[1] << 8 | (uint32_t) computed_mic[0]); } else { ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED; } -exit: mbedtls_cipher_free(aes_cmac_ctx); +exit: + mbedtls_cipher_free(aes_cmac_ctx); return ret; } @@ -108,12 +112,16 @@ int LoRaMacCrypto::encrypt_payload(const uint8_t *buffer, uint16_t size, uint8_t bufferIndex = 0; uint16_t ctr = 1; int ret = 0; + uint8_t a_block[16] = {}; + uint8_t s_block[16] = {}; mbedtls_aes_init(&aes_ctx); ret = mbedtls_aes_setkey_enc(&aes_ctx, key, key_length); - if (0 != ret) + if (0 != ret) { goto exit; + } + a_block[0] = 0x01; a_block[5] = dir; a_block[6] = (address) & 0xFF; @@ -131,8 +139,9 @@ int LoRaMacCrypto::encrypt_payload(const uint8_t *buffer, uint16_t size, ctr++; ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, a_block, s_block); - if (0 != ret) + if (0 != ret) { goto exit; + } for (i = 0; i < 16; i++) { enc_buffer[bufferIndex + i] = buffer[bufferIndex + i] ^ s_block[i]; @@ -145,15 +154,17 @@ int LoRaMacCrypto::encrypt_payload(const uint8_t *buffer, uint16_t size, a_block[15] = ((ctr) & 0xFF); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, a_block, s_block); - if (0 != ret) + if (0 != ret) { goto exit; + } for (i = 0; i < size; i++) { enc_buffer[bufferIndex + i] = buffer[bufferIndex + i] ^ s_block[i]; } } -exit: mbedtls_aes_free(&aes_ctx); +exit: + mbedtls_aes_free(&aes_ctx); return ret; } @@ -170,36 +181,42 @@ int LoRaMacCrypto::compute_join_frame_mic(const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t key_length, uint32_t *mic) { + uint8_t computed_mic[16] = {}; int ret = 0; mbedtls_cipher_init(aes_cmac_ctx); - const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); + const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); if (NULL != cipher_info) { ret = mbedtls_cipher_setup(aes_cmac_ctx, cipher_info); - if (0 != ret) + if (0 != ret) { goto exit; + } ret = mbedtls_cipher_cmac_starts(aes_cmac_ctx, key, key_length); - if (0 != ret) + if (0 != ret) { goto exit; + } ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, buffer, size & 0xFF); - if (0 != ret) + if (0 != ret) { goto exit; + } ret = mbedtls_cipher_cmac_finish(aes_cmac_ctx, computed_mic); - if (0 != ret) + if (0 != ret) { goto exit; + } - *mic = (uint32_t) ((uint32_t) computed_mic[3] << 24 - | (uint32_t) computed_mic[2] << 16 - | (uint32_t) computed_mic[1] << 8 | (uint32_t) computed_mic[0]); + *mic = (uint32_t)((uint32_t) computed_mic[3] << 24 + | (uint32_t) computed_mic[2] << 16 + | (uint32_t) computed_mic[1] << 8 | (uint32_t) computed_mic[0]); } else { ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED; } -exit: mbedtls_cipher_free(aes_cmac_ctx); +exit: + mbedtls_cipher_free(aes_cmac_ctx); return ret; } @@ -212,13 +229,15 @@ int LoRaMacCrypto::decrypt_join_frame(const uint8_t *buffer, uint16_t size, mbedtls_aes_init(&aes_ctx); ret = mbedtls_aes_setkey_enc(&aes_ctx, key, key_length); - if (0 != ret) + if (0 != ret) { goto exit; + } ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, buffer, dec_buffer); - if (0 != ret) + if (0 != ret) { goto exit; + } // Check if optional CFList is included if (size >= 16) { @@ -226,7 +245,8 @@ int LoRaMacCrypto::decrypt_join_frame(const uint8_t *buffer, uint16_t size, dec_buffer + 16); } -exit: mbedtls_aes_free(&aes_ctx); +exit: + mbedtls_aes_free(&aes_ctx); return ret; } @@ -241,16 +261,18 @@ int LoRaMacCrypto::compute_skeys_for_join_frame(const uint8_t *key, uint32_t key mbedtls_aes_init(&aes_ctx); ret = mbedtls_aes_setkey_enc(&aes_ctx, key, key_length); - if (0 != ret) + if (0 != ret) { goto exit; + } memset(nonce, 0, sizeof(nonce)); nonce[0] = 0x01; memcpy(nonce + 1, app_nonce, 6); memcpy(nonce + 7, p_dev_nonce, 2); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, nonce, nwk_skey); - if (0 != ret) + if (0 != ret) { goto exit; + } memset(nonce, 0, sizeof(nonce)); nonce[0] = 0x02; @@ -258,7 +280,8 @@ int LoRaMacCrypto::compute_skeys_for_join_frame(const uint8_t *key, uint32_t key memcpy(nonce + 7, p_dev_nonce, 2); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, nonce, app_skey); - exit: mbedtls_aes_free(&aes_ctx); +exit: + mbedtls_aes_free(&aes_ctx); return ret; } #else @@ -272,7 +295,7 @@ LoRaMacCrypto::LoRaMacCrypto() // user knows what is wrong and in addition to that these ensure that // Mbed-OS compiles properly under normal conditions where LoRaWAN in conjunction // with mbedTLS is not being used. -int LoRaMacCrypto::compute_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t, uint32_t, +int LoRaMacCrypto::compute_mic(const uint8_t *, uint16_t, const uint8_t *, uint32_t, uint32_t, uint8_t dir, uint32_t, uint32_t *) { MBED_ASSERT(0 && "[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); @@ -281,8 +304,8 @@ int LoRaMacCrypto::compute_mic(const uint8_t *, uint16_t , const uint8_t *, uint return LORAWAN_STATUS_CRYPTO_FAIL; } -int LoRaMacCrypto::encrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t, uint32_t, - uint8_t , uint32_t , uint8_t *) +int LoRaMacCrypto::encrypt_payload(const uint8_t *, uint16_t, const uint8_t *, uint32_t, uint32_t, + uint8_t, uint32_t, uint8_t *) { MBED_ASSERT(0 && "[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); @@ -290,8 +313,8 @@ int LoRaMacCrypto::encrypt_payload(const uint8_t *, uint16_t , const uint8_t *, return LORAWAN_STATUS_CRYPTO_FAIL; } -int LoRaMacCrypto::decrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t, uint32_t, - uint8_t , uint32_t , uint8_t *) +int LoRaMacCrypto::decrypt_payload(const uint8_t *, uint16_t, const uint8_t *, uint32_t, uint32_t, + uint8_t, uint32_t, uint8_t *) { MBED_ASSERT(0 && "[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); @@ -299,7 +322,7 @@ int LoRaMacCrypto::decrypt_payload(const uint8_t *, uint16_t , const uint8_t *, return LORAWAN_STATUS_CRYPTO_FAIL; } -int LoRaMacCrypto::compute_join_frame_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t, uint32_t *) +int LoRaMacCrypto::compute_join_frame_mic(const uint8_t *, uint16_t, const uint8_t *, uint32_t, uint32_t *) { MBED_ASSERT(0 && "[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); @@ -307,7 +330,7 @@ int LoRaMacCrypto::compute_join_frame_mic(const uint8_t *, uint16_t , const uint return LORAWAN_STATUS_CRYPTO_FAIL; } -int LoRaMacCrypto::decrypt_join_frame(const uint8_t *, uint16_t , const uint8_t *, uint32_t, uint8_t *) +int LoRaMacCrypto::decrypt_join_frame(const uint8_t *, uint16_t, const uint8_t *, uint32_t, uint8_t *) { MBED_ASSERT(0 && "[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); @@ -315,7 +338,7 @@ int LoRaMacCrypto::decrypt_join_frame(const uint8_t *, uint16_t , const uint8_t return LORAWAN_STATUS_CRYPTO_FAIL; } -int LoRaMacCrypto::compute_skeys_for_join_frame(const uint8_t *, uint32_t, const uint8_t *, uint16_t , +int LoRaMacCrypto::compute_skeys_for_join_frame(const uint8_t *, uint32_t, const uint8_t *, uint16_t, uint8_t *, uint8_t *) { MBED_ASSERT(0 && "[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); diff --git a/features/lorawan/lorastack/mac/LoRaMacCrypto.h b/features/lorawan/lorastack/mac/LoRaMacCrypto.h index b74729280e..845b8ee635 100644 --- a/features/lorawan/lorastack/mac/LoRaMacCrypto.h +++ b/features/lorawan/lorastack/mac/LoRaMacCrypto.h @@ -34,8 +34,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "mbedtls/cmac.h" -class LoRaMacCrypto -{ +class LoRaMacCrypto { public: /** * Constructor @@ -147,24 +146,6 @@ public: uint8_t *nwk_skey, uint8_t *app_skey); private: - /** - * MIC field computation initial data - */ - uint8_t mic_block_b0[16]; - - /** - * Contains the computed MIC field. - * - * \remark Only the 4 first bytes are used - */ - uint8_t computed_mic[16]; - - /** - * Encryption aBlock and sBlock - */ - uint8_t a_block[16]; - uint8_t s_block[16]; - /** * AES computation context variable */ diff --git a/features/lorawan/lorastack/phy/LoRaPHY.cpp b/features/lorawan/lorastack/phy/LoRaPHY.cpp index 7a8462fa8e..c995cd211b 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHY.cpp @@ -36,7 +36,8 @@ SPDX-License-Identifier: BSD-3-Clause #define CHANNELS_IN_MASK 16 LoRaPHY::LoRaPHY() - : _radio(NULL) + : _radio(NULL), + _lora_time(NULL) { memset(&phy_params, 0, sizeof(phy_params)); } @@ -164,19 +165,18 @@ int32_t LoRaPHY::get_random(int32_t min, int32_t max) return (int32_t) rand() % (max - min + 1) + min; } -bool LoRaPHY::verify_channel_DR(uint8_t nb_channels, uint16_t *channel_mask, - int8_t dr, int8_t min_dr, int8_t max_dr, - channel_params_t *channels) +bool LoRaPHY::verify_channel_DR(uint16_t *channel_mask, int8_t dr) { - if (val_in_range(dr, min_dr, max_dr) == 0) { + if (val_in_range(dr, phy_params.min_tx_datarate, + phy_params.max_tx_datarate) == 0) { return false; } for (uint8_t i = 0; i < phy_params.max_channel_cnt; i++) { if (mask_bit_test(channel_mask, i)) { // Check datarate validity for enabled channels - if (val_in_range(dr, (channels[i].dr_range.fields.min & 0x0F), - (channels[i].dr_range.fields.max & 0x0F))) { + if (val_in_range(dr, (phy_params.channels.channel_list[i].dr_range.fields.min & 0x0F), + (phy_params.channels.channel_list[i].dr_range.fields.max & 0x0F))) { // At least 1 channel has been found we can return OK. return true; } @@ -248,45 +248,6 @@ void LoRaPHY::copy_channel_mask(uint16_t *dest_mask, uint16_t *src_mask, uint8_t } } -void LoRaPHY::intersect_channel_mask(const uint16_t *source, - uint16_t *destination, uint8_t size) -{ - if (!source || !destination || size == 0) { - return; - } - - for (uint8_t i = 0; i < size; i++) { - destination[i] &= source[i]; - } -} - -void LoRaPHY::fill_channel_mask_with_fsb(const uint16_t *expectation, - const uint16_t *fsb_mask, - uint16_t *destination, - uint8_t size) -{ - if (!expectation || !fsb_mask || !destination || size == 0) { - return; - } - - for (uint8_t i = 0; i < size; i++) { - destination[i] = expectation[i] & fsb_mask[i]; - } - -} - -void LoRaPHY::fill_channel_mask_with_value(uint16_t *channel_mask, - uint16_t value, uint8_t size) -{ - if (!channel_mask || size == 0) { - return; - } - - for (uint8_t i = 0; i < size; i++) { - channel_mask[i] = value; - } -} - void LoRaPHY::set_last_tx_done(uint8_t channel, bool joined, lorawan_time_t last_tx_done_time) { band_t *band_table = (band_t *) phy_params.bands.table; @@ -396,16 +357,13 @@ uint8_t LoRaPHY::verify_link_ADR_req(verify_adr_params_t *verify_params, if (status != 0) { // Verify channel datarate - if (verify_channel_DR(phy_params.max_channel_cnt, verify_params->channel_mask, - datarate, phy_params.min_tx_datarate, - phy_params.max_tx_datarate, phy_params.channels.channel_list) - == false) { + if (verify_channel_DR(verify_params->channel_mask, datarate) == false) { status &= 0xFD; // Datarate KO } // Verify tx power if (val_in_range(tx_power, phy_params.max_tx_power, - phy_params.min_tx_power) == 0) { + phy_params.min_tx_power) == false) { // Verify if the maximum TX power is exceeded if (phy_params.max_tx_power > tx_power) { // Apply maximum TX power. Accept TX power. @@ -446,7 +404,7 @@ void LoRaPHY::get_rx_window_params(double t_symb, uint8_t min_rx_symb, { // Computed number of symbols *window_timeout = MAX((uint32_t) ceil(((2 * min_rx_symb - 8) * t_symb + 2 * rx_error) / t_symb), min_rx_symb); - *window_offset = (int32_t) ceil((4.0 * t_symb) - ((*window_timeout * t_symb) / 2.0 ) - wakeup_time); + *window_offset = (int32_t) ceil((4.0 * t_symb) - ((*window_timeout * t_symb) / 2.0) - wakeup_time); } int8_t LoRaPHY::compute_tx_power(int8_t tx_power_idx, float max_eirp, @@ -849,6 +807,11 @@ void LoRaPHY::compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols, ((uint32_t *)phy_params.bandwidths.table)[rx_conf_params->datarate]); } + if (rx_conf_params->rx_slot == RX_SLOT_WIN_1) { + rx_conf_params->frequency = phy_params.channels.channel_list[rx_conf_params->channel].frequency; + } + + get_rx_window_params(t_symbol, min_rx_symbols, rx_error, RADIO_WAKEUP_TIME, &rx_conf_params->window_timeout, &rx_conf_params->window_offset); } @@ -1031,7 +994,7 @@ uint8_t LoRaPHY::link_ADR_request(adr_req_params_t *link_adr_req, verify_params.adr_enabled = link_adr_req->adr_enabled; verify_params.current_datarate = link_adr_req->current_datarate; verify_params.current_tx_power = link_adr_req->current_tx_power; - verify_params.current_nb_rep = link_adr_req->current_nb_rep; + verify_params.current_nb_rep = link_adr_req->current_nb_trans; verify_params.datarate = adr_settings.datarate; verify_params.tx_power = adr_settings.tx_power; @@ -1140,8 +1103,8 @@ uint8_t LoRaPHY::dl_channel_request(uint8_t channel_id, uint32_t rx1_frequency) uint8_t status = 0x03; // Verify if the frequency is supported - uint8_t band = lookup_band_for_frequency(rx1_frequency); - if (verify_frequency_for_band(rx1_frequency, band) == false) { + int band = lookup_band_for_frequency(rx1_frequency); + if (band < 0) { status &= 0xFE; } @@ -1343,7 +1306,7 @@ lorawan_status_t LoRaPHY::add_channel(const channel_params_t *new_channel, // Default channels don't accept all values if (id < phy_params.default_channel_cnt) { // Validate the datarate range for min: must be DR_0 - if (new_channel->dr_range.fields.min > phy_params.min_tx_datarate) { + if (new_channel->dr_range.fields.min != DR_0) { dr_invalid = true; } @@ -1382,7 +1345,7 @@ lorawan_status_t LoRaPHY::add_channel(const channel_params_t *new_channel, return LORAWAN_STATUS_FREQUENCY_INVALID; } - memcpy(&(phy_params.channels.channel_list[id]), new_channel, sizeof(channel_params_t)); + memmove(&(phy_params.channels.channel_list[id]), new_channel, sizeof(channel_params_t)); phy_params.channels.channel_list[id].band = new_channel->band; diff --git a/features/lorawan/lorastack/phy/LoRaPHY.h b/features/lorawan/lorastack/phy/LoRaPHY.h index 5b4ed32b8b..76bad8993c 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.h +++ b/features/lorawan/lorastack/phy/LoRaPHY.h @@ -147,7 +147,7 @@ public: * * @return bit mask, according to the LoRaWAN spec 1.0.2. */ - virtual uint8_t request_new_channel(int8_t channel_id, channel_params_t* new_channel); + virtual uint8_t request_new_channel(int8_t channel_id, channel_params_t *new_channel); /** Process PHY layer state after a successful transmission. * @brief set_last_tx_done Updates times of the last transmission for the particular channel and @@ -174,7 +174,7 @@ public: * @param size Size of the payload. * */ - virtual void apply_cf_list(const uint8_t* payload, uint8_t size); + virtual void apply_cf_list(const uint8_t *payload, uint8_t size); /** Calculates the next datarate to set, when ADR is on or off. * @@ -189,8 +189,8 @@ public: * * @return True, if an ADR request should be performed. */ - bool get_next_ADR(bool restore_channel_mask, int8_t& dr_out, - int8_t& tx_power_out, uint32_t& adr_ack_counter); + bool get_next_ADR(bool restore_channel_mask, int8_t &dr_out, + int8_t &tx_power_out, uint32_t &adr_ack_counter); /** Configure radio reception. * @@ -198,7 +198,7 @@ public: * * @return True, if the configuration was applied successfully. */ - virtual bool rx_config(rx_config_params_t* config); + virtual bool rx_config(rx_config_params_t *config); /** Computing Receive Windows * @@ -268,8 +268,8 @@ public: * * @return True, if the configuration was applied successfully. */ - virtual bool tx_config(tx_config_params_t* tx_config, int8_t* tx_power, - lorawan_time_t* tx_toa); + virtual bool tx_config(tx_config_params_t *tx_config, int8_t *tx_power, + lorawan_time_t *tx_toa); /** Processes a Link ADR Request. * @@ -285,10 +285,10 @@ public: * * @return The status of the operation, according to the LoRaMAC specification. */ - virtual uint8_t link_ADR_request(adr_req_params_t* params, - int8_t* dr_out, int8_t* tx_power_out, - uint8_t* nb_rep_out, - uint8_t* nb_bytes_parsed); + virtual uint8_t link_ADR_request(adr_req_params_t *params, + int8_t *dr_out, int8_t *tx_power_out, + uint8_t *nb_rep_out, + uint8_t *nb_bytes_parsed); /** Accept or rejects RxParamSetupReq MAC command * @@ -299,7 +299,7 @@ public: * * @return The status of the operation, according to the LoRaWAN specification. */ - virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t* params); + virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t *params); /** * @brief accept_tx_param_setup_req Makes decision whether to accept or reject TxParamSetupReq MAC command. @@ -345,9 +345,9 @@ public: * * @return Function status [1: OK, 0: Unable to find a channel on the current datarate]. */ - virtual lorawan_status_t set_next_channel(channel_selection_params_t* nextChanParams, - uint8_t* channel, lorawan_time_t* time, - lorawan_time_t* aggregatedTimeOff); + virtual lorawan_status_t set_next_channel(channel_selection_params_t *nextChanParams, + uint8_t *channel, lorawan_time_t *time, + lorawan_time_t *aggregatedTimeOff); /** Adds a channel to the channel list. * @@ -361,7 +361,7 @@ public: * @return LORAWAN_STATUS_OK if everything goes fine, negative error code * otherwise. */ - virtual lorawan_status_t add_channel(const channel_params_t* new_channel, uint8_t id); + virtual lorawan_status_t add_channel(const channel_params_t *new_channel, uint8_t id); /** Removes a channel from the channel list. * @@ -377,7 +377,7 @@ public: * * @param [in] frequency Frequency to transmit at */ - virtual void set_tx_cont_mode(cw_mode_params_t* continuous_wave, + virtual void set_tx_cont_mode(cw_mode_params_t *continuous_wave, uint32_t frequency = 0); /** Computes new data rate according to the given offset @@ -474,7 +474,7 @@ public: * @param get_default If true the default mask is returned, otherwise the current mask is returned * @return A channel mask */ - uint16_t* get_channel_mask(bool get_default = false); + uint16_t *get_channel_mask(bool get_default = false); /** * @brief get_max_nb_channels Gets maximum number of channels supported @@ -486,7 +486,7 @@ public: * @brief get_phy_channels Gets PHY channels * @return PHY channels */ - channel_params_t* get_phy_channels(); + channel_params_t *get_phy_channels(); /** * @brief is_custom_channel_plan_supported Checks if custom channel plan is supported @@ -535,26 +535,6 @@ public: //Verifiers protected: LoRaPHY(); - /** - * Sets the intersection of source and destination channel masks - * into the destination. - */ - void intersect_channel_mask(const uint16_t *source, uint16_t *destination, - uint8_t size); - - /** - * Fills channel mask array based upon the provided FSB mask - */ - void fill_channel_mask_with_fsb(const uint16_t *expectation, - const uint16_t *fsb_mask, - uint16_t *channel_mask, uint8_t size); - - /** - * Fills channel mask array with a given value - */ - void fill_channel_mask_with_value(uint16_t *channel_mask, - uint16_t value, uint8_t size); - /** * Looks up corresponding band for a frequency. Returns -1 if not in any band. */ @@ -573,13 +553,12 @@ protected: /** * Verifies, if a datarate is available on an active channel. */ - bool verify_channel_DR(uint8_t nbChannels, uint16_t* channelsMask, int8_t dr, - int8_t minDr, int8_t maxDr, channel_params_t* channels); + bool verify_channel_DR(uint16_t *channelsMask, int8_t dr); /** * Disables a channel in a given channels mask. */ - bool disable_channel(uint16_t* channel_mask, uint8_t id, uint8_t max_channels); + bool disable_channel(uint16_t *channel_mask, uint8_t id, uint8_t max_channels); /** * Counts number of bits on in a given mask @@ -589,48 +568,38 @@ protected: /** * Counts the number of active channels in a given channels mask. */ - uint8_t num_active_channels(uint16_t* channel_mask, uint8_t start_idx, + uint8_t num_active_channels(uint16_t *channel_mask, uint8_t start_idx, uint8_t stop_idx); /** * Copy channel masks. */ - void copy_channel_mask(uint16_t* dest_mask, uint16_t* src_mask, uint8_t len); + void copy_channel_mask(uint16_t *dest_mask, uint16_t *src_mask, uint8_t len); /** * Updates the time-offs of the bands. */ - lorawan_time_t update_band_timeoff(bool joined, bool dutyCycle, band_t* bands, + lorawan_time_t update_band_timeoff(bool joined, bool dutyCycle, band_t *bands, uint8_t nb_bands); /** * Parses the parameter of an LinkAdrRequest. */ - uint8_t parse_link_ADR_req(const uint8_t* payload, link_adr_params_t* adr_params); + uint8_t parse_link_ADR_req(const uint8_t *payload, link_adr_params_t *adr_params); /** * Verifies and updates the datarate, the TX power and the number of repetitions * of a LinkAdrRequest. */ - uint8_t verify_link_ADR_req(verify_adr_params_t* verify_params, int8_t* dr, - int8_t* tx_pow, uint8_t* nb_rep); - - /** - * Computes the symbol time for LoRa modulation. - */ - double compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth ); - - /** - * Computes the symbol time for FSK modulation. - */ - double compute_symb_timeout_fsk(uint8_t phy_dr); + uint8_t verify_link_ADR_req(verify_adr_params_t *verify_params, int8_t *dr, + int8_t *tx_pow, uint8_t *nb_rep); /** * Computes the RX window timeout and the RX window offset. */ void get_rx_window_params(double t_symbol, uint8_t min_rx_symbols, uint32_t rx_error, uint32_t wakeup_time, - uint32_t* window_timeout, int32_t* window_offset); + uint32_t *window_timeout, int32_t *window_offset); /** * Computes the txPower, based on the max EIRP and the antenna gain. @@ -653,11 +622,23 @@ protected: uint8_t get_bandwidth(uint8_t dr_index); uint8_t enabled_channel_count(uint8_t datarate, - const uint16_t *mask, uint8_t* enabledChannels, - uint8_t* delayTx); + const uint16_t *mask, uint8_t *enabledChannels, + uint8_t *delayTx); bool is_datarate_supported(const int8_t datarate) const; +private: + + /** + * Computes the symbol time for LoRa modulation. + */ + double compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth); + + /** + * Computes the symbol time for FSK modulation. + */ + double compute_symb_timeout_fsk(uint8_t phy_dr); + protected: LoRaRadio *_radio; LoRaWANTimeHandler *_lora_time; diff --git a/features/lorawan/lorastack/phy/LoRaPHYAS923.cpp b/features/lorawan/lorastack/phy/LoRaPHYAS923.cpp index a5be66ac66..e5e37e8f84 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYAS923.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHYAS923.cpp @@ -194,13 +194,13 @@ static const band_t AS923_BAND0 = {100, AS923_MAX_TX_POWER, 0, 0, 0, 923000000, * LoRaMac default channel 1 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t AS923_LC1 = { 923200000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }; +static const channel_params_t AS923_LC1 = { 923200000, 0, { ((DR_5 << 4) | DR_0) }, 0 }; /*! * LoRaMac default channel 2 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t AS923_LC2 = { 923400000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }; +static const channel_params_t AS923_LC2 = { 923400000, 0, { ((DR_5 << 4) | DR_0) }, 0 }; /*! * LoRaMac channels which are allowed for the join procedure @@ -228,12 +228,12 @@ static const uint8_t datarates_AS923[] = {12, 11, 10, 9, 8, 7, 7, 50}; static const uint32_t bandwidths_AS923[] = {125000, 125000, 125000, 125000, 125000, 125000, 250000, 0}; #if (MBED_CONF_LORA_DWELL_TIME == 0) - static const uint8_t max_payload_table[] = {51, 51, 51, 115, 242, 242, 242, 242}; - static const uint8_t max_payload_table_with_repeater[] = {51, 51, 51, 115, 222, 222, 222, 222}; +static const uint8_t max_payload_table[] = {51, 51, 51, 115, 242, 242, 242, 242}; +static const uint8_t max_payload_table_with_repeater[] = {51, 51, 51, 115, 222, 222, 222, 222}; #else - // this is the default, i.e., - static const uint8_t max_payload_table[] = {0, 0, 11, 53, 125, 242, 242, 242}; - static const uint8_t max_payload_table_with_repeater[] = {0, 0, 11, 53, 125, 242, 242, 242}; +// this is the default, i.e., +static const uint8_t max_payload_table[] = {0, 0, 11, 53, 125, 242, 242, 242}; +static const uint8_t max_payload_table_with_repeater[] = {0, 0, 11, 53, 125, 242, 242, 242}; #endif /*! @@ -336,9 +336,9 @@ int8_t LoRaPHYAS923::get_alternate_DR(uint8_t nb_trials) return AS923_DWELL_LIMIT_DATARATE; } -lorawan_status_t LoRaPHYAS923::set_next_channel(channel_selection_params_t* next_channel_prams, - uint8_t* channel, lorawan_time_t* time, - lorawan_time_t* aggregate_timeoff) +lorawan_status_t LoRaPHYAS923::set_next_channel(channel_selection_params_t *next_channel_prams, + uint8_t *channel, lorawan_time_t *time, + lorawan_time_t *aggregate_timeoff) { uint8_t next_channel_idx = 0; uint8_t nb_enabled_channels = 0; @@ -375,7 +375,7 @@ lorawan_status_t LoRaPHYAS923::set_next_channel(channel_selection_params_t* next for (uint8_t i = 0, j = get_random(0, nb_enabled_channels - 1); i < AS923_MAX_NB_CHANNELS; i++) { next_channel_idx = enabled_channels[j]; - j = ( j + 1 ) % nb_enabled_channels; + j = (j + 1) % nb_enabled_channels; // Perform carrier sense for AS923_CARRIER_SENSE_TIME // If the channel is free, we can stop the LBT mechanism @@ -402,7 +402,7 @@ lorawan_status_t LoRaPHYAS923::set_next_channel(channel_selection_params_t* next } // Datarate not supported by any channel, restore defaults - channel_mask[0] |= LC( 1 ) + LC( 2 ); + channel_mask[0] |= LC(1) + LC(2); *time = 0; return LORAWAN_STATUS_NO_CHANNEL_FOUND; } diff --git a/features/lorawan/lorastack/phy/LoRaPHYAS923.h b/features/lorawan/lorastack/phy/LoRaPHYAS923.h index 7643dad5d9..2a9d3f89f3 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYAS923.h +++ b/features/lorawan/lorastack/phy/LoRaPHYAS923.h @@ -55,11 +55,11 @@ public: virtual int8_t get_alternate_DR(uint8_t nb_trials); - virtual lorawan_status_t set_next_channel(channel_selection_params_t* nextChanParams, - uint8_t* channel, lorawan_time_t* time, - lorawan_time_t* aggregatedTimeOff ); + virtual lorawan_status_t set_next_channel(channel_selection_params_t *nextChanParams, + uint8_t *channel, lorawan_time_t *time, + lorawan_time_t *aggregatedTimeOff); - virtual uint8_t apply_DR_offset(int8_t dr, int8_t drOffset ); + virtual uint8_t apply_DR_offset(int8_t dr, int8_t drOffset); private: channel_params_t channels[AS923_MAX_NB_CHANNELS]; diff --git a/features/lorawan/lorastack/phy/LoRaPHYAU915.cpp b/features/lorawan/lorastack/phy/LoRaPHYAU915.cpp index 357d382844..46ea344860 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYAU915.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHYAU915.cpp @@ -192,33 +192,38 @@ static const uint8_t datarates_AU915[] = {12, 11, 10, 9, 8, 7, 8, 0, 12, 11, 10, * Bandwidths table definition in Hz */ static const uint32_t bandwidths_AU915[] = { 125000, 125000, 125000, 125000, - 125000, 125000, 500000, 0, 500000, 500000, 500000, 500000, 500000, 500000, - 0, 0 }; + 125000, 125000, 500000, 0, 500000, 500000, 500000, 500000, 500000, 500000, + 0, 0 + }; /*! * Up/Down link data rates offset definition */ -static const int8_t datarate_offsets_AU915[7][6] = { { DR_8, DR_8, DR_8, DR_8, -DR_8, DR_8 }, // DR_0 +static const int8_t datarate_offsets_AU915[7][6] = { { + DR_8, DR_8, DR_8, DR_8, + DR_8, DR_8 + }, // DR_0 { DR_9, DR_8, DR_8, DR_8, DR_8, DR_8 }, // DR_1 { DR_10, DR_9, DR_8, DR_8, DR_8, DR_8 }, // DR_2 { DR_11, DR_10, DR_9, DR_8, DR_8, DR_8 }, // DR_3 { DR_12, DR_11, DR_10, DR_9, DR_8, DR_8 }, // DR_4 { DR_13, DR_12, DR_11, DR_10, DR_9, DR_8 }, // DR_5 { DR_13, DR_13, DR_12, DR_11, DR_10, DR_9 }, // DR_6 - }; +}; /*! * Maximum payload with respect to the datarate index. Cannot operate with repeater. */ static const uint8_t max_payload_AU915[] = { 51, 51, 51, 115, 242, 242, - 242, 0, 53, 129, 242, 242, 242, 242, 0, 0 }; + 242, 0, 53, 129, 242, 242, 242, 242, 0, 0 + }; /*! * Maximum payload with respect to the datarate index. Can operate with repeater. */ static const uint8_t max_payload_with_repeater_AU915[] = { 51, 51, 51, 115, - 222, 222, 222, 0, 33, 109, 222, 222, 222, 222, 0, 0 }; + 222, 222, 222, 0, 33, 109, 222, 222, 222, 222, 0, 0 + }; static const uint16_t fsb_mask[] = MBED_CONF_LORA_FSB_MASK; @@ -232,14 +237,14 @@ LoRaPHYAU915::LoRaPHYAU915() // 125 kHz channels Upstream only for (uint8_t i = 0; i < AU915_MAX_NB_CHANNELS - 8; i++) { channels[i].frequency = 915200000 + i * 200000; - channels[i].dr_range.value = ( DR_5 << 4) | DR_0; + channels[i].dr_range.value = (DR_5 << 4) | DR_0; channels[i].band = 0; } // 500 kHz channels // Upstream and downstream both for (uint8_t i = AU915_MAX_NB_CHANNELS - 8; i < AU915_MAX_NB_CHANNELS; i++) { - channels[i].frequency = 915900000 + (i - ( AU915_MAX_NB_CHANNELS - 8)) * 1600000; - channels[i].dr_range.value = ( DR_6 << 4) | DR_6; + channels[i].frequency = 915900000 + (i - (AU915_MAX_NB_CHANNELS - 8)) * 1600000; + channels[i].dr_range.value = (DR_6 << 4) | DR_6; channels[i].band = 0; } @@ -335,7 +340,7 @@ LoRaPHYAU915::~LoRaPHYAU915() { } -bool LoRaPHYAU915::rx_config(rx_config_params_t* params) +bool LoRaPHYAU915::rx_config(rx_config_params_t *params) { int8_t dr = params->datarate; uint8_t max_payload = 0; @@ -349,7 +354,7 @@ bool LoRaPHYAU915::rx_config(rx_config_params_t* params) if (params->rx_slot == RX_SLOT_WIN_1) { // Apply window 1 frequency frequency = AU915_FIRST_RX1_CHANNEL - + (params->channel % 8) * AU915_STEPWIDTH_RX1_CHANNEL; + + (params->channel % 8) * AU915_STEPWIDTH_RX1_CHANNEL; } // Read the physical datarate from the datarates table @@ -377,8 +382,8 @@ bool LoRaPHYAU915::rx_config(rx_config_params_t* params) return true; } -bool LoRaPHYAU915::tx_config(tx_config_params_t* params, int8_t* tx_power, - lorawan_time_t* tx_toa) +bool LoRaPHYAU915::tx_config(tx_config_params_t *params, int8_t *tx_power, + lorawan_time_t *tx_toa) { int8_t phy_dr = datarates_AU915[params->datarate]; @@ -414,13 +419,13 @@ bool LoRaPHYAU915::tx_config(tx_config_params_t* params, int8_t* tx_power, return true; } -uint8_t LoRaPHYAU915::link_ADR_request(adr_req_params_t* params, - int8_t* dr_out, int8_t* tx_power_out, - uint8_t* nb_rep_out, - uint8_t* nb_bytes_parsed) +uint8_t LoRaPHYAU915::link_ADR_request(adr_req_params_t *params, + int8_t *dr_out, int8_t *tx_power_out, + uint8_t *nb_rep_out, + uint8_t *nb_bytes_parsed) { uint8_t status = 0x07; - link_adr_params_t adr_settings; + link_adr_params_t adr_settings = {}; uint8_t next_index = 0; uint8_t bytes_processed = 0; uint16_t temp_channel_masks[AU915_CHANNEL_MASK_SIZE] = { 0, 0, 0, 0, 0}; @@ -479,7 +484,7 @@ uint8_t LoRaPHYAU915::link_ADR_request(adr_req_params_t* params, verify_params.nb_rep = adr_settings.nb_rep; verify_params.current_datarate = params->current_datarate; verify_params.current_tx_power = params->current_tx_power; - verify_params.current_nb_rep = params->current_nb_rep; + verify_params.current_nb_rep = params->current_nb_trans; verify_params.channel_mask = temp_channel_masks; @@ -505,7 +510,7 @@ uint8_t LoRaPHYAU915::link_ADR_request(adr_req_params_t* params, return status; } -uint8_t LoRaPHYAU915::accept_rx_param_setup_req(rx_param_setup_req_t* params) +uint8_t LoRaPHYAU915::accept_rx_param_setup_req(rx_param_setup_req_t *params) { uint8_t status = 0x07; uint32_t freq = params->frequency; @@ -517,7 +522,7 @@ uint8_t LoRaPHYAU915::accept_rx_param_setup_req(rx_param_setup_req_t* params) || (freq < AU915_FIRST_RX1_CHANNEL) || (freq > AU915_LAST_RX1_CHANNEL) || (((freq - (uint32_t) AU915_FIRST_RX1_CHANNEL) - % (uint32_t) AU915_STEPWIDTH_RX1_CHANNEL) != 0)) { + % (uint32_t) AU915_STEPWIDTH_RX1_CHANNEL) != 0)) { status &= 0xFE; // Channel frequency KO } @@ -553,9 +558,9 @@ int8_t LoRaPHYAU915::get_alternate_DR(uint8_t nb_trials) return datarate; } -lorawan_status_t LoRaPHYAU915::set_next_channel(channel_selection_params_t* next_chan_params, - uint8_t* channel, lorawan_time_t* time, - lorawan_time_t* aggregated_timeOff) +lorawan_status_t LoRaPHYAU915::set_next_channel(channel_selection_params_t *next_chan_params, + uint8_t *channel, lorawan_time_t *time, + lorawan_time_t *aggregated_timeOff) { uint8_t nb_enabled_channels = 0; uint8_t delay_tx = 0; @@ -615,10 +620,32 @@ lorawan_status_t LoRaPHYAU915::set_next_channel(channel_selection_params_t* next uint8_t LoRaPHYAU915::apply_DR_offset(int8_t dr, int8_t dr_offset) { - int8_t datarate = datarate_offsets_AU915[dr][dr_offset]; - - if (datarate < 0) { - datarate = DR_0; - } - return datarate; + return datarate_offsets_AU915[dr][dr_offset]; +} + +void LoRaPHYAU915::intersect_channel_mask(const uint16_t *source, + uint16_t *destination, uint8_t size) +{ + for (uint8_t i = 0; i < size; i++) { + destination[i] &= source[i]; + } +} + +void LoRaPHYAU915::fill_channel_mask_with_fsb(const uint16_t *expectation, + const uint16_t *fsb_mask, + uint16_t *destination, + uint8_t size) +{ + for (uint8_t i = 0; i < size; i++) { + destination[i] = expectation[i] & fsb_mask[i]; + } + +} + +void LoRaPHYAU915::fill_channel_mask_with_value(uint16_t *channel_mask, + uint16_t value, uint8_t size) +{ + for (uint8_t i = 0; i < size; i++) { + channel_mask[i] = value; + } } diff --git a/features/lorawan/lorastack/phy/LoRaPHYAU915.h b/features/lorawan/lorastack/phy/LoRaPHYAU915.h index 1db1ff227c..2fa0e453c0 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYAU915.h +++ b/features/lorawan/lorastack/phy/LoRaPHYAU915.h @@ -49,33 +49,55 @@ #define AU915_CHANNEL_MASK_SIZE 5 -class LoRaPHYAU915 : public LoRaPHY{ +class LoRaPHYAU915 : public LoRaPHY { public: LoRaPHYAU915(); virtual ~LoRaPHYAU915(); - virtual bool rx_config(rx_config_params_t* config); + virtual bool rx_config(rx_config_params_t *config); - virtual bool tx_config(tx_config_params_t* config, int8_t* txPower, - lorawan_time_t* txTimeOnAir); + virtual bool tx_config(tx_config_params_t *config, int8_t *txPower, + lorawan_time_t *txTimeOnAir); - virtual uint8_t link_ADR_request(adr_req_params_t* params, - int8_t* drOut, int8_t* txPowOut, - uint8_t* nbRepOut, - uint8_t* nbBytesParsed); + virtual uint8_t link_ADR_request(adr_req_params_t *params, + int8_t *drOut, int8_t *txPowOut, + uint8_t *nbRepOut, + uint8_t *nbBytesParsed); - virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t* params); + virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t *params); virtual int8_t get_alternate_DR(uint8_t nb_trials); - virtual lorawan_status_t set_next_channel(channel_selection_params_t* next_chan_params, - uint8_t* channel, lorawan_time_t* time, - lorawan_time_t* aggregate_timeoff); + virtual lorawan_status_t set_next_channel(channel_selection_params_t *next_chan_params, + uint8_t *channel, lorawan_time_t *time, + lorawan_time_t *aggregate_timeoff); virtual uint8_t apply_DR_offset(int8_t dr, int8_t dr_offset); +private: + + /** + * Sets the intersection of source and destination channel masks + * into the destination. + */ + void intersect_channel_mask(const uint16_t *source, uint16_t *destination, + uint8_t size); + + /** + * Fills channel mask array based upon the provided FSB mask + */ + void fill_channel_mask_with_fsb(const uint16_t *expectation, + const uint16_t *fsb_mask, + uint16_t *channel_mask, uint8_t size); + + /** + * Fills channel mask array with a given value + */ + void fill_channel_mask_with_value(uint16_t *channel_mask, + uint16_t value, uint8_t size); + private: /*! diff --git a/features/lorawan/lorastack/phy/LoRaPHYCN470.cpp b/features/lorawan/lorastack/phy/LoRaPHYCN470.cpp index 777677765a..01614e34f5 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYCN470.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHYCN470.cpp @@ -212,10 +212,9 @@ LoRaPHYCN470::LoRaPHYCN470() // Channels // 125 kHz channels - for( uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++ ) - { + for (uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++) { channels[i].frequency = 470300000 + i * 200000; - channels[i].dr_range.value = ( DR_5 << 4 ) | DR_0; + channels[i].dr_range.value = (DR_5 << 4) | DR_0; channels[i].band = 0; } @@ -359,7 +358,7 @@ lorawan_status_t LoRaPHYCN470::set_next_channel(channel_selection_params_t *para return LORAWAN_STATUS_NO_CHANNEL_FOUND; } -bool LoRaPHYCN470::rx_config(rx_config_params_t* config) +bool LoRaPHYCN470::rx_config(rx_config_params_t *config) { int8_t dr = config->datarate; uint8_t max_payload = 0; @@ -375,8 +374,7 @@ bool LoRaPHYCN470::rx_config(rx_config_params_t* config) _radio->unlock(); - if( config->rx_slot == RX_SLOT_WIN_1 ) - { + if (config->rx_slot == RX_SLOT_WIN_1) { // Apply window 1 frequency frequency = CN470_FIRST_RX1_CHANNEL + (config->channel % 48) * CN470_STEPWIDTH_RX1_CHANNEL; } @@ -409,8 +407,8 @@ bool LoRaPHYCN470::rx_config(rx_config_params_t* config) return true; } -bool LoRaPHYCN470::tx_config(tx_config_params_t* config, int8_t* tx_power, - lorawan_time_t* tx_toa) +bool LoRaPHYCN470::tx_config(tx_config_params_t *config, int8_t *tx_power, + lorawan_time_t *tx_toa) { int8_t phy_dr = datarates_CN470[config->datarate]; @@ -429,9 +427,9 @@ bool LoRaPHYCN470::tx_config(tx_config_params_t* config, int8_t* tx_power, _radio->set_channel(channels[config->channel].frequency); - _radio->set_tx_config(MODEM_LORA, phy_tx_power, 0, 0, phy_dr, 1, - MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH, false, true, - 0, 0, false, 3000); + _radio->set_tx_config(MODEM_LORA, phy_tx_power, 0, 0, phy_dr, 1, + MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH, false, true, + 0, 0, false, 3000); // Setup maximum payload lenght of the radio driver _radio->set_max_payload_length(MODEM_LORA, config->pkt_len); @@ -446,10 +444,10 @@ bool LoRaPHYCN470::tx_config(tx_config_params_t* config, int8_t* tx_power, return true; } -uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t* params, - int8_t* dr_out, int8_t* tx_power_out, - uint8_t* nb_rep_out, - uint8_t* nb_bytes_parsed) +uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t *params, + int8_t *dr_out, int8_t *tx_power_out, + uint8_t *nb_rep_out, + uint8_t *nb_bytes_parsed) { uint8_t status = 0x07; link_adr_params_t adr_settings; @@ -462,7 +460,7 @@ uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t* params, // Initialize local copy of channels mask copy_channel_mask(temp_channel_masks, channel_mask, CN470_CHANNEL_MASK_SIZE); - while(bytes_processed < params->payload_size) { + while (bytes_processed < params->payload_size) { // Get ADR request parameters next_index = parse_link_ADR_req(&(params->payload[bytes_processed]), &adr_settings); @@ -484,7 +482,7 @@ uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t* params, temp_channel_masks[i] = 0xFFFF; } - } else if( adr_settings.ch_mask_ctrl == 7 ) { + } else if (adr_settings.ch_mask_ctrl == 7) { status &= 0xFE; // Channel mask KO @@ -492,8 +490,8 @@ uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t* params, for (uint8_t i = 0; i < 16; i++) { - if (((adr_settings.channel_mask & (1 << i)) != 0 ) && - (channels[adr_settings.ch_mask_ctrl * 16 + i].frequency == 0)) { + if (((adr_settings.channel_mask & (1 << i)) != 0) && + (channels[adr_settings.ch_mask_ctrl * 16 + i].frequency == 0)) { // Trying to enable an undefined channel status &= 0xFE; // Channel mask KO } @@ -510,7 +508,7 @@ uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t* params, verify_params.nb_rep = adr_settings.nb_rep; verify_params.current_datarate = params->current_datarate; verify_params.current_tx_power = params->current_tx_power; - verify_params.current_nb_rep = params->current_nb_rep; + verify_params.current_nb_rep = params->current_nb_trans; verify_params.channel_mask = temp_channel_masks; @@ -533,7 +531,7 @@ uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t* params, return status; } -uint8_t LoRaPHYCN470::accept_rx_param_setup_req(rx_param_setup_req_t* params) +uint8_t LoRaPHYCN470::accept_rx_param_setup_req(rx_param_setup_req_t *params) { uint8_t status = 0x07; uint32_t freq = params->frequency; diff --git a/features/lorawan/lorastack/phy/LoRaPHYCN470.h b/features/lorawan/lorastack/phy/LoRaPHYCN470.h index 64f0e438fc..6e2a64103b 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYCN470.h +++ b/features/lorawan/lorastack/phy/LoRaPHYCN470.h @@ -57,19 +57,19 @@ public: virtual ~LoRaPHYCN470(); virtual lorawan_status_t set_next_channel(channel_selection_params_t *params, - uint8_t *channel, lorawan_time_t *time, - lorawan_time_t *aggregate_timeoff); + uint8_t *channel, lorawan_time_t *time, + lorawan_time_t *aggregate_timeoff); - virtual bool rx_config(rx_config_params_t* config); + virtual bool rx_config(rx_config_params_t *config); - virtual bool tx_config(tx_config_params_t* config, int8_t* tx_power, - lorawan_time_t* tx_toa); + virtual bool tx_config(tx_config_params_t *config, int8_t *tx_power, + lorawan_time_t *tx_toa); - virtual uint8_t link_ADR_request(adr_req_params_t* params, int8_t* dr_out, - int8_t* tx_power_out, uint8_t* nb_rep_out, - uint8_t* nb_bytes_parsed); + virtual uint8_t link_ADR_request(adr_req_params_t *params, int8_t *dr_out, + int8_t *tx_power_out, uint8_t *nb_rep_out, + uint8_t *nb_bytes_parsed); - virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t* params); + virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t *params); private: diff --git a/features/lorawan/lorastack/phy/LoRaPHYCN779.cpp b/features/lorawan/lorastack/phy/LoRaPHYCN779.cpp index ff6e6d6903..d19e95efb1 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYCN779.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHYCN779.cpp @@ -191,18 +191,18 @@ static const band_t CN779_BAND0 = {100, CN779_MAX_TX_POWER, 0, 0, 0, 779500000, * LoRaMac default channel 1 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t CN779_LC1 = {779500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0}; +static const channel_params_t CN779_LC1 = {779500000, 0, { ((DR_5 << 4) | DR_0) }, 0}; /*! * LoRaMac default channel 2 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t CN779_LC2 = {779700000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0}; +static const channel_params_t CN779_LC2 = {779700000, 0, { ((DR_5 << 4) | DR_0) }, 0}; /*! * LoRaMac default channel 3 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t CN779_LC3 = {779900000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0}; +static const channel_params_t CN779_LC3 = {779900000, 0, { ((DR_5 << 4) | DR_0) }, 0}; /*! * LoRaMac channels which are allowed for the join procedure diff --git a/features/lorawan/lorastack/phy/LoRaPHYEU433.cpp b/features/lorawan/lorastack/phy/LoRaPHYEU433.cpp index a4d2dbded5..50d60ffd50 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYEU433.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHYEU433.cpp @@ -191,19 +191,19 @@ static const band_t EU433_BAND0 = {100, EU433_MAX_TX_POWER, 0, 0, 0, 433175000, * LoRaMac default channel 1 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t EU433_LC1 = {433175000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0}; +static const channel_params_t EU433_LC1 = {433175000, 0, { ((DR_5 << 4) | DR_0) }, 0}; /*! * LoRaMac default channel 2 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t EU433_LC2 = {433375000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0}; +static const channel_params_t EU433_LC2 = {433375000, 0, { ((DR_5 << 4) | DR_0) }, 0}; /*! * LoRaMac default channel 3 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t EU433_LC3 = {433575000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0}; +static const channel_params_t EU433_LC3 = {433575000, 0, { ((DR_5 << 4) | DR_0) }, 0}; /*! * LoRaMac channels which are allowed for the join procedure diff --git a/features/lorawan/lorastack/phy/LoRaPHYEU868.cpp b/features/lorawan/lorastack/phy/LoRaPHYEU868.cpp index 1478a42163..ba1301c015 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYEU868.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHYEU868.cpp @@ -182,12 +182,12 @@ * Band 0 definition * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff } */ -static const band_t EU868_BAND0 = {100 , EU868_MAX_TX_POWER, 0, 0, 0,865000000, 868000000}; // 1.0 % +static const band_t EU868_BAND0 = {100, EU868_MAX_TX_POWER, 0, 0, 0, 865000000, 868000000}; // 1.0 % /*! * Band 1 definition * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff } */ -static const band_t EU868_BAND1 = {100 , EU868_MAX_TX_POWER, 0, 0, 0, 868100000, 868600000}; // 1.0 % +static const band_t EU868_BAND1 = {100, EU868_MAX_TX_POWER, 0, 0, 0, 868100000, 868600000}; // 1.0 % /*! * Band 2 definition @@ -199,13 +199,13 @@ static const band_t EU868_BAND2 = {1000, EU868_MAX_TX_POWER, 0, 0, 0, 868700000, * Band 3 definition * Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff } */ -static const band_t EU868_BAND3 = {10 , EU868_MAX_TX_POWER, 0, 0, 0, 869400000, 869650000}; // 10.0 % +static const band_t EU868_BAND3 = {10, EU868_MAX_TX_POWER, 0, 0, 0, 869400000, 869650000}; // 10.0 % /*! * Band 4 definition * Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff } */ -static const band_t EU868_BAND4 = {100 , EU868_MAX_TX_POWER, 0, 0, 0, 869700000, 870000000}; // 1.0 % +static const band_t EU868_BAND4 = {100, EU868_MAX_TX_POWER, 0, 0, 0, 869700000, 870000000}; // 1.0 % /*! * Band 5 definition - It's actually a sub part of Band 2 @@ -217,19 +217,19 @@ static const band_t EU868_BAND5 = {1000, EU868_MAX_TX_POWER, 0, 0, 0, 863000000, * LoRaMac default channel 1 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t EU868_LC1 = {868100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1}; +static const channel_params_t EU868_LC1 = {868100000, 0, { ((DR_5 << 4) | DR_0) }, 1}; /*! * LoRaMac default channel 2 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t EU868_LC2 = {868300000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1}; +static const channel_params_t EU868_LC2 = {868300000, 0, { ((DR_5 << 4) | DR_0) }, 1}; /*! * LoRaMac default channel 3 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t EU868_LC3 = {868500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1}; +static const channel_params_t EU868_LC3 = {868500000, 0, { ((DR_5 << 4) | DR_0) }, 1}; /*! * LoRaMac channels which are allowed for the join procedure diff --git a/features/lorawan/lorastack/phy/LoRaPHYIN865.cpp b/features/lorawan/lorastack/phy/LoRaPHYIN865.cpp index d9e0631885..bdcfcc24a3 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYIN865.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHYIN865.cpp @@ -182,25 +182,25 @@ * Band 0 definition * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff } */ -static const band_t IN865_BAND0 = { 1 , IN865_MAX_TX_POWER, 0, 0, 0, 865000000, 867000000 }; // 100.0 % +static const band_t IN865_BAND0 = { 1, IN865_MAX_TX_POWER, 0, 0, 0, 865000000, 867000000 }; // 100.0 % /*! * LoRaMac default channel 1 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t IN865_LC1 = { 865062500, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }; +static const channel_params_t IN865_LC1 = { 865062500, 0, { ((DR_5 << 4) | DR_0) }, 0 }; /*! * LoRaMac default channel 2 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t IN865_LC2 = { 865402500, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }; +static const channel_params_t IN865_LC2 = { 865402500, 0, { ((DR_5 << 4) | DR_0) }, 0 }; /*! * LoRaMac default channel 3 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t IN865_LC3 = { 865985000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }; +static const channel_params_t IN865_LC3 = { 865985000, 0, { ((DR_5 << 4) | DR_0) }, 0 }; /*! * LoRaMac channels which are allowed for the join procedure diff --git a/features/lorawan/lorastack/phy/LoRaPHYIN865.h b/features/lorawan/lorastack/phy/LoRaPHYIN865.h index 50e2d41821..491364ec46 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYIN865.h +++ b/features/lorawan/lorastack/phy/LoRaPHYIN865.h @@ -55,7 +55,7 @@ public: LoRaPHYIN865(); virtual ~LoRaPHYIN865(); - virtual uint8_t apply_DR_offset(int8_t dr, int8_t dr_offset ); + virtual uint8_t apply_DR_offset(int8_t dr, int8_t dr_offset); private: /*! diff --git a/features/lorawan/lorastack/phy/LoRaPHYKR920.cpp b/features/lorawan/lorastack/phy/LoRaPHYKR920.cpp index 3bba5e11f2..e5df591e61 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYKR920.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHYKR920.cpp @@ -186,25 +186,25 @@ * Band 0 definition * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff } */ -static const band_t KR920_BAND0 = { 1 , KR920_MAX_TX_POWER, 0, 0, 0 }; // 100.0 % +static const band_t KR920_BAND0 = { 1, KR920_MAX_TX_POWER, 0, 0, 0 }; // 100.0 % /*! * LoRaMac default channel 1 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t KR920_LC1 = { 922100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }; +static const channel_params_t KR920_LC1 = { 922100000, 0, { ((DR_5 << 4) | DR_0) }, 0 }; /*! * LoRaMac default channel 2 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t KR920_LC2 = { 922300000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }; +static const channel_params_t KR920_LC2 = { 922300000, 0, { ((DR_5 << 4) | DR_0) }, 0 }; /*! * LoRaMac default channel 3 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } */ -static const channel_params_t KR920_LC3 = { 922500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }; +static const channel_params_t KR920_LC3 = { 922500000, 0, { ((DR_5 << 4) | DR_0) }, 0 }; /*! * LoRaMac channels which are allowed for the join procedure @@ -254,7 +254,7 @@ LoRaPHYKR920::LoRaPHYKR920() channels[2].band = 0; // Initialize the channels default mask - default_channel_mask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); + default_channel_mask[0] = LC(1) + LC(2) + LC(3); // Update the channels mask copy_channel_mask(channel_mask, default_channel_mask, KR920_CHANNEL_MASK_SIZE); @@ -356,7 +356,7 @@ bool LoRaPHYKR920::verify_frequency_for_band(uint32_t freq, uint8_t band) const // Verify if the frequency is valid. The frequency must be in a specified // range and can be set to specific values. - if ((tmp_freq >= 920900000) && (tmp_freq <=923300000)) { + if ((tmp_freq >= 920900000) && (tmp_freq <= 923300000)) { // Range ok, check for specific value tmp_freq -= 920900000; if ((tmp_freq % 200000) == 0) { @@ -367,8 +367,8 @@ bool LoRaPHYKR920::verify_frequency_for_band(uint32_t freq, uint8_t band) const return false; } -bool LoRaPHYKR920::tx_config(tx_config_params_t* config, int8_t* tx_power, - lorawan_time_t* tx_toa) +bool LoRaPHYKR920::tx_config(tx_config_params_t *config, int8_t *tx_power, + lorawan_time_t *tx_toa) { int8_t phy_dr = datarates_KR920[config->datarate]; @@ -393,12 +393,12 @@ bool LoRaPHYKR920::tx_config(tx_config_params_t* config, int8_t* tx_power, _radio->set_channel(channels[config->channel].frequency); _radio->set_tx_config(MODEM_LORA, phy_tx_power, 0, bandwidth, phy_dr, 1, 8, - false, true, 0, 0, false, 3000 ); + false, true, 0, 0, false, 3000); // Setup maximum payload lenght of the radio driver _radio->set_max_payload_length(MODEM_LORA, config->pkt_len); // Get the time-on-air of the next tx frame - *tx_toa =_radio->time_on_air(MODEM_LORA, config->pkt_len); + *tx_toa = _radio->time_on_air(MODEM_LORA, config->pkt_len); _radio->unlock(); @@ -406,9 +406,9 @@ bool LoRaPHYKR920::tx_config(tx_config_params_t* config, int8_t* tx_power, return true; } -lorawan_status_t LoRaPHYKR920::set_next_channel(channel_selection_params_t* params, - uint8_t* channel, lorawan_time_t* time, - lorawan_time_t* aggregate_timeoff) +lorawan_status_t LoRaPHYKR920::set_next_channel(channel_selection_params_t *params, + uint8_t *channel, lorawan_time_t *time, + lorawan_time_t *aggregate_timeoff) { uint8_t next_channel_idx = 0; uint8_t nb_enabled_channels = 0; @@ -441,9 +441,9 @@ lorawan_status_t LoRaPHYKR920::set_next_channel(channel_selection_params_t* para if (nb_enabled_channels > 0) { for (uint8_t i = 0, j = get_random(0, nb_enabled_channels - 1); - i < KR920_MAX_NB_CHANNELS; i++) { + i < KR920_MAX_NB_CHANNELS; i++) { next_channel_idx = enabled_channels[j]; - j = ( j + 1 ) % nb_enabled_channels; + j = (j + 1) % nb_enabled_channels; // Perform carrier sense for KR920_CARRIER_SENSE_TIME // If the channel is free, we can stop the LBT mechanism @@ -452,7 +452,7 @@ lorawan_status_t LoRaPHYKR920::set_next_channel(channel_selection_params_t* para if (_radio->perform_carrier_sense(MODEM_LORA, channels[next_channel_idx].frequency, KR920_RSSI_FREE_TH, - KR920_CARRIER_SENSE_TIME ) == true) { + KR920_CARRIER_SENSE_TIME) == true) { // Free channel found *channel = next_channel_idx; *time = 0; @@ -480,7 +480,7 @@ lorawan_status_t LoRaPHYKR920::set_next_channel(channel_selection_params_t* para } } -void LoRaPHYKR920::set_tx_cont_mode(cw_mode_params_t* params, uint32_t given_frequency) +void LoRaPHYKR920::set_tx_cont_mode(cw_mode_params_t *params, uint32_t given_frequency) { (void)given_frequency; @@ -495,7 +495,7 @@ void LoRaPHYKR920::set_tx_cont_mode(cw_mode_params_t* params, uint32_t given_fre // Take the minimum between the max_eirp and params->max_eirp. // The value of params->max_eirp could have changed during runtime, // e.g. due to a MAC command. - max_eirp = MIN (params->max_eirp, max_eirp); + max_eirp = MIN(params->max_eirp, max_eirp); // Calculate physical TX power phy_tx_power = compute_tx_power(params->tx_power, max_eirp, params->antenna_gain); diff --git a/features/lorawan/lorastack/phy/LoRaPHYKR920.h b/features/lorawan/lorastack/phy/LoRaPHYKR920.h index 771a335b16..8fcc255641 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYKR920.h +++ b/features/lorawan/lorastack/phy/LoRaPHYKR920.h @@ -56,14 +56,14 @@ public: virtual bool verify_frequency_for_band(uint32_t freq, uint8_t band) const; - virtual bool tx_config(tx_config_params_t* config, int8_t* tx_power, - lorawan_time_t* tx_toa); + virtual bool tx_config(tx_config_params_t *config, int8_t *tx_power, + lorawan_time_t *tx_toa); - virtual lorawan_status_t set_next_channel(channel_selection_params_t* params, uint8_t* channel, - lorawan_time_t* time, - lorawan_time_t* aggregate_timeOff); + virtual lorawan_status_t set_next_channel(channel_selection_params_t *params, uint8_t *channel, + lorawan_time_t *time, + lorawan_time_t *aggregate_timeOff); - virtual void set_tx_cont_mode(cw_mode_params_t* continuousWave, + virtual void set_tx_cont_mode(cw_mode_params_t *continuousWave, uint32_t frequency = 0); diff --git a/features/lorawan/lorastack/phy/LoRaPHYUS915.cpp b/features/lorawan/lorastack/phy/LoRaPHYUS915.cpp index a531de055b..abc496be13 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYUS915.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHYUS915.cpp @@ -192,10 +192,9 @@ static const uint32_t bandwidths_US915[] = {125000, 125000, 125000, 125000, 5000 /*! * Up/Down link data rates offset definition */ -static const int8_t datarate_offsets_US915[5][4] = -{ - { DR_10, DR_9 , DR_8 , DR_8 }, // DR_0 - { DR_11, DR_10, DR_9 , DR_8 }, // DR_1 +static const int8_t datarate_offsets_US915[5][4] = { + { DR_10, DR_9, DR_8, DR_8 }, // DR_0 + { DR_11, DR_10, DR_9, DR_8 }, // DR_1 { DR_12, DR_11, DR_10, DR_9 }, // DR_2 { DR_13, DR_12, DR_11, DR_10 }, // DR_3 { DR_13, DR_13, DR_12, DR_11 }, // DR_4 @@ -222,13 +221,13 @@ LoRaPHYUS915::LoRaPHYUS915() // 125 kHz channels - Upstream for (uint8_t i = 0; i < US915_MAX_NB_CHANNELS - 8; i++) { channels[i].frequency = 902300000 + i * 200000; - channels[i].dr_range.value = ( DR_3 << 4) | DR_0; + channels[i].dr_range.value = (DR_3 << 4) | DR_0; channels[i].band = 0; } // 500 kHz channels - Upstream for (uint8_t i = US915_MAX_NB_CHANNELS - 8; i < US915_MAX_NB_CHANNELS; i++) { - channels[i].frequency = 903000000 + (i - ( US915_MAX_NB_CHANNELS - 8)) * 1600000; - channels[i].dr_range.value = ( DR_4 << 4) | DR_4; + channels[i].frequency = 903000000 + (i - (US915_MAX_NB_CHANNELS - 8)) * 1600000; + channels[i].dr_range.value = (DR_4 << 4) | DR_4; channels[i].band = 0; } @@ -325,16 +324,16 @@ int8_t LoRaPHYUS915::limit_tx_power(int8_t tx_power, int8_t max_band_tx_power, int8_t tx_power_out = tx_power; // Limit tx power to the band max - tx_power_out = MAX (tx_power, max_band_tx_power); + tx_power_out = MAX(tx_power, max_band_tx_power); if (datarate == DR_4) { // Limit tx power to max 26dBm - tx_power_out = MAX (tx_power, TX_POWER_2); + tx_power_out = MAX(tx_power, TX_POWER_2); } else { if (num_active_channels(channel_mask, 0, 4) < 50) { // Limit tx power to max 21dBm - tx_power_out = MAX (tx_power, TX_POWER_5); + tx_power_out = MAX(tx_power, TX_POWER_5); } } @@ -350,7 +349,7 @@ void LoRaPHYUS915::restore_default_channels() intersect_channel_mask(channel_mask, current_channel_mask, US915_CHANNEL_MASK_SIZE); } -bool LoRaPHYUS915::rx_config(rx_config_params_t* config) +bool LoRaPHYUS915::rx_config(rx_config_params_t *config) { int8_t dr = config->datarate; uint8_t max_payload = 0; @@ -410,8 +409,8 @@ bool LoRaPHYUS915::rx_config(rx_config_params_t* config) return true; } -bool LoRaPHYUS915::tx_config(tx_config_params_t* config, int8_t* tx_power, - lorawan_time_t* tx_toa) +bool LoRaPHYUS915::tx_config(tx_config_params_t *config, int8_t *tx_power, + lorawan_time_t *tx_toa) { int8_t phy_dr = datarates_US915[config->datarate]; int8_t tx_power_limited = limit_tx_power(config->tx_power, @@ -422,7 +421,7 @@ bool LoRaPHYUS915::tx_config(tx_config_params_t* config, int8_t* tx_power, int8_t phy_tx_power = 0; // Calculate physical TX power - phy_tx_power = compute_tx_power( tx_power_limited, US915_DEFAULT_MAX_ERP, 0 ); + phy_tx_power = compute_tx_power(tx_power_limited, US915_DEFAULT_MAX_ERP, 0); _radio->lock(); @@ -445,9 +444,9 @@ bool LoRaPHYUS915::tx_config(tx_config_params_t* config, int8_t* tx_power, return true; } -uint8_t LoRaPHYUS915::link_ADR_request(adr_req_params_t* params, - int8_t* dr_out, int8_t* tx_power_out, - uint8_t* nb_rep_out, uint8_t* nb_bytes_parsed) +uint8_t LoRaPHYUS915::link_ADR_request(adr_req_params_t *params, + int8_t *dr_out, int8_t *tx_power_out, + uint8_t *nb_rep_out, uint8_t *nb_bytes_parsed) { uint8_t status = 0x07; @@ -504,7 +503,7 @@ uint8_t LoRaPHYUS915::link_ADR_request(adr_req_params_t* params, // FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels if ((adr_settings.datarate < DR_4) && - (num_active_channels(temp_channel_masks, 0, 4) < 2)) { + (num_active_channels(temp_channel_masks, 0, 4) < 2)) { status &= 0xFE; // Channel mask KO @@ -517,7 +516,7 @@ uint8_t LoRaPHYUS915::link_ADR_request(adr_req_params_t* params, verify_params.nb_rep = adr_settings.nb_rep; verify_params.current_datarate = params->current_datarate; verify_params.current_tx_power = params->current_tx_power; - verify_params.current_nb_rep = params->current_nb_rep; + verify_params.current_nb_rep = params->current_nb_trans; verify_params.channel_mask = temp_channel_masks; // Verify the parameters and update, if necessary @@ -543,7 +542,7 @@ uint8_t LoRaPHYUS915::link_ADR_request(adr_req_params_t* params, return status; } -uint8_t LoRaPHYUS915::accept_rx_param_setup_req(rx_param_setup_req_t* params) +uint8_t LoRaPHYUS915::accept_rx_param_setup_req(rx_param_setup_req_t *params) { uint8_t status = 0x07; uint32_t freq = params->frequency; @@ -572,8 +571,7 @@ uint8_t LoRaPHYUS915::accept_rx_param_setup_req(rx_param_setup_req_t* params) } // Verify datarate offset - if (val_in_range( params->dr_offset, US915_MIN_RX1_DR_OFFSET, US915_MAX_RX1_DR_OFFSET ) == 0 ) - { + if (val_in_range(params->dr_offset, US915_MIN_RX1_DR_OFFSET, US915_MAX_RX1_DR_OFFSET) == 0) { status &= 0xFB; // Rx1DrOffset range KO } @@ -593,9 +591,9 @@ int8_t LoRaPHYUS915::get_alternate_DR(uint8_t nb_trials) return datarate; } -lorawan_status_t LoRaPHYUS915::set_next_channel(channel_selection_params_t* params, - uint8_t* channel, lorawan_time_t* time, - lorawan_time_t* aggregate_timeOff) +lorawan_status_t LoRaPHYUS915::set_next_channel(channel_selection_params_t *params, + uint8_t *channel, lorawan_time_t *time, + lorawan_time_t *aggregate_timeOff) { uint8_t nb_enabled_channels = 0; uint8_t delay_tx = 0; @@ -654,13 +652,13 @@ lorawan_status_t LoRaPHYUS915::set_next_channel(channel_selection_params_t* para } } -void LoRaPHYUS915::set_tx_cont_mode(cw_mode_params_t* params, uint32_t given_frequency) +void LoRaPHYUS915::set_tx_cont_mode(cw_mode_params_t *params, uint32_t given_frequency) { (void)given_frequency; int8_t tx_power_limited = limit_tx_power(params->tx_power, - bands[channels[params->channel].band].max_tx_pwr, - params->datarate); + bands[channels[params->channel].band].max_tx_pwr, + params->datarate); int8_t phyTxPower = 0; uint32_t frequency = channels[params->channel].frequency; @@ -676,11 +674,33 @@ void LoRaPHYUS915::set_tx_cont_mode(cw_mode_params_t* params, uint32_t given_fre uint8_t LoRaPHYUS915::apply_DR_offset(int8_t dr, int8_t dr_offset) { - int8_t datarate = datarate_offsets_US915[dr][dr_offset]; + return datarate_offsets_US915[dr][dr_offset]; +} - if (datarate < 0) { - datarate = DR_0; + +void LoRaPHYUS915::intersect_channel_mask(const uint16_t *source, + uint16_t *destination, uint8_t size) +{ + for (uint8_t i = 0; i < size; i++) { + destination[i] &= source[i]; + } +} + +void LoRaPHYUS915::fill_channel_mask_with_fsb(const uint16_t *expectation, + const uint16_t *fsb_mask, + uint16_t *destination, + uint8_t size) +{ + for (uint8_t i = 0; i < size; i++) { + destination[i] = expectation[i] & fsb_mask[i]; } - return datarate; +} + +void LoRaPHYUS915::fill_channel_mask_with_value(uint16_t *channel_mask, + uint16_t value, uint8_t size) +{ + for (uint8_t i = 0; i < size; i++) { + channel_mask[i] = value; + } } diff --git a/features/lorawan/lorastack/phy/LoRaPHYUS915.h b/features/lorawan/lorastack/phy/LoRaPHYUS915.h index 2c883ae69d..5a48e374a9 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYUS915.h +++ b/features/lorawan/lorastack/phy/LoRaPHYUS915.h @@ -56,30 +56,50 @@ public: virtual void restore_default_channels(); - virtual bool rx_config(rx_config_params_t* config); + virtual bool rx_config(rx_config_params_t *config); - virtual bool tx_config(tx_config_params_t* config, int8_t* tx_power, - lorawan_time_t* tx_toa); + virtual bool tx_config(tx_config_params_t *config, int8_t *tx_power, + lorawan_time_t *tx_toa); - virtual uint8_t link_ADR_request(adr_req_params_t* params, - int8_t* dr_out, int8_t* tx_power_out, - uint8_t* nb_rep_out, - uint8_t* nb_bytes_parsed); + virtual uint8_t link_ADR_request(adr_req_params_t *params, + int8_t *dr_out, int8_t *tx_power_out, + uint8_t *nb_rep_out, + uint8_t *nb_bytes_parsed); - virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t* params); + virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t *params); virtual int8_t get_alternate_DR(uint8_t nb_trials); - virtual lorawan_status_t set_next_channel(channel_selection_params_t* params, uint8_t* channel, - lorawan_time_t* time, lorawan_time_t* aggregate_timeOff); + virtual lorawan_status_t set_next_channel(channel_selection_params_t *params, uint8_t *channel, + lorawan_time_t *time, lorawan_time_t *aggregate_timeOff); - virtual void set_tx_cont_mode(cw_mode_params_t* continuousWave, + virtual void set_tx_cont_mode(cw_mode_params_t *continuousWave, uint32_t frequency = 0); virtual uint8_t apply_DR_offset(int8_t dr, int8_t dr_offset); private: + /** + * Sets the intersection of source and destination channel masks + * into the destination. + */ + void intersect_channel_mask(const uint16_t *source, uint16_t *destination, + uint8_t size); + + /** + * Fills channel mask array based upon the provided FSB mask + */ + void fill_channel_mask_with_fsb(const uint16_t *expectation, + const uint16_t *fsb_mask, + uint16_t *channel_mask, uint8_t size); + + /** + * Fills channel mask array with a given value + */ + void fill_channel_mask_with_value(uint16_t *channel_mask, + uint16_t value, uint8_t size); + int8_t limit_tx_power(int8_t tx_power, int8_t max_band_tx_power, int8_t datarate); diff --git a/features/lorawan/lorastack/phy/lora_phy_ds.h b/features/lorawan/lorastack/phy/lora_phy_ds.h index 79af3e9d31..8bf5e29a34 100644 --- a/features/lorawan/lorastack/phy/lora_phy_ds.h +++ b/features/lorawan/lorastack/phy/lora_phy_ds.h @@ -307,7 +307,7 @@ typedef struct { /*! * A pointer to the payload containing the MAC commands. */ - const uint8_t* payload; + const uint8_t *payload; /*! * The size of the payload. */ @@ -329,9 +329,10 @@ typedef struct { */ int8_t current_tx_power; /*! - * The current number of repetitions. + * The current number of repetitions for obtaining a QOS level set by + * NS (applicable only to unconfirmed messages). */ - uint8_t current_nb_rep; + uint8_t current_nb_trans; } adr_req_params_t; /** @@ -401,7 +402,7 @@ typedef struct verify_adr_params_s { /*! * A pointer to the first element of the channels mask. */ - uint16_t* channel_mask; + uint16_t *channel_mask; } verify_adr_params_t; /** diff --git a/features/lorawan/lorastack/phy/loraphy_target.h b/features/lorawan/lorastack/phy/loraphy_target.h index 480cf3a3bb..cef9be9a93 100644 --- a/features/lorawan/lorastack/phy/loraphy_target.h +++ b/features/lorawan/lorastack/phy/loraphy_target.h @@ -48,38 +48,38 @@ #define mbed_lora_concat(x) mbed_lora_concat_(x) #define LORA_REGION mbed_lora_concat(MBED_CONF_LORA_PHY) - #if LORA_REGION == LORA_REGION_EU868 - #include "lorawan/lorastack/phy/LoRaPHYEU868.h" - #define LoRaPHY_region LoRaPHYEU868 - #elif LORA_REGION == LORA_REGION_AS923 - #include "lorawan/lorastack/phy/LoRaPHYAS923.h" - #define LoRaPHY_region LoRaPHYAS923 - #elif LORA_REGION == LORA_REGION_AU915 - #include "lorawan/lorastack/phy/LoRaPHYAU915.h" - #define LoRaPHY_region LoRaPHYAU915 - #elif LORA_REGION == LORA_REGION_CN470 - #include "lorawan/lorastack/phy/LoRaPHYCN470.h" - #define LoRaPHY_region LoRaPHYCN470 - #elif LORA_REGION == LORA_REGION_CN779 - #include "lorawan/lorastack/phy/LoRaPHYCN779.h" - #define LoRaPHY_region LoRaPHYCN779 - #elif LORA_REGION == LORA_REGION_EU433 - #include "lorawan/lorastack/phy/LoRaPHYEU433.h" - #define LoRaPHY_region LoRaPHYEU433 - #elif LORA_REGION == LORA_REGION_IN865 - #include "lorawan/lorastack/phy/LoRaPHYIN865.h" - #define LoRaPHY_region LoRaPHYIN865 - #elif LORA_REGION == LORA_REGION_KR920 - #include "lorawan/lorastack/phy/LoRaPHYKR920.h" - #define LoRaPHY_region LoRaPHYKR920 - #elif LORA_REGION == LORA_REGION_US915 - #include "lorawan/lorastack/phy/LoRaPHYUS915.h" - #define LoRaPHY_region LoRaPHYUS915 - #else - #error "Invalid region configuration, update mbed_app.json with correct MBED_CONF_LORA_PHY value" - #endif //MBED_CONF_LORA_PHY == VALUE +#if LORA_REGION == LORA_REGION_EU868 +#include "lorawan/lorastack/phy/LoRaPHYEU868.h" +#define LoRaPHY_region LoRaPHYEU868 +#elif LORA_REGION == LORA_REGION_AS923 +#include "lorawan/lorastack/phy/LoRaPHYAS923.h" +#define LoRaPHY_region LoRaPHYAS923 +#elif LORA_REGION == LORA_REGION_AU915 +#include "lorawan/lorastack/phy/LoRaPHYAU915.h" +#define LoRaPHY_region LoRaPHYAU915 +#elif LORA_REGION == LORA_REGION_CN470 +#include "lorawan/lorastack/phy/LoRaPHYCN470.h" +#define LoRaPHY_region LoRaPHYCN470 +#elif LORA_REGION == LORA_REGION_CN779 +#include "lorawan/lorastack/phy/LoRaPHYCN779.h" +#define LoRaPHY_region LoRaPHYCN779 +#elif LORA_REGION == LORA_REGION_EU433 +#include "lorawan/lorastack/phy/LoRaPHYEU433.h" +#define LoRaPHY_region LoRaPHYEU433 +#elif LORA_REGION == LORA_REGION_IN865 +#include "lorawan/lorastack/phy/LoRaPHYIN865.h" +#define LoRaPHY_region LoRaPHYIN865 +#elif LORA_REGION == LORA_REGION_KR920 +#include "lorawan/lorastack/phy/LoRaPHYKR920.h" +#define LoRaPHY_region LoRaPHYKR920 +#elif LORA_REGION == LORA_REGION_US915 +#include "lorawan/lorastack/phy/LoRaPHYUS915.h" +#define LoRaPHY_region LoRaPHYUS915 #else - #error "Must set LoRa PHY layer parameters." +#error "Invalid region configuration, update mbed_app.json with correct MBED_CONF_LORA_PHY value" +#endif //MBED_CONF_LORA_PHY == VALUE +#else +#error "Must set LoRa PHY layer parameters." #endif //MBED_CONF_LORA_PHY #endif // LORAPHY_TARGET diff --git a/features/lorawan/lorawan_types.h b/features/lorawan/lorawan_types.h index 186eda07a1..fd0a6e791c 100644 --- a/features/lorawan/lorawan_types.h +++ b/features/lorawan/lorawan_types.h @@ -98,13 +98,9 @@ typedef enum lorawan_status { LORAWAN_STATUS_CRYPTO_FAIL = -1014, /**< Service not started - crypto failure */ LORAWAN_STATUS_PORT_INVALID = -1015, /**< Invalid port */ LORAWAN_STATUS_CONNECT_IN_PROGRESS = -1016, /**< Services started - Connection in progress */ - LORAWAN_STATUS_NO_ACTIVE_SESSIONS = -1017, /**< Services not started - No active session */ + LORAWAN_STATUS_NO_ACTIVE_SESSIONS = -1017, /**< Services not started - No active session */ LORAWAN_STATUS_IDLE = -1018, /**< Services started - Idle at the moment */ -#if defined(LORAWAN_COMPLIANCE_TEST) - //Deprecated - will replace the code -1019 with something - //else in future. - LORAWAN_STATUS_COMPLIANCE_TEST_ON = -1019, /**< Compliance test - is on-going */ -#endif + LORAWAN_STATUS_NO_OP = -1019, /**< Cannot perform requested operation */ LORAWAN_STATUS_DUTYCYCLE_RESTRICTED = -1020, /**< Transmission will continue after duty cycle backoff*/ LORAWAN_STATUS_NO_CHANNEL_FOUND = -1021, /**< None of the channels is enabled at the moment*/ LORAWAN_STATUS_NO_FREE_CHANNEL_FOUND = -1022, /**< None of the enabled channels is ready for another TX (duty cycle limited)*/ diff --git a/features/lorawan/system/LoRaWANTimer.cpp b/features/lorawan/system/LoRaWANTimer.cpp index df5e5abba8..a91424b96d 100644 --- a/features/lorawan/system/LoRaWANTimer.cpp +++ b/features/lorawan/system/LoRaWANTimer.cpp @@ -34,7 +34,7 @@ void LoRaWANTimeHandler::activate_timer_subsystem(events::EventQueue *queue) _queue = queue; } -lorawan_time_t LoRaWANTimeHandler::get_current_time( void ) +lorawan_time_t LoRaWANTimeHandler::get_current_time(void) { const uint32_t current_time = _queue->tick(); return (lorawan_time_t)current_time; diff --git a/features/lorawan/system/LoRaWANTimer.h b/features/lorawan/system/LoRaWANTimer.h index bfe90c234a..e66d2680b6 100644 --- a/features/lorawan/system/LoRaWANTimer.h +++ b/features/lorawan/system/LoRaWANTimer.h @@ -26,8 +26,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "lorawan_data_structures.h" -class LoRaWANTimeHandler -{ +class LoRaWANTimeHandler { public: LoRaWANTimeHandler(); ~LoRaWANTimeHandler(); @@ -62,7 +61,7 @@ public: * @param [in] obj The structure containing the timer object parameters. * @param [in] callback The function callback called at the end of the timeout. */ - void init(timer_event_t &obj, mbed::Callback callback); + void init(timer_event_t &obj, mbed::Callback callback); /** Starts and adds the timer object to the list of timer events. * diff --git a/features/lorawan/system/lorawan_data_structures.h b/features/lorawan/system/lorawan_data_structures.h index fcf9d88f35..45c3a56326 100644 --- a/features/lorawan/system/lorawan_data_structures.h +++ b/features/lorawan/system/lorawan_data_structures.h @@ -70,14 +70,16 @@ typedef uint32_t lorawan_time_t; */ #define LORAMAC_PHY_MAXPAYLOAD 255 +#define LORAWAN_DEFAULT_QOS 1 + /** * * Default user application maximum data size for transmission */ // reject if user tries to set more than MTU #if MBED_CONF_LORA_TX_MAX_SIZE > 255 - #warning "Cannot set TX Max size more than MTU=255" - #define MBED_CONF_LORA_TX_MAX_SIZE 255 +#warning "Cannot set TX Max size more than MTU=255" +#define MBED_CONF_LORA_TX_MAX_SIZE 255 #endif /*! @@ -187,9 +189,10 @@ typedef struct { */ uint32_t join_accept_delay2; /*! - * The number of uplink messages repetitions (confirmed messages only). + * The number of uplink messages repetitions for QOS set by network server + * in LinkADRReq mac command (unconfirmed messages only). */ - uint8_t retry_num; + uint8_t nb_trans; /*! * The datarate offset between uplink and downlink on first window. */ @@ -874,6 +877,9 @@ typedef struct { */ int8_t data_rate; /*! + * + * For CONFIRMED Messages: + * * The number of trials to transmit the frame, if the LoRaMAC layer did not * receive an acknowledgment. The MAC performs a datarate adaptation * according to the LoRaWAN Specification V1.0.2, chapter 18.4, as in @@ -892,6 +898,13 @@ typedef struct { * * Note that if nb_trials is set to 1 or 2, the MAC will not decrease * the datarate, if the LoRaMAC layer did not receive an acknowledgment. + * + * For UNCONFIRMED Messages: + * + * Provides a certain QOS level set by network server in LinkADRReq MAC + * command. The device will transmit the given UNCONFIRMED message nb_trials + * time with same frame counter until a downlink is received. Standard defined + * range is 1:15. Data rates will NOT be adapted according to chapter 18.4. */ uint8_t nb_trials; diff --git a/features/lwipstack/LWIPInterface.cpp b/features/lwipstack/LWIPInterface.cpp index 9c59ea3316..c469f2ddbc 100644 --- a/features/lwipstack/LWIPInterface.cpp +++ b/features/lwipstack/LWIPInterface.cpp @@ -59,10 +59,10 @@ static void add_dns_addr_to_dns_list_index(const u8_t addr_type, const u8_t inde if (addr_type == IPADDR_TYPE_V6) { /* 2001:4860:4860::8888 google */ ip_addr_t ipv6_dns_addr = IPADDR6_INIT( - PP_HTONL(0x20014860UL), - PP_HTONL(0x48600000UL), - PP_HTONL(0x00000000UL), - PP_HTONL(0x00008888UL)); + PP_HTONL(0x20014860UL), + PP_HTONL(0x48600000UL), + PP_HTONL(0x00000000UL), + PP_HTONL(0x00008888UL)); dns_setserver(index, &ipv6_dns_addr); } #endif @@ -166,8 +166,9 @@ nsapi_error_t LWIP::Interface::set_dhcp() void LWIP::Interface::netif_link_irq(struct netif *netif) { LWIP::Interface *interface = our_if_from_netif(netif); + nsapi_connection_status_t connectedStatusPrev = interface->connected; - if (netif_is_link_up(&interface->netif)) { + if (netif_is_link_up(&interface->netif) && interface->connected == NSAPI_STATUS_CONNECTING) { nsapi_error_t dhcp_status = interface->set_dhcp(); if (interface->blocking && dhcp_status == NSAPI_ERROR_OK) { @@ -177,15 +178,25 @@ void LWIP::Interface::netif_link_irq(struct netif *netif) } } else { osSemaphoreRelease(interface->unlinked); + if (netif_is_up(&interface->netif)) { + interface->connected = NSAPI_STATUS_CONNECTING; + } netif_set_down(&interface->netif); } + + if (interface->client_callback && connectedStatusPrev != interface->connected + && interface->connected != NSAPI_STATUS_GLOBAL_UP /* advertised by netif_status_irq */ + && interface->connected != NSAPI_STATUS_DISCONNECTED) { /* advertised by bring_down */ + interface->client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, interface->connected); + } } void LWIP::Interface::netif_status_irq(struct netif *netif) { LWIP::Interface *interface = our_if_from_netif(netif); + nsapi_connection_status_t connectedStatusPrev = interface->connected; - if (netif_is_up(&interface->netif)) { + if (netif_is_up(&interface->netif) && netif_is_link_up(&interface->netif)) { bool dns_addr_has_to_be_added = false; if (!(interface->has_addr_state & HAS_ANY_ADDR) && LWIP::get_ip_addr(true, netif)) { if (interface->blocking) { @@ -212,19 +223,19 @@ void LWIP::Interface::netif_status_irq(struct netif *netif) dns_addr_has_to_be_added = true; } #endif - if (dns_addr_has_to_be_added && !interface->blocking) { + if (dns_addr_has_to_be_added && !interface->blocking) { add_dns_addr(&interface->netif); } - if (interface->has_addr_state & HAS_ANY_ADDR) { interface->connected = NSAPI_STATUS_GLOBAL_UP; } - } else { + } else if (!netif_is_up(&interface->netif) && netif_is_link_up(&interface->netif)) { interface->connected = NSAPI_STATUS_DISCONNECTED; } - if (interface->client_callback) { + if (interface->client_callback && (connectedStatusPrev != interface->connected) + && interface->connected != NSAPI_STATUS_DISCONNECTED) { /* advertised by bring_down */ interface->client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, interface->connected); } } @@ -251,8 +262,8 @@ static void mbed_lwip_clear_ipv6_addresses(struct netif *netif) char *LWIP::Interface::get_mac_address(char *buf, nsapi_size_t buflen) { (void) snprintf(buf, buflen, "%02x:%02x:%02x:%02x:%02x:%02x", - netif.hwaddr[0], netif.hwaddr[1], netif.hwaddr[2], - netif.hwaddr[3], netif.hwaddr[4], netif.hwaddr[5]); + netif.hwaddr[0], netif.hwaddr[1], netif.hwaddr[2], + netif.hwaddr[3], netif.hwaddr[4], netif.hwaddr[5]); return buf; } @@ -306,9 +317,9 @@ char *LWIP::Interface::get_gateway(char *buf, nsapi_size_t buflen) } LWIP::Interface::Interface() : - hw(NULL), has_addr_state(0), - connected(NSAPI_STATUS_DISCONNECTED), - dhcp_started(false), dhcp_has_to_be_set(false), blocking(true), ppp(false) + hw(NULL), has_addr_state(0), + connected(NSAPI_STATUS_DISCONNECTED), + dhcp_started(false), dhcp_has_to_be_set(false), blocking(true), ppp(false) { memset(&netif, 0, sizeof netif); @@ -368,9 +379,9 @@ nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardN if (!netif_add(&interface->netif, #if LWIP_IPV4 - 0, 0, 0, + 0, 0, 0, #endif - interface, &LWIP::Interface::emac_if_init, tcpip_input)) { + interface, &LWIP::Interface::emac_if_init, tcpip_input)) { return NSAPI_ERROR_DEVICE_ERROR; } @@ -486,8 +497,8 @@ nsapi_error_t LWIP::Interface::bringup(bool dhcp, const char *ip, const char *ne ip4_addr_t gw_addr; if (!inet_aton(ip, &ip_addr) || - !inet_aton(netmask, &netmask_addr) || - !inet_aton(gw, &gw_addr)) { + !inet_aton(netmask, &netmask_addr) || + !inet_aton(gw, &gw_addr)) { return NSAPI_ERROR_PARAMETER; } @@ -501,14 +512,14 @@ nsapi_error_t LWIP::Interface::bringup(bool dhcp, const char *ip, const char *ne } if (ppp) { - err_t err = ppp_lwip_connect(hw); - if (err) { - connected = NSAPI_STATUS_DISCONNECTED; - if (client_callback) { - client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED); - } - return err_remap(err); - } + err_t err = ppp_lwip_connect(hw); + if (err) { + connected = NSAPI_STATUS_DISCONNECTED; + if (client_callback) { + client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED); + } + return err_remap(err); + } } if (!netif_is_link_up(&netif)) { @@ -587,16 +598,16 @@ nsapi_error_t LWIP::Interface::bringdown() if (ppp) { /* this is a blocking call, returns when PPP is properly closed */ - err_t err = ppp_lwip_disconnect(hw); - if (err) { - return err_remap(err); - } - MBED_ASSERT(!netif_is_link_up(&netif)); - /*if (netif_is_link_up(&netif)) { - if (sys_arch_sem_wait(&unlinked, 15000) == SYS_ARCH_TIMEOUT) { - return NSAPI_ERROR_DEVICE_ERROR; - } - }*/ + err_t err = ppp_lwip_disconnect(hw); + if (err) { + return err_remap(err); + } + MBED_ASSERT(!netif_is_link_up(&netif)); + /*if (netif_is_link_up(&netif)) { + if (sys_arch_sem_wait(&unlinked, 15000) == SYS_ARCH_TIMEOUT) { + return NSAPI_ERROR_DEVICE_ERROR; + } + }*/ } else { netif_set_down(&netif); } @@ -632,5 +643,8 @@ nsapi_error_t LWIP::Interface::bringdown() has_addr_state = 0; connected = NSAPI_STATUS_DISCONNECTED; + if (client_callback) { + client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, connected); + } return 0; } diff --git a/features/lwipstack/LWIPInterfaceEMAC.cpp b/features/lwipstack/LWIPInterfaceEMAC.cpp index 36d8f90f55..362fc10c75 100644 --- a/features/lwipstack/LWIPInterfaceEMAC.cpp +++ b/features/lwipstack/LWIPInterfaceEMAC.cpp @@ -74,8 +74,7 @@ err_t LWIP::Interface::emac_igmp_mac_filter(struct netif *netif, const ip4_addr_ LWIP::Interface *mbed_if = static_cast(netif->state); switch (action) { - case NETIF_ADD_MAC_FILTER: - { + case NETIF_ADD_MAC_FILTER: { uint32_t group23 = ntohl(group->addr) & 0x007FFFFF; uint8_t addr[6]; addr[0] = LL_IP4_MULTICAST_ADDR_0; @@ -112,8 +111,7 @@ err_t LWIP::Interface::emac_mld_mac_filter(struct netif *netif, const ip6_addr_t LWIP::Interface *mbed_if = static_cast(netif->state); switch (action) { - case NETIF_ADD_MAC_FILTER: - { + case NETIF_ADD_MAC_FILTER: { uint32_t group32 = ntohl(group->addr[3]); uint8_t addr[6]; addr[0] = LL_IP6_MULTICAST_ADDR_0; diff --git a/features/lwipstack/LWIPStack.cpp b/features/lwipstack/LWIPStack.cpp index 751b4d4c90..f9ab49f123 100644 --- a/features/lwipstack/LWIPStack.cpp +++ b/features/lwipstack/LWIPStack.cpp @@ -38,7 +38,7 @@ #include "LWIPStack.h" #ifndef LWIP_SOCKET_MAX_MEMBERSHIPS - #define LWIP_SOCKET_MAX_MEMBERSHIPS 4 +#define LWIP_SOCKET_MAX_MEMBERSHIPS 4 #endif void LWIP::socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len) @@ -54,8 +54,8 @@ void LWIP::socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len) for (int i = 0; i < MEMP_NUM_NETCONN; i++) { if (lwip.arena[i].in_use - && lwip.arena[i].conn == nc - && lwip.arena[i].cb) { + && lwip.arena[i].conn == nc + && lwip.arena[i].cb) { lwip.arena[i].cb(lwip.arena[i].data); } } @@ -101,15 +101,15 @@ static bool convert_mbed_addr_to_lwip(ip_addr_t *out, const nsapi_addr_t *in) { #if LWIP_IPV6 if (in->version == NSAPI_IPv6) { - IP_SET_TYPE(out, IPADDR_TYPE_V6); - SMEMCPY(ip_2_ip6(out), in->bytes, sizeof(ip6_addr_t)); - return true; + IP_SET_TYPE(out, IPADDR_TYPE_V6); + SMEMCPY(ip_2_ip6(out), in->bytes, sizeof(ip6_addr_t)); + return true; } #if !LWIP_IPV4 /* For bind() and other purposes, need to accept "null" of other type */ /* (People use IPv4 0.0.0.0 as a general null) */ if (in->version == NSAPI_UNSPEC || - (in->version == NSAPI_IPv4 && all_zeros(in->bytes, 4))) { + (in->version == NSAPI_IPv4 && all_zeros(in->bytes, 4))) { ip_addr_set_zero_ip6(out); return true; } @@ -118,14 +118,14 @@ static bool convert_mbed_addr_to_lwip(ip_addr_t *out, const nsapi_addr_t *in) #if LWIP_IPV4 if (in->version == NSAPI_IPv4) { - IP_SET_TYPE(out, IPADDR_TYPE_V4); - SMEMCPY(ip_2_ip4(out), in->bytes, sizeof(ip4_addr_t)); - return true; + IP_SET_TYPE(out, IPADDR_TYPE_V4); + SMEMCPY(ip_2_ip4(out), in->bytes, sizeof(ip4_addr_t)); + return true; } #if !LWIP_IPV6 /* For symmetry with above, accept IPv6 :: as a general null */ if (in->version == NSAPI_UNSPEC || - (in->version == NSAPI_IPv6 && all_zeros(in->bytes, 16))) { + (in->version == NSAPI_IPv6 && all_zeros(in->bytes, 16))) { ip_addr_set_zero_ip4(out); return true; } @@ -273,7 +273,7 @@ nsapi_error_t LWIP::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto) #if LWIP_IPV6 // Enable IPv6 (or dual-stack) - lwip_proto = (enum netconn_type) (lwip_proto | NETCONN_TYPE_IPV6); + lwip_proto = (enum netconn_type)(lwip_proto | NETCONN_TYPE_IPV6); #endif s->conn = netconn_new_with_callback(lwip_proto, &LWIP::socket_callback); @@ -485,7 +485,8 @@ nsapi_size_or_error_t LWIP::socket_recvfrom(nsapi_socket_t handle, SocketAddress return recv; } -int32_t LWIP::find_multicast_member(const struct mbed_lwip_socket *s, const nsapi_ip_mreq_t *imr) { +int32_t LWIP::find_multicast_member(const struct mbed_lwip_socket *s, const nsapi_ip_mreq_t *imr) +{ uint32_t count = 0; uint32_t index = 0; // Set upper limit on while loop, should break out when the membership pair is found @@ -493,7 +494,7 @@ int32_t LWIP::find_multicast_member(const struct mbed_lwip_socket *s, const nsap index = next_registered_multicast_member(s, index); if (memcmp(&s->multicast_memberships[index].imr_multiaddr, &imr->imr_multiaddr, sizeof(nsapi_addr_t)) == 0 && - memcmp(&s->multicast_memberships[index].imr_interface, &imr->imr_interface, sizeof(nsapi_addr_t)) == 0) { + memcmp(&s->multicast_memberships[index].imr_interface, &imr->imr_interface, sizeof(nsapi_addr_t)) == 0) { return index; } count++; @@ -522,7 +523,7 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co return NSAPI_ERROR_UNSUPPORTED; } - s->conn->pcb.tcp->keep_idle = *(int*)optval; + s->conn->pcb.tcp->keep_idle = *(int *)optval; return 0; case NSAPI_KEEPINTVL: @@ -530,7 +531,7 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co return NSAPI_ERROR_UNSUPPORTED; } - s->conn->pcb.tcp->keep_intvl = *(int*)optval; + s->conn->pcb.tcp->keep_intvl = *(int *)optval; return 0; #endif @@ -582,11 +583,11 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co if (optname == NSAPI_ADD_MEMBERSHIP) { if (!s->multicast_memberships) { // First multicast join on this socket, allocate space for membership tracking - s->multicast_memberships = (nsapi_ip_mreq_t*)malloc(sizeof(nsapi_ip_mreq_t) * LWIP_SOCKET_MAX_MEMBERSHIPS); + s->multicast_memberships = (nsapi_ip_mreq_t *)malloc(sizeof(nsapi_ip_mreq_t) * LWIP_SOCKET_MAX_MEMBERSHIPS); if (!s->multicast_memberships) { return NSAPI_ERROR_NO_MEMORY; } - } else if(s->multicast_memberships_count == LWIP_SOCKET_MAX_MEMBERSHIPS) { + } else if (s->multicast_memberships_count == LWIP_SOCKET_MAX_MEMBERSHIPS) { return NSAPI_ERROR_NO_MEMORY; } @@ -598,16 +599,16 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co adaptation.lock(); - #if LWIP_IPV4 +#if LWIP_IPV4 if (IP_IS_V4(&if_addr)) { igmp_err = igmp_joingroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr)); } - #endif - #if LWIP_IPV6 +#endif +#if LWIP_IPV6 if (IP_IS_V6(&if_addr)) { igmp_err = mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr)); } - #endif +#endif adaptation.unlock(); @@ -626,22 +627,22 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co adaptation.lock(); - #if LWIP_IPV4 +#if LWIP_IPV4 if (IP_IS_V4(&if_addr)) { igmp_err = igmp_leavegroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr)); } - #endif - #if LWIP_IPV6 +#endif +#if LWIP_IPV6 if (IP_IS_V6(&if_addr)) { igmp_err = mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr)); } - #endif +#endif adaptation.unlock(); } return err_remap(igmp_err); - } + } default: return NSAPI_ERROR_UNSUPPORTED; @@ -662,7 +663,8 @@ void LWIP::socket_attach(nsapi_socket_t handle, void (*callback)(void *), void * s->data = data; } -LWIP &LWIP::get_instance() { +LWIP &LWIP::get_instance() +{ static LWIP lwip; return lwip; } @@ -672,7 +674,8 @@ LWIP &LWIP::get_instance() { #define LWIP 0x11991199 #if MBED_CONF_NSAPI_DEFAULT_STACK == LWIP #undef LWIP -OnboardNetworkStack &OnboardNetworkStack::get_default_instance() { +OnboardNetworkStack &OnboardNetworkStack::get_default_instance() +{ return LWIP::get_instance(); } #endif diff --git a/features/lwipstack/LWIPStack.h b/features/lwipstack/LWIPStack.h index 3ed82cf6d3..4c13ab3946 100644 --- a/features/lwipstack/LWIPStack.h +++ b/features/lwipstack/LWIPStack.h @@ -53,7 +53,7 @@ public: const char *netmask, const char *gw, nsapi_ip_stack_t stack = DEFAULT_STACK, bool blocking = true - ); + ); /** Disconnect interface from the network * @@ -120,24 +120,24 @@ public: static void netif_status_irq(struct netif *netif); static Interface *our_if_from_netif(struct netif *netif); - #if LWIP_ETHERNET +#if LWIP_ETHERNET static err_t emac_low_level_output(struct netif *netif, struct pbuf *p); void emac_input(emac_mem_buf_t *buf); void emac_state_change(bool up); - #if LWIP_IGMP +#if LWIP_IGMP static err_t emac_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, enum netif_mac_filter_action action); - #endif - #if LWIP_IPV6_MLD +#endif +#if LWIP_IPV6_MLD static err_t emac_mld_mac_filter(struct netif *netif, const ip6_addr_t *group, enum netif_mac_filter_action action); - #endif +#endif static err_t emac_if_init(struct netif *netif); - #endif +#endif union { - #if LWIP_ETHERNET +#if LWIP_ETHERNET EMAC *emac; /**< HW specific emac implementation */ - #endif +#endif void *hw; /**< alternative implementation pointer - used for PPP */ }; @@ -147,17 +147,17 @@ public: osSemaphoreId_t unlinked; mbed_rtos_storage_semaphore_t has_any_addr_sem; osSemaphoreId_t has_any_addr; - #define HAS_ANY_ADDR 1 - #if PREF_ADDR_TIMEOUT +#define HAS_ANY_ADDR 1 +#if PREF_ADDR_TIMEOUT mbed_rtos_storage_semaphore_t has_pref_addr_sem; osSemaphoreId_t has_pref_addr; - #define HAS_PREF_ADDR 2 - #endif - #if BOTH_ADDR_TIMEOUT +#define HAS_PREF_ADDR 2 +#endif +#if BOTH_ADDR_TIMEOUT mbed_rtos_storage_semaphore_t has_both_addr_sem; osSemaphoreId_t has_both_addr; - #define HAS_BOTH_ADDR 4 - #endif +#define HAS_BOTH_ADDR 4 +#endif char has_addr_state; nsapi_connection_status_t connected; bool dhcp_started; @@ -301,7 +301,7 @@ protected: * @return 0 on success, negative error code on failure */ virtual nsapi_error_t socket_accept(nsapi_socket_t server, - nsapi_socket_t *handle, SocketAddress *address=0); + nsapi_socket_t *handle, SocketAddress *address = 0); /** Send data over a TCP socket * @@ -487,21 +487,29 @@ private: struct mbed_lwip_socket *arena_alloc(); void arena_dealloc(struct mbed_lwip_socket *s); - static uint32_t next_registered_multicast_member(const struct mbed_lwip_socket *s, uint32_t index) { - while (!(s->multicast_memberships_registry & (0x0001 << index))) { index++; } + static uint32_t next_registered_multicast_member(const struct mbed_lwip_socket *s, uint32_t index) + { + while (!(s->multicast_memberships_registry & (0x0001 << index))) { + index++; + } return index; } - static uint32_t next_free_multicast_member(const struct mbed_lwip_socket *s, uint32_t index) { - while ((s->multicast_memberships_registry & (0x0001 << index))) { index++; } + static uint32_t next_free_multicast_member(const struct mbed_lwip_socket *s, uint32_t index) + { + while ((s->multicast_memberships_registry & (0x0001 << index))) { + index++; + } return index; } - static void set_multicast_member_registry_bit(struct mbed_lwip_socket *s, uint32_t index) { + static void set_multicast_member_registry_bit(struct mbed_lwip_socket *s, uint32_t index) + { s->multicast_memberships_registry |= (0x0001 << index); } - static void clear_multicast_member_registry_bit(struct mbed_lwip_socket *s, uint32_t index) { + static void clear_multicast_member_registry_bit(struct mbed_lwip_socket *s, uint32_t index) + { s->multicast_memberships_registry &= ~(0x0001 << index); } static int32_t find_multicast_member(const struct mbed_lwip_socket *s, const nsapi_ip_mreq_t *imr); diff --git a/features/lwipstack/lwip-sys/arch/cc.h b/features/lwipstack/lwip-sys/arch/cc.h index 90a0d7c868..619e144efd 100644 --- a/features/lwipstack/lwip-sys/arch/cc.h +++ b/features/lwipstack/lwip-sys/arch/cc.h @@ -97,7 +97,7 @@ void lwip_mbed_tracef_debug(const char *fmt, ...); void lwip_mbed_tracef_error(const char *fmt, ...); void lwip_mbed_tracef_warn(const char *fmt, ...); -void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line); +MBED_NORETURN void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line); #define LWIP_PLATFORM_DIAG(vars) lwip_mbed_tracef_debug vars #define LWIP_PLATFORM_DIAG_SEVERE(vars) lwip_mbed_tracef_error vars @@ -109,7 +109,7 @@ void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, #else // MBED_CONF_LWIP_USE_MBED_TRACE #include -void assert_printf(char *msg, int line, char *file); +MBED_NORETURN void assert_printf(char *msg, int line, char *file); /* Plaform specific diagnostic output */ #define LWIP_PLATFORM_DIAG(vars) printf vars diff --git a/features/lwipstack/lwip-sys/arch/lwip_sys_arch.c b/features/lwipstack/lwip-sys/arch/lwip_sys_arch.c index 20ad0b5380..e5afb99901 100644 --- a/features/lwipstack/lwip-sys/arch/lwip_sys_arch.c +++ b/features/lwipstack/lwip-sys/arch/lwip_sys_arch.c @@ -589,7 +589,7 @@ void lwip_mbed_tracef_error(const char *fmt, ...) va_end(ap); } -void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line) +MBED_NORETURN void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line) { mbed_tracef(TRACE_LEVEL_ERROR, "lwIP", "Assertion failed: %s, function %s, file %s, line %u.", msg, func, file, line); exit(EXIT_FAILURE); // XXX how about abort? mbed_assert uses exit, so follow suit @@ -605,7 +605,7 @@ void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, \param[in] line Line number in file with error \param[in] file Filename with error */ -void assert_printf(char *msg, int line, char *file) { +MBED_NORETURN void assert_printf(char *msg, int line, char *file) { if (msg) error("%s:%d in file %s\n", msg, line, file); else diff --git a/features/lwipstack/lwip/src/include/lwip/opt.h b/features/lwipstack/lwip/src/include/lwip/opt.h index cf0a7af6d9..1caa12d769 100644 --- a/features/lwipstack/lwip/src/include/lwip/opt.h +++ b/features/lwipstack/lwip/src/include/lwip/opt.h @@ -1536,7 +1536,7 @@ * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. */ #if !defined TCPIP_THREAD_NAME || defined __DOXYGEN__ -#define TCPIP_THREAD_NAME "tcpip_thread" +#define TCPIP_THREAD_NAME "lwip_tcpip" #endif /** diff --git a/features/lwipstack/lwip_tools.cpp b/features/lwipstack/lwip_tools.cpp index 0e7ee26aa4..29e6bbb730 100644 --- a/features/lwipstack/lwip_tools.cpp +++ b/features/lwipstack/lwip_tools.cpp @@ -27,7 +27,8 @@ #include "netsocket/nsapi_types.h" /* LWIP error remapping */ -nsapi_error_t LWIP::err_remap(err_t err) { +nsapi_error_t LWIP::err_remap(err_t err) +{ switch (err) { case ERR_OK: case ERR_CLSD: @@ -103,7 +104,7 @@ bool LWIP::is_local_addr(const ip_addr_t *ip_addr) if (IP_IS_V6(ip_addr)) { for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(netif_ip6_addr(netif, i), ip_2_ip6(ip_addr))) { + ip6_addr_cmp(netif_ip6_addr(netif, i), ip_2_ip6(ip_addr))) { return true; } } @@ -113,7 +114,7 @@ bool LWIP::is_local_addr(const ip_addr_t *ip_addr) #if LWIP_IPV4 if (IP_IS_V4(ip_addr)) { if (!ip4_addr_isany(netif_ip4_addr(netif)) && - ip4_addr_cmp(netif_ip4_addr(netif), ip_2_ip4(ip_addr))) { + ip4_addr_cmp(netif_ip4_addr(netif), ip_2_ip4(ip_addr))) { return true; } } @@ -185,7 +186,7 @@ void LWIP::arena_dealloc(struct mbed_lwip_socket *s) index = next_registered_multicast_member(s, index); setsockopt(s, NSAPI_SOCKET, NSAPI_DROP_MEMBERSHIP, &s->multicast_memberships[index], - sizeof(s->multicast_memberships[index])); + sizeof(s->multicast_memberships[index])); index++; } diff --git a/features/lwipstack/lwipopts.h b/features/lwipstack/lwipopts.h index e21b11d60e..073a060242 100644 --- a/features/lwipstack/lwipopts.h +++ b/features/lwipstack/lwipopts.h @@ -25,7 +25,7 @@ #include #endif -// Operating System +// Operating System #define NO_SYS 0 #if MBED_CONF_LWIP_IPV4_ENABLED diff --git a/features/lwipstack/ppp_lwip.cpp b/features/lwipstack/ppp_lwip.cpp index cea781badd..a861267c24 100644 --- a/features/lwipstack/ppp_lwip.cpp +++ b/features/lwipstack/ppp_lwip.cpp @@ -68,7 +68,7 @@ static EventQueue *prepare_event_queue() // Only need to queue 2 events. new blows on failure. event_queue = new EventQueue(2 * EVENTS_EVENT_SIZE, NULL); - event_thread = new Thread(osPriorityNormal, PPP_THREAD_STACK_SIZE); + event_thread = new Thread(osPriorityNormal, PPP_THREAD_STACK_SIZE, NULL, "ppp_lwip"); if (event_thread->start(callback(event_queue, &EventQueue::dispatch_forever)) != osOK) { delete event_thread; @@ -120,7 +120,7 @@ static void ppp_link_status(ppp_pcb *pcb, int err_code, void *ctx) { nsapi_error_t mapped_err_code = NSAPI_ERROR_NO_CONNECTION; - switch(err_code) { + switch (err_code) { case PPPERR_NONE: mapped_err_code = NSAPI_ERROR_OK; tr_info("status_cb: Connected"); @@ -247,7 +247,7 @@ static void ppp_input() fhs.fh = my_stream; fhs.events = POLLIN; poll(&fhs, 1, 0); - if (fhs.revents & (POLLHUP|POLLERR|POLLNVAL)) { + if (fhs.revents & (POLLHUP | POLLERR | POLLNVAL)) { handle_modem_hangup(); return; } @@ -268,7 +268,8 @@ static void ppp_input() return; } -static void stream_cb() { +static void stream_cb() +{ if (my_stream && !event_queued) { event_queued = true; if (event_queue->call(callback(ppp_input)) == 0) { @@ -280,17 +281,17 @@ static void stream_cb() { extern "C" err_t ppp_lwip_connect(void *pcb) { #if PPP_AUTH_SUPPORT - ppp_set_auth(my_ppp_pcb, PPPAUTHTYPE_ANY, login, pwd); + ppp_set_auth(my_ppp_pcb, PPPAUTHTYPE_ANY, login, pwd); #endif //PPP_AUTH_SUPPORT - ppp_active = true; - err_t ret = ppp_connect(my_ppp_pcb, 0); - // lwIP's ppp.txt says input must not be called until after connect - if (ret == ERR_OK) { - my_stream->sigio(callback(stream_cb)); - } else { - ppp_active = false; - } - return ret; + ppp_active = true; + err_t ret = ppp_connect(my_ppp_pcb, 0); + // lwIP's ppp.txt says input must not be called until after connect + if (ret == ERR_OK) { + my_stream->sigio(callback(stream_cb)); + } else { + ppp_active = false; + } + return ret; } extern "C" err_t ppp_lwip_disconnect(void *pcb) @@ -315,7 +316,7 @@ extern "C" nsapi_error_t ppp_lwip_if_init(void *pcb, struct netif *netif, const if (!my_ppp_pcb) { my_ppp_pcb = pppos_create(netif, - ppp_output, ppp_link_status, NULL); + ppp_output, ppp_link_status, NULL); if (!my_ppp_pcb) { return NSAPI_ERROR_DEVICE_ERROR; } diff --git a/features/mbedtls/README.md b/features/mbedtls/README.md index efb1ceace9..96c6a2aa67 100644 --- a/features/mbedtls/README.md +++ b/features/mbedtls/README.md @@ -1,25 +1,93 @@ -README for mbed TLS -=================== +## README for Mbed TLS -mbed TLS for mbed OS --------------------- +### Mbed TLS for Mbed OS -This edition of mbed TLS has been adapted for mbed OS and imported from its standalone release, which you can find on [github here](https://github.com/ARMmbed/mbedtls). This edition of mbed TLS does not include test code, sample applications, or the scripts used in the development of the library. All of these can be found in the standalone release. +This edition of Mbed TLS has been adapted for Mbed OS and imported from its standalone release, which you can find on [GitHub](https://github.com/ARMmbed/mbedtls). This edition of Mbed TLS does not include the test code or scripts used in the development of the library. You can find these in the standalone release. +### Getting started -Getting Help and Support ------------------------- +Several example programs are available that demonstrate Mbed TLS with Mbed OS. These can help you become familiar with the library: -The [mbed TLS website](https://tls.mbed.org/) contains full documentation for the library, including function by function descriptions, knowledgebase articles, blogs and a support forum for questions to the community. +* [**TLS Client:**](https://github.com/ARMmbed/mbed-os-example-tls/tree/master/tls-client) TLS Client demonstrates the use of Mbed TLS to establish a TLS connection to a remote server. +* [**Benchmark:**](https://github.com/ARMmbed/mbed-os-example-tls/tree/master/benchmark) Benchmark measures the time taken to perform basic cryptographic functions used in the library. -Contributing to the Project ---------------------------- +* [**Hashing:**](https://github.com/ARMmbed/mbed-os-example-tls/tree/master/hashing) Hashing demonstrates the various APIs for computing hashes of data (also known as message digests) with SHA-256. -We gratefully accept bug reports and contributions from the community. There are some requirements we need to fulfill in order to be able to integrate contributions: +* [**Authenticated encryption:**](https://github.com/ARMmbed/mbed-os-example-tls/tree/master/authcrypt) Authcrypt demonstrates usage of the cipher API for encrypting and authenticating data with AES-CCM. -- Simple bug fixes to existing code do not contain copyright themselves and we can integrate without issue. The same is true of trivial contributions. -- For larger contributions, such as a new feature, the code can possibly fall under copyright law. We then need your consent to share in the ownership of the copyright. We have a form for this, which we will send to you in case you submit a contribution or pull request that we deem this necessary for. +These examples are fully integrated into Mbed OS. Each of them comes with complete usage instructions as a `README.md` file. -Contributions should be submitted to the [standalone mbed TLS project](https://github.com/ARMmbed/mbedtls), not to the mbed OS imported edition of mbed TLS. +### Configuring Mbed TLS features +With Mbed TLS, you can disable any unneeded features during compilation for a particular project. The default configuration enables widely used features of the TLS protocol, which meets the needs of most projects. It also disables all older and less common features to minimize the code footprint. + +The list of available compilation flags is available in the fully documented [`config.h` file](https://github.com/ARMmbed/mbedtls/blob/development/include/mbedtls/config.h). + +If you need to adjust these flags, you can provide your own supplementary configuration adjustment file with suitable `#define` and `#undef` statements. These are included between the default definitions and the sanity checks. Your configuration file should be in your application's include directory and can be named freely, but you then need to tell Mbed TLS the file's name. To do that, you can use the [Mbed OS configuration system](https://os.mbed.com/docs/latest/reference/configuration.html). + +For example, if you wanted to enable the options `MBEDTLS_PEM_WRITE_C` and `MBEDTLS_CMAC_C` and provide your own additional configuration file for Mbed TLS named `my_config.h`, you could define these in a top level `mbed_app.json` configuration file in the root directory of your project. + +The Mbed TLS configuration file would be specified in the `.json` file as: + +``` +{ + "macros" : [ + + "MBEDTLS_USER_CONFIG_FILE" : "my_config.h", + + "MBEDTLS_PEM_WRITE_C", + "MBEDTLS_CMAC_C" + ] + [remainder of file] +} +``` + +You can then use the additional configuration file `my_config.h` as a normal configuration header file to include or exclude configurations. For example, it could include the following lines to include ECJPAKE, and to disable the CBC block mode: + +``` + #define MBEDTLS_ECJPAKE_C + #define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + + #undef MBEDTLS_CIPHER_MODE_CBC +``` + +You can use this to change any configuration normally in the `config.h` file. + +### Getting Mbed TLS from GitHub + +We maintain and develop Mbed TLS in the open, independently of Mbed OS, and you can find its source on GitHub here: [ARMmbed/mbedtls](https://github.com/ARMmbed/mbedtls). To import a different version of Mbed TLS into an instance of Mbed OS, there is a `Makefile` script to update the local Git repository, extract a specific version and modify the configuration files to Mbed OS defaults. + +To use the `Makefile`, you can either set `MBED_TLS_RELEASE` environment variable to the Git tag or commit ID of the Mbed TLS release or version you want to use, or modify the `Makefile` itself. If `MBED_TLS_RELEASE` is not set, the HEAD of the main development branch will be extracted. + +Run the following commands in the `importer` directory in the Mbed TLS directory: + +``` + make update + make +``` + +The `make update` command pulls the specified version of Mbed TLS into the local `importer/TARGET_IGNORE` directory, and `make` transforms it into the `src` directory, modifying its configuration file as necessary. + +Once these steps are complete, you can build Mbed OS normally with the new version of Mbed TLS. + +### Differences between the standalone and Mbed OS editions + +Although the two editions share the same code base, there are differences, mainly in configuration and integration. Remember these differences if you consult our [knowledge base](https://tls.mbed.org/kb), as the knowledge base articles refer to the standalone edition. + +* The Mbed OS edition has a smaller set of features enabled by default in `config.h`, to reduce footprint. Although the default configuration of the standalone edition puts more emphasis on maintaining interoperability with old peers, the Mbed OS edition only enables the most modern ciphers and the latest version of (D)TLS. + +* The following components of Mbed TLS are disabled in the Mbed OS edition: `net_sockets.c` and `timing.c`. This is because Mbed OS includes its own equivalents. + +### Help and support + +For further documentation and help, you can visit the [Mbed TLS website](https://tls.mbed.org/), which contains full documentation of the library, including function-by-function descriptions, knowledge base articles and blogs. Additionally, you can join our [support forum](https://forums.mbed.com/c/mbed-tls) for questions to the community or to help others. + +### Contributing to the project + +We are happy to accept bug reports and contributions from the community. There are some requirements to integrate contributions: + +* Simple bug fixes to existing code do not contain copyright themselves, and we can integrate without issue. The same is true of trivial contributions. +* For larger contributions, such as a new feature, the code can possibly fall under copyright law. We then need your consent to share in the ownership of the copyright. We have a form for this, which we will send to you if you submit a contribution or pull request that we deem this necessary for. + +Please submit contributions to the [standalone Mbed TLS project](https://github.com/ARMmbed/mbedtls), not to the version of Mbed TLS embedded within Mbed OS. diff --git a/features/mbedtls/importer/adjust-config.sh b/features/mbedtls/importer/adjust-config.sh index b61093e49c..a4cfe005fc 100755 --- a/features/mbedtls/importer/adjust-config.sh +++ b/features/mbedtls/importer/adjust-config.sh @@ -37,38 +37,39 @@ add_code() { # add an #ifndef to include config-no-entropy.h when the target does not have # an entropy source we can use. -add_code \ - "#ifndef MBEDTLS_CONFIG_H\n" \ - "\n" \ - "#include \"platform\/inc\/platform_mbed.h\"\n" \ - "\n" \ - "\/*\n" \ - " * Only use features that do not require an entropy source when\n" \ - " * DEVICE_ENTROPY_SOURCE is not defined in mbed OS.\n" \ - " *\/\n" \ - "#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) && !defined(MBEDTLS_TEST_NULL_ENTROPY)\n" \ - "#include \"mbedtls\/config-no-entropy.h\"\n" \ - "\n" \ - "#if defined(MBEDTLS_USER_CONFIG_FILE)\n" \ - "#include MBEDTLS_USER_CONFIG_FILE\n" \ - "#endif\n" \ - "\n" \ +add_code \ + "#ifndef MBEDTLS_CONFIG_H\n" \ + "\n" \ + "#include \"platform\/inc\/platform_mbed.h\"\n" \ + "\n" \ + "\/*\n" \ + " * Only use features that do not require an entropy source when\n" \ + " * DEVICE_ENTROPY_SOURCE is not defined in mbed OS.\n" \ + " *\/\n" \ + "#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) && !defined(MBEDTLS_TEST_NULL_ENTROPY) && \\\\\n" \ + " !defined(MBEDTLS_ENTROPY_NV_SEED)\n" \ + "#include \"mbedtls\/config-no-entropy.h\"\n" \ + "\n" \ + "#if defined(MBEDTLS_USER_CONFIG_FILE)\n" \ + "#include MBEDTLS_USER_CONFIG_FILE\n" \ + "#endif\n" \ + "\n" \ "#else\n" -add_code \ - "#include \"check_config.h\"\n" \ - "\n" \ - "#endif \/* !MBEDTLS_ENTROPY_HARDWARE_ALT && !MBEDTLS_TEST_NULL_ENTROPY *\/\n" \ - "\n" \ - "#if defined(MBEDTLS_TEST_NULL_ENTROPY)\n" \ - "#warning \"MBEDTLS_TEST_NULL_ENTROPY has been enabled. This \" \\\\\n" \ - " \"configuration is not secure and is not suitable for production use\"\n" \ - "#endif\n" \ - "\n" \ - "#if defined(MBEDTLS_SSL_TLS_C) && !defined(MBEDTLS_TEST_NULL_ENTROPY) && \\\\\n" \ - " !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) && !defined(MBEDTLS_ENTROPY_NV_SEED)\n" \ - "#error \"No entropy source was found at build time, so TLS \" \\\\\n" \ - " \"functionality is not available\"\n" \ +add_code \ + "#include \"check_config.h\"\n" \ + "\n" \ + "#endif \/* !MBEDTLS_ENTROPY_HARDWARE_ALT && !MBEDTLS_TEST_NULL_ENTROPY && !MBEDTLS_ENTROPY_NV_SEED *\/\n" \ + "\n" \ + "#if defined(MBEDTLS_TEST_NULL_ENTROPY)\n" \ + "#warning \"MBEDTLS_TEST_NULL_ENTROPY has been enabled. This \" \\\\\n" \ + " \"configuration is not secure and is not suitable for production use\"\n" \ + "#endif\n" \ + "\n" \ + "#if defined(MBEDTLS_SSL_TLS_C) && !defined(MBEDTLS_TEST_NULL_ENTROPY) && \\\\\n" \ + " !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) && !defined(MBEDTLS_ENTROPY_NV_SEED)\n" \ + "#error \"No entropy source was found at build time, so TLS \" \\\\\n" \ + " \"functionality is not available\"\n" \ "#endif\n" # not supported on mbed OS, nor used by mbed Client diff --git a/features/mbedtls/platform/inc/platform_mbed.h b/features/mbedtls/platform/inc/platform_mbed.h index efb5b6dc11..0da5014e97 100644 --- a/features/mbedtls/platform/inc/platform_mbed.h +++ b/features/mbedtls/platform/inc/platform_mbed.h @@ -25,4 +25,9 @@ #include "mbedtls_device.h" #endif +/* + * MBEDTLS_ERR_PLATFORM_HW_FAILED is deprecated and should not be used. + */ #define MBEDTLS_ERR_PLATFORM_HW_FAILED -0x0080 + +#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 diff --git a/features/mbedtls/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/mbedtls_device.h b/features/mbedtls/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/mbedtls_device.h index dfbc82055e..4fafb6f580 100644 --- a/features/mbedtls/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/mbedtls_device.h +++ b/features/mbedtls/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/mbedtls_device.h @@ -22,8 +22,6 @@ #define MBEDTLS_AES_ALT -#define MBEDTLS_SHA256_ALT - #define MBEDTLS_SHA1_ALT #define MBEDTLS_MD5_ALT diff --git a/features/mbedtls/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/mbedtls_device.h b/features/mbedtls/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/mbedtls_device.h index dfbc82055e..4fafb6f580 100644 --- a/features/mbedtls/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/mbedtls_device.h +++ b/features/mbedtls/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/mbedtls_device.h @@ -22,8 +22,6 @@ #define MBEDTLS_AES_ALT -#define MBEDTLS_SHA256_ALT - #define MBEDTLS_SHA1_ALT #define MBEDTLS_MD5_ALT diff --git a/features/mbedtls/targets/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/mbedtls_device.h b/features/mbedtls/targets/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/mbedtls_device.h index 8382789dfb..ddce19c470 100644 --- a/features/mbedtls/targets/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/mbedtls_device.h +++ b/features/mbedtls/targets/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/mbedtls_device.h @@ -23,8 +23,6 @@ #define MBEDTLS_AES_ALT #define MBEDTLS_SHA1_ALT - -#define MBEDTLS_SHA256_ALT #define MBEDTLS_MD5_ALT #endif /* MBEDTLS_DEVICE_H */ diff --git a/features/nanostack/mbed-mesh-api/mbed-mesh-api/MeshInterfaceNanostack.h b/features/nanostack/mbed-mesh-api/mbed-mesh-api/MeshInterfaceNanostack.h index 91d2bc1222..a4c7f86392 100644 --- a/features/nanostack/mbed-mesh-api/mbed-mesh-api/MeshInterfaceNanostack.h +++ b/features/nanostack/mbed-mesh-api/mbed-mesh-api/MeshInterfaceNanostack.h @@ -51,10 +51,11 @@ protected: NanostackPhy &get_phy() const { return interface_phy; } int8_t interface_id; int8_t _device_id; - Semaphore connect_semaphore; + rtos::Semaphore connect_semaphore; - Callback _connection_status_cb; + mbed::Callback _connection_status_cb; nsapi_connection_status_t _connect_status; + nsapi_connection_status_t _previous_connection_status; bool _blocking; }; diff --git a/features/nanostack/mbed-mesh-api/source/LoWPANNDInterface.cpp b/features/nanostack/mbed-mesh-api/source/LoWPANNDInterface.cpp index b493838f91..712015af9f 100644 --- a/features/nanostack/mbed-mesh-api/source/LoWPANNDInterface.cpp +++ b/features/nanostack/mbed-mesh-api/source/LoWPANNDInterface.cpp @@ -35,7 +35,7 @@ Nanostack::LoWPANNDInterface *LoWPANNDInterface::get_interface() const nsapi_error_t LoWPANNDInterface::do_initialize() { if (!_interface) { - _interface = new (nothrow) Nanostack::LoWPANNDInterface(*_phy); + _interface = new (std::nothrow) Nanostack::LoWPANNDInterface(*_phy); if (!_interface) { return NSAPI_ERROR_NO_MEMORY; } diff --git a/features/nanostack/mbed-mesh-api/source/MeshInterfaceNanostack.cpp b/features/nanostack/mbed-mesh-api/source/MeshInterfaceNanostack.cpp index 6280bf1a39..72702dd2bc 100644 --- a/features/nanostack/mbed-mesh-api/source/MeshInterfaceNanostack.cpp +++ b/features/nanostack/mbed-mesh-api/source/MeshInterfaceNanostack.cpp @@ -69,7 +69,7 @@ void Nanostack::Interface::attach( } Nanostack::Interface::Interface(NanostackPhy &phy) : interface_phy(phy), interface_id(-1), _device_id(-1), - _connect_status(NSAPI_STATUS_DISCONNECTED), _blocking(true) + _connect_status(NSAPI_STATUS_DISCONNECTED), _previous_connection_status(NSAPI_STATUS_DISCONNECTED), _blocking(true) { mesh_system_init(); } @@ -138,15 +138,17 @@ void Nanostack::Interface::network_handler(mesh_connection_status_t status) _connect_status = NSAPI_STATUS_LOCAL_UP; } else if (status == MESH_CONNECTED_GLOBAL) { _connect_status = NSAPI_STATUS_GLOBAL_UP; - } else if (status == MESH_BOOTSTRAP_STARTED) { + } else if (status == MESH_BOOTSTRAP_STARTED || status == MESH_BOOTSTRAP_FAILED) { _connect_status = NSAPI_STATUS_CONNECTING; } else { _connect_status = NSAPI_STATUS_DISCONNECTED; } - if (_connection_status_cb) { + if (_connection_status_cb && _previous_connection_status != _connect_status) { + _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status); } + _previous_connection_status = _connect_status; } nsapi_error_t Nanostack::Interface::register_phy() diff --git a/features/nanostack/mbed-mesh-api/source/NanostackEMACInterface.cpp b/features/nanostack/mbed-mesh-api/source/NanostackEMACInterface.cpp index bbf76e9777..37e047a230 100644 --- a/features/nanostack/mbed-mesh-api/source/NanostackEMACInterface.cpp +++ b/features/nanostack/mbed-mesh-api/source/NanostackEMACInterface.cpp @@ -2,12 +2,11 @@ * Copyright (c) 2017 ARM Limited. All rights reserved. */ -#include "Nanostack.h" #include "NanostackEthernetInterface.h" #include "NanostackEthernetPhy.h" -#include "EMAC.h" #include "nsdynmemLIB.h" #include "arm_hal_phy.h" +#include "EMAC.h" class EMACPhy : public NanostackEthernetPhy { @@ -138,7 +137,7 @@ int8_t EMACPhy::phy_register() phy.phy_tx_done_cb = NULL; emac.set_memory_manager(memory_manager); - emac.set_link_input_cb(callback(this, &EMACPhy::emac_phy_rx)); + emac.set_link_input_cb(mbed::callback(this, &EMACPhy::emac_phy_rx)); if (!emac.power_up()) { return -1; @@ -183,7 +182,7 @@ nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, Nan return NSAPI_ERROR_DEVICE_ERROR; } - single_phy = new (nothrow) EMACPhy(this->memory_manager, emac); + single_phy = new (std::nothrow) EMACPhy(this->memory_manager, emac); if (!single_phy) { return NSAPI_ERROR_NO_MEMORY; } @@ -194,13 +193,14 @@ nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, Nan Nanostack::EthernetInterface *interface; - interface = new (nothrow) Nanostack::EthernetInterface(*single_phy); + interface = new (std::nothrow) Nanostack::EthernetInterface(*single_phy); if (!interface) { return NSAPI_ERROR_NO_MEMORY; } nsapi_error_t err = interface->initialize(); if (err) { + delete interface; return err; } diff --git a/features/nanostack/mbed-mesh-api/source/NanostackEthernetInterface.cpp b/features/nanostack/mbed-mesh-api/source/NanostackEthernetInterface.cpp index 41a00c9eb2..c62297dedb 100644 --- a/features/nanostack/mbed-mesh-api/source/NanostackEthernetInterface.cpp +++ b/features/nanostack/mbed-mesh-api/source/NanostackEthernetInterface.cpp @@ -38,7 +38,7 @@ nsapi_error_t NanostackEthernetInterface::initialize(NanostackEthernetPhy *phy) return NSAPI_ERROR_PARAMETER; } - _interface = new (nothrow) Nanostack::EthernetInterface(*phy); + _interface = new (std::nothrow) Nanostack::EthernetInterface(*phy); if (!_interface) { return NSAPI_ERROR_NO_MEMORY; } diff --git a/features/nanostack/mbed-mesh-api/source/ThreadInterface.cpp b/features/nanostack/mbed-mesh-api/source/ThreadInterface.cpp index 33f2159065..8388f627ea 100644 --- a/features/nanostack/mbed-mesh-api/source/ThreadInterface.cpp +++ b/features/nanostack/mbed-mesh-api/source/ThreadInterface.cpp @@ -79,7 +79,7 @@ Nanostack::ThreadInterface *ThreadInterface::get_interface() const nsapi_error_t ThreadInterface::do_initialize() { if (!_interface) { - _interface = new (nothrow) Nanostack::ThreadInterface(*_phy); + _interface = new (std::nothrow) Nanostack::ThreadInterface(*_phy); if (!_interface) { return NSAPI_ERROR_NO_MEMORY; } diff --git a/features/nanostack/mbed-mesh-api/source/nd_tasklet.c b/features/nanostack/mbed-mesh-api/source/nd_tasklet.c index 8c9c749dfb..28cc6e72f9 100644 --- a/features/nanostack/mbed-mesh-api/source/nd_tasklet.c +++ b/features/nanostack/mbed-mesh-api/source/nd_tasklet.c @@ -185,28 +185,28 @@ void nd_tasklet_parse_network_event(arm_event_s *event) /* Link Layer Active Scan Fail, Stack is Already at Idle state */ tr_debug("Link Layer Scan Fail: No Beacons"); tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; - nd_tasklet_network_state_changed(MESH_DISCONNECTED); + nd_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED); break; case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: /* No ND Router at current Channel Stack is Already at Idle state */ tr_debug("ND Scan/ GP REG fail"); tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; - nd_tasklet_network_state_changed(MESH_DISCONNECTED); + nd_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED); break; case ARM_NWK_NWK_CONNECTION_DOWN: /* Connection to Access point is lost wait for Scan Result */ tr_debug("ND/RPL scan new network"); tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; - nd_tasklet_network_state_changed(MESH_DISCONNECTED); + nd_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED); break; case ARM_NWK_NWK_PARENT_POLL_FAIL: tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; - nd_tasklet_network_state_changed(MESH_DISCONNECTED); + nd_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED); break; case ARM_NWK_AUHTENTICATION_FAIL: tr_debug("Network authentication fail"); tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; - nd_tasklet_network_state_changed(MESH_DISCONNECTED); + nd_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED); break; default: tr_warn("Unknown event %d", status); diff --git a/features/nanostack/mbed-mesh-api/source/thread_tasklet.c b/features/nanostack/mbed-mesh-api/source/thread_tasklet.c index de7a091d14..9668ad6103 100644 --- a/features/nanostack/mbed-mesh-api/source/thread_tasklet.c +++ b/features/nanostack/mbed-mesh-api/source/thread_tasklet.c @@ -189,28 +189,28 @@ void thread_tasklet_parse_network_event(arm_event_s *event) /* Link Layer Active Scan Fail, Stack is Already at Idle state */ tr_debug("Link Layer Scan Fail: No Beacons"); thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; - thread_tasklet_network_state_changed(MESH_DISCONNECTED); + thread_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED); break; case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: /* No ND Router at current Channel Stack is Already at Idle state */ tr_debug("ND Scan/ GP REG fail"); thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; - thread_tasklet_network_state_changed(MESH_DISCONNECTED); + thread_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED); break; case ARM_NWK_NWK_CONNECTION_DOWN: /* Connection to Access point is lost wait for Scan Result */ tr_debug("ND/RPL scan new network"); thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; - thread_tasklet_network_state_changed(MESH_DISCONNECTED); + thread_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED); break; case ARM_NWK_NWK_PARENT_POLL_FAIL: thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; - thread_tasklet_network_state_changed(MESH_DISCONNECTED); + thread_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED); break; case ARM_NWK_AUHTENTICATION_FAIL: tr_debug("Network authentication fail"); thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; - thread_tasklet_network_state_changed(MESH_DISCONNECTED); + thread_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED); break; default: tr_warn("Unknown event %d", status); diff --git a/features/nanostack/nanostack-hal-mbed-cmsis-rtos/arm_hal_fhss_timer.cpp b/features/nanostack/nanostack-hal-mbed-cmsis-rtos/arm_hal_fhss_timer.cpp new file mode 100644 index 0000000000..4cb42af986 --- /dev/null +++ b/features/nanostack/nanostack-hal-mbed-cmsis-rtos/arm_hal_fhss_timer.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2018 ARM Limited. All rights reserved. + * 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. + */ +#include "ns_types.h" +#include "fhss_api.h" +#include "fhss_config.h" +#include "mbed.h" +#include "mbed_trace.h" +#include "platform/arm_hal_interrupt.h" +#include + +#define TRACE_GROUP "fhdr" +#ifndef NUMBER_OF_SIMULTANEOUS_TIMEOUTS +#define NUMBER_OF_SIMULTANEOUS_TIMEOUTS 2 +#endif //NUMBER_OF_SIMULTANEOUS_TIMEOUTS + +using namespace mbed; +using namespace events; + +static Timer timer; +static bool timer_initialized = false; +static const fhss_api_t *fhss_active_handle = NULL; +#if !MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT +static EventQueue *equeue; +#endif + +struct fhss_timeout_s +{ + void (*fhss_timer_callback)(const fhss_api_t *fhss_api, uint16_t); + uint32_t start_time; + uint32_t stop_time; + bool active; + Timeout timeout; +}; + +fhss_timeout_s fhss_timeout[NUMBER_OF_SIMULTANEOUS_TIMEOUTS]; + +static uint32_t read_current_time(void) +{ + return timer.read_us(); +} + +static fhss_timeout_s *find_timeout(void (*callback)(const fhss_api_t *api, uint16_t)) +{ + for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) { + if (fhss_timeout[i].fhss_timer_callback == callback) { + return &fhss_timeout[i]; + } + } + return NULL; +} + +static fhss_timeout_s *allocate_timeout(void) +{ + for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) { + if (fhss_timeout[i].fhss_timer_callback == NULL) { + memset(&fhss_timeout[i], sizeof(fhss_timeout_s), 0); + return &fhss_timeout[i]; + } + } + return NULL; +} + +static void fhss_timeout_handler(void) +{ + for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) { + if (fhss_timeout[i].active && ((fhss_timeout[i].stop_time - fhss_timeout[i].start_time) <= (read_current_time() - fhss_timeout[i].start_time))) { + fhss_timeout[i].active = false; + fhss_timeout[i].fhss_timer_callback(fhss_active_handle, read_current_time() - fhss_timeout[i].stop_time); + } + } +} + +static void timer_callback(void) +{ +#if MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT + fhss_timeout_handler(); +#else + equeue->call(fhss_timeout_handler); +#endif +} + +static int platform_fhss_timer_start(uint32_t slots, void (*callback)(const fhss_api_t *api, uint16_t), const fhss_api_t *callback_param) +{ + int ret_val = -1; + platform_enter_critical(); + if (timer_initialized == false) { +#if !MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT + equeue = mbed_highprio_event_queue(); + MBED_ASSERT(equeue != NULL); +#endif + timer.start(); + timer_initialized = true; + } + fhss_timeout_s *fhss_tim = find_timeout(callback); + if (!fhss_tim) { + fhss_tim = allocate_timeout(); + } + if (!fhss_tim) { + platform_exit_critical(); + tr_error("Failed to allocate timeout"); + return ret_val; + } + fhss_tim->fhss_timer_callback = callback; + fhss_tim->start_time = read_current_time(); + fhss_tim->stop_time = fhss_tim->start_time + slots; + fhss_tim->active = true; + fhss_tim->timeout.attach_us(timer_callback, slots); + fhss_active_handle = callback_param; + ret_val = 0; + platform_exit_critical(); + return ret_val; +} + +static int platform_fhss_timer_stop(void (*callback)(const fhss_api_t *api, uint16_t), const fhss_api_t *api) +{ + (void)api; + platform_enter_critical(); + fhss_timeout_s *fhss_tim = find_timeout(callback); + if (!fhss_tim) { + platform_exit_critical(); + return -1; + } + fhss_tim->timeout.detach(); + fhss_tim->active = false; + platform_exit_critical(); + return 0; +} + +static uint32_t platform_fhss_get_remaining_slots(void (*callback)(const fhss_api_t *api, uint16_t), const fhss_api_t *api) +{ + (void)api; + platform_enter_critical(); + fhss_timeout_s *fhss_tim = find_timeout(callback); + if (!fhss_tim) { + platform_exit_critical(); + return 0; + } + uint32_t remaining_slots = fhss_tim->stop_time - read_current_time(); + platform_exit_critical(); + return remaining_slots; +} + +static uint32_t platform_fhss_timestamp_read(const fhss_api_t *api) +{ + (void)api; + return read_current_time(); +} + +fhss_timer_t fhss_functions = { + .fhss_timer_start = platform_fhss_timer_start, + .fhss_timer_stop = platform_fhss_timer_stop, + .fhss_get_remaining_slots = platform_fhss_get_remaining_slots, + .fhss_get_timestamp = platform_fhss_timestamp_read, + .fhss_resolution_divider = 1 +}; diff --git a/features/nanostack/nanostack-hal-mbed-cmsis-rtos/arm_hal_timer.cpp b/features/nanostack/nanostack-hal-mbed-cmsis-rtos/arm_hal_timer.cpp index d5191f66bf..dbc519196c 100644 --- a/features/nanostack/nanostack-hal-mbed-cmsis-rtos/arm_hal_timer.cpp +++ b/features/nanostack/nanostack-hal-mbed-cmsis-rtos/arm_hal_timer.cpp @@ -17,11 +17,17 @@ // Include before mbed.h to properly get UINT*_C() #include "ns_types.h" -#include "mbed.h" #include "platform/SingletonPtr.h" #include "platform/arm_hal_timer.h" #include "platform/arm_hal_interrupt.h" -#include +#include "platform/mbed_assert.h" +#include "Timeout.h" +#include "Timer.h" +#include "events/Event.h" +#include "events/mbed_shared_queues.h" + +using namespace mbed; +using namespace events; static SingletonPtr timer; static SingletonPtr timeout; @@ -45,8 +51,8 @@ void platform_timer_enable(void) equeue = mbed_highprio_event_queue(); MBED_ASSERT(equeue != NULL); #endif - // Prime the SingletonPtrs - can't construct from IRQ/critical section - timer.get(); + timer->start(); + // Prime the SingletonPtr - can't construct from IRQ/critical section timeout.get(); } diff --git a/features/nanostack/nanostack-interface/Nanostack.cpp b/features/nanostack/nanostack-interface/Nanostack.cpp index c76a567d31..cddb054d34 100644 --- a/features/nanostack/nanostack-interface/Nanostack.cpp +++ b/features/nanostack/nanostack-interface/Nanostack.cpp @@ -17,8 +17,6 @@ /* Nanostack implementation of NetworkSocketAPI */ -#include "mbed.h" -#include "rtos.h" #include "Nanostack.h" #include "NanostackLockGuard.h" diff --git a/features/nanostack/nanostack-interface/Nanostack.h b/features/nanostack/nanostack-interface/Nanostack.h index 8bc3fb2c97..b2607cc70b 100644 --- a/features/nanostack/nanostack-interface/Nanostack.h +++ b/features/nanostack/nanostack-interface/Nanostack.h @@ -18,7 +18,6 @@ #ifndef NANOSTACK_H_ #define NANOSTACK_H_ -#include "mbed.h" #include "OnboardNetworkStack.h" #include "NanostackMemoryManager.h" #include "MeshInterface.h" diff --git a/features/nanostack/targets/TARGET_NCS36510/NanostackRfPhyNcs36510.cpp b/features/nanostack/targets/TARGET_NCS36510/NanostackRfPhyNcs36510.cpp index b7179ce297..f88b2ca2db 100644 --- a/features/nanostack/targets/TARGET_NCS36510/NanostackRfPhyNcs36510.cpp +++ b/features/nanostack/targets/TARGET_NCS36510/NanostackRfPhyNcs36510.cpp @@ -157,13 +157,10 @@ static phy_device_driver_s device_driver = { static void rf_thread_loop() { for (;;) { - osEvent event = rf_thread.signal_wait(0); - if (event.status != osEventSignal) { - continue; - } + uint32_t flags = ThisThread::flags_wait_any(0x7FFFFFFF); platform_enter_critical(); - if (event.value.signals & SIGNAL_COUNT_RADIO) { + if (flags & SIGNAL_COUNT_RADIO) { handle_IRQ_events(); } platform_exit_critical(); @@ -806,7 +803,7 @@ static void rf_mac_tx_interrupt(void) extern "C" void fIrqMacHwHandler(void) { NVIC_DisableIRQ(MacHw_IRQn); - rf_thread.signal_set(SIGNAL_COUNT_RADIO); + rf_thread.flags_set(SIGNAL_COUNT_RADIO); } static void handle_IRQ_events(void) diff --git a/features/netsocket/CellularBase.h b/features/netsocket/CellularBase.h index 348324020b..270b0fde6e 100644 --- a/features/netsocket/CellularBase.h +++ b/features/netsocket/CellularBase.h @@ -18,115 +18,114 @@ #include "netsocket/NetworkInterface.h" -/** CellularBase class - * - * Common interface that is shared between Cellular interfaces +/** Common interface that is shared between cellular interfaces. + * @addtogroup netsocket */ class CellularBase: public NetworkInterface { public: - - /** Get the default Cellular interface. + /** Get the default cellular interface. * * This is provided as a weak method so applications can override. - * Default behaviour is to get the target's default interface, if + * Default behavior is to get the target's default interface, if * any. * - * @return pointer to interface, if any + * @return pointer to interface, if any. */ - static CellularBase *get_default_instance(); - /** Set the Cellular network credentials + /** Set the cellular network credentials. * - * Please check documentation of connect() for default behaviour of APN settings. + * Please check documentation of connect() for default behavior of APN settings. * - * @param apn Access point name - * @param uname optionally, Username - * @param pwd optionally, password + * @param apn Access point name. + * @param uname Username (optional). + * @param pwd Password (optional). */ virtual void set_credentials(const char *apn, const char *uname = 0, const char *pwd = 0) = 0; - /** Set the pin code for SIM card + /** Set the PIN code for SIM card. * - * @param sim_pin PIN for the SIM card + * @param sim_pin PIN for the SIM card. */ virtual void set_sim_pin(const char *sim_pin) = 0; - /** Start the interface + /** Attempt to connect to a cellular network with a PIN and credentials. * - * Attempts to connect to a Cellular network. - * - * @param sim_pin PIN for the SIM card - * @param apn optionally, access point name - * @param uname optionally, Username - * @param pwd optionally, password - * @return NSAPI_ERROR_OK on success, or negative error code on failure + * @param sim_pin PIN for the SIM card. + * @param apn Access point name (optional). + * @param uname Username (optional). + * @param pwd Password (optional). + * @return NSAPI_ERROR_OK on success, or negative error code on failure. */ virtual nsapi_error_t connect(const char *sim_pin, const char *apn = 0, const char *uname = 0, const char *pwd = 0) = 0; - /** Start the interface + /** Attempt to connect to a cellular network. * - * Attempts to connect to a Cellular network. - * If the SIM requires a PIN, and it is not set/invalid, NSAPI_ERROR_AUTH_ERROR is returned. + * If the SIM requires a PIN, and it is invalid or not set, NSAPI_ERROR_AUTH_ERROR is returned. * - * @return NSAPI_ERROR_OK on success, or negative error code on failure + * @return NSAPI_ERROR_OK on success, or negative error code on failure. */ virtual nsapi_error_t connect() = 0; - /** Stop the interface + /** Stop the interface. * - * @return 0 on success, or error code on failure + * @return NSAPI_ERROR_OK on success, or error code on failure. */ virtual nsapi_error_t disconnect() = 0; - /** Check if the connection is currently established or not + /** Check if the connection is currently established. * - * @return true/false If the cellular module have successfully acquired a carrier and is - * connected to an external packet data network using PPP, isConnected() - * API returns true and false otherwise. + * @return `true` if the cellular module have successfully acquired a carrier and is + * connected to an external packet data network using PPP, `false` otherwise. */ virtual bool is_connected() = 0; - /** Get the local IP address + /** Get the local IP address. * - * @return Null-terminated representation of the local IP address - * or null if no IP address has been received + * @return Null-terminated representation of the local IP address, + * or null if no IP address has been received. */ virtual const char *get_ip_address() = 0; - /** Get the local network mask + /** Get the local network mask. * - * @return Null-terminated representation of the local network mask - * or null if no network mask has been received + * @return Null-terminated representation of the local network mask, + * or null if no network mask has been received. */ virtual const char *get_netmask() = 0; - /** Get the local gateways + /** Get the local gateways. * - * @return Null-terminated representation of the local gateway - * or null if no network mask has been received + * @return Null-terminated representation of the local gateway, + * or null if no network mask has been received. */ virtual const char *get_gateway() = 0; + /** @copydoc NetworkInterface::cellularBase + */ virtual CellularBase *cellularBase() { return this; } +#if !defined(DOXYGEN_ONLY) + protected: - /** Get the target's default Cellular interface. + /** Get the target's default cellular interface. * * This is provided as a weak method so targets can override. The - * default implementation configures and returns the OnBoardModemInterface + * default implementation configures and returns the OnBoardModemInterface, * if available. * - * @return pointer to interface, if any + * @return Pointer to interface, if any. */ static CellularBase *get_target_default_instance(); + +#endif //!defined(DOXYGEN_ONLY) }; #endif //CELLULAR_BASE_H diff --git a/features/netsocket/DNS.h b/features/netsocket/DNS.h index 9e74744b6b..bdfa69705f 100644 --- a/features/netsocket/DNS.h +++ b/features/netsocket/DNS.h @@ -20,7 +20,7 @@ class DNS { public: - /** Translates a hostname to an IP address with specific version + /** Translate a hostname to an IP address with specific version. * * The hostname may be either a domain name or an IP address. If the * hostname is an IP address, no network transactions will be performed. @@ -28,18 +28,18 @@ public: * If no stack-specific DNS resolution is provided, the hostname * will be resolve using a UDP socket on the stack. * - * @param host Hostname to resolve - * @param address Destination for the host SocketAddress + * @param host Hostname to resolve. + * @param address Pointer to a SocketAddress to store the result. * @param version IP version of address to resolve, NSAPI_UNSPEC indicates - * version is chosen by the stack (defaults to NSAPI_UNSPEC) - * @return 0 on success, negative error code on failure + * version is chosen by the stack (defaults to NSAPI_UNSPEC). + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t gethostbyname(const char *host, SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC) = 0; - /** Hostname translation callback (asynchronous) + /** Hostname translation callback for gethostbyname_async. * - * Callback will be called after DNS resolution completes or a failure occurs. + * The callback is called after DNS resolution completes, or a failure occurs. * * Callback should not take more than 10ms to execute, otherwise it might * prevent underlying thread processing. A portable user of the callback @@ -47,49 +47,49 @@ public: * The callback should not perform expensive operations such as socket recv/send * calls or blocking operations. * - * @param status 0 on success, negative error code on failure - * @param address On success, destination for the host SocketAddress + * @param result NSAPI_ERROR_OK on success, negative error code on failure. + * @param address On success, destination for the host SocketAddress. */ typedef mbed::Callback hostbyname_cb_t; - /** Translates a hostname to an IP address (asynchronous) + /** Translate a hostname to an IP address (asynchronous). * * The hostname may be either a domain name or an IP address. If the * hostname is an IP address, no network transactions will be performed. * * If no stack-specific DNS resolution is provided, the hostname - * will be resolve using a UDP socket on the stack. + * will be resolved using a UDP socket on the stack. * - * Call is non-blocking. Result of the DNS operation is returned by the callback. - * If this function returns failure, callback will not be called. In case result - * is success (IP address was found from DNS cache), callback will be called - * before function returns. + * The call is non-blocking. The result of the DNS operation is returned by the callback. + * If this function returns failure, the callback will not be called. If it is successful, + * (the IP address was found from the DNS cache), the callback will be called + * before the function returns. * - * @param host Hostname to resolve - * @param callback Callback that is called for result - * @param version IP version of address to resolve, NSAPI_UNSPEC indicates - * version is chosen by the stack (defaults to NSAPI_UNSPEC) - * @return 0 on immediate success, + * @param host Hostname to resolve. + * @param callback Callback that is called to return the result. + * @param version IP version of address to resolve. NSAPI_UNSPEC indicates that the + * version is chosen by the stack (defaults to NSAPI_UNSPEC). + * @return NSAPI_ERROR_OK on immediate success, * negative error code on immediate failure or - * a positive unique id that represents the hostname translation operation - * and can be passed to cancel + * a positive unique ID that represents the hostname translation operation + * and can be passed to cancel. */ virtual nsapi_value_or_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback, nsapi_version_t version = NSAPI_UNSPEC) = 0; - /** Cancels asynchronous hostname translation + /** Cancel asynchronous hostname translation. * - * When translation is cancelled, callback will not be called. + * When translation is canceled, callback is not called. * - * @param id Unique id of the hostname translation operation - * @return 0 on success, negative error code on failure + * @param id Unique ID of the hostname translation operation returned by gethostbyname_async. + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t gethostbyname_async_cancel(int id) = 0; - /** Add a domain name server to list of servers to query + /** Add a domain name server to list of servers to query. * - * @param address Destination for the host address - * @return 0 on success, negative error code on failure + * @param address DNS server host address. + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t add_dns_server(const SocketAddress &address) = 0; }; diff --git a/features/netsocket/EMAC.h b/features/netsocket/EMAC.h index 27ced11e72..d59c267e1f 100644 --- a/features/netsocket/EMAC.h +++ b/features/netsocket/EMAC.h @@ -26,7 +26,7 @@ /** * This interface should be used to abstract low level access to networking hardware - * All operations receive a `void *` hw pointer which an emac device provides when + * All operations receive a `void *` hardware pointer which an EMAC device provides when * it is registered with a stack. */ class EMAC { @@ -40,7 +40,7 @@ public: static EMAC &get_default_instance(); /** - * Callback to be register with Emac interface and to be called for received packets + * Callback to be register with EMAC interface and to be called for received packets * * @param buf Received data */ @@ -48,7 +48,7 @@ public: typedef mbed::Callback emac_link_input_cb_t; /** - * Callback to be register with Emac interface and to be called for link status changes + * Callback to be register with EMAC interface and to be called for link status changes * * @param up Link status */ @@ -65,7 +65,7 @@ public: /** * Gets memory buffer alignment preference * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * Gets preferred memory buffer alignment of the EMAC device. IP stack may or may not * align link out memory buffer chains using the alignment. * * @return Memory alignment requirement in bytes @@ -107,7 +107,7 @@ public: * Provided address has to be of correct size, see @a get_hwaddr_size * * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test + * the stack would normally use that, but it could be overridden, for example for test * purposes. * * @param addr Address to be set @@ -179,7 +179,7 @@ public: /** These need to be defined by targets wishing to provide an Ethernet driver using EMAC interface. It will - * be used by the EMACInterface class's default constructor to initialise the networking subsystem. + * be used by the EMACInterface class's default constructor to initialize the networking subsystem. */ //extern const emac_interface_ops_t mbed_emac_eth_ops_default; //extern void *mbed_emac_eth_hw_default; diff --git a/features/netsocket/EMACInterface.cpp b/features/netsocket/EMACInterface.cpp index c864ed881e..c88d9b461f 100644 --- a/features/netsocket/EMACInterface.cpp +++ b/features/netsocket/EMACInterface.cpp @@ -15,6 +15,7 @@ */ #include "EMACInterface.h" +using namespace mbed; /* Interface implementation */ EMACInterface::EMACInterface(EMAC &emac, OnboardNetworkStack &stack) : @@ -117,7 +118,7 @@ NetworkStack *EMACInterface::get_stack() } void EMACInterface::attach( - Callback status_cb) + mbed::Callback status_cb) { _connection_status_cb = status_cb; if (_interface) { diff --git a/features/netsocket/EMACInterface.h b/features/netsocket/EMACInterface.h index 8db5da5c1b..6d9d981ad4 100644 --- a/features/netsocket/EMACInterface.h +++ b/features/netsocket/EMACInterface.h @@ -18,7 +18,6 @@ #define EMAC_INTERFACE_H #include "nsapi.h" -#include "rtos.h" #include "EMAC.h" #include "OnboardNetworkStack.h" @@ -33,7 +32,7 @@ * Drivers derived from EMACInterface should be constructed so that their * EMAC is functional without the need to call `connect()`. For example * a Wi-Fi driver should permit `WiFi::get_emac().power_up()` as soon as - * the credentials have been set. This is necessary to support specialised + * the credentials have been set. This is necessary to support specialized * applications such as 6LoWPAN mesh border routers. */ class EMACInterface : public virtual NetworkInterface { @@ -100,21 +99,21 @@ public: /** Get the local IP address * * @return Null-terminated representation of the local IP address - * or null if no IP address has been recieved + * or null if no IP address has been received */ virtual const char *get_ip_address(); /** Get the local network mask * * @return Null-terminated representation of the local network mask - * or null if no network mask has been recieved + * or null if no network mask has been received */ virtual const char *get_netmask(); /** Get the local gateways * * @return Null-terminated representation of the local gateway - * or null if no network mask has been recieved + * or null if no network mask has been received */ virtual const char *get_gateway(); @@ -171,7 +170,7 @@ protected: char _ip_address[NSAPI_IPv6_SIZE]; char _netmask[NSAPI_IPv4_SIZE]; char _gateway[NSAPI_IPv4_SIZE]; - Callback _connection_status_cb; + mbed::Callback _connection_status_cb; }; #endif diff --git a/features/netsocket/EthInterface.h b/features/netsocket/EthInterface.h index ed7a0de818..0e856c99f6 100644 --- a/features/netsocket/EthInterface.h +++ b/features/netsocket/EthInterface.h @@ -23,13 +23,13 @@ #include "netsocket/NetworkInterface.h" -/** EthInterface class - * - * Common interface that is shared between ethernet hardware. +/** Common interface that is shared between Ethernet hardware. */ class EthInterface : public virtual NetworkInterface { public: + /** @copydoc NetworkInterface::ethInterface + */ virtual EthInterface *ethInterface() { return this; @@ -38,13 +38,14 @@ public: /** Get the default Ethernet interface. * * This is provided as a weak method so applications can override. - * Default behaviour is to get the target's default interface, if + * Default behavior is to get the target's default interface, if * any. * - * @return pointer to interface, if any + * @return Pointer to interface, if one exists. */ static EthInterface *get_default_instance(); +#if !defined(DOXYGEN_ONLY) protected: /** Get the target's default Ethernet interface. @@ -53,9 +54,10 @@ protected: * default implementation will invoke EthernetInterface with the * default EMAC and default network stack, if DEVICE_EMAC is set. * - * @return pointer to interface, if any + * @return Pointer to interface, if one exists. */ static EthInterface *get_target_default_instance(); +#endif //!defined(DOXYGEN_ONLY) }; diff --git a/features/netsocket/EthernetInterface.h b/features/netsocket/EthernetInterface.h index 2c8d6a8aff..08b158dd49 100644 --- a/features/netsocket/EthernetInterface.h +++ b/features/netsocket/EthernetInterface.h @@ -18,16 +18,14 @@ #define ETHERNET_INTERFACE_H #include "nsapi.h" -#include "rtos.h" #include "EMACInterface.h" -/** EthernetInterface class - * Implementation of the NetworkStack for an EMAC-based Ethernet driver +/** Implementation of the NetworkStack for an EMAC-based Ethernet driver. */ class EthernetInterface : public EMACInterface, public EthInterface { public: - /** Create an EMAC-based ethernet interface. + /** Create an EMAC-based Ethernet interface. * * The default arguments obtain the default EMAC, which will be target- * dependent (and the target may have some JSON option to choose which @@ -37,8 +35,8 @@ public: * Due to inability to return errors from the constructor, no real * work is done until the first call to connect(). * - * @param emac Reference to EMAC to use - * @param stack Reference to onboard-network stack to use + * @param emac Reference to EMAC to use. + * @param stack Reference to onboard-network stack to use. */ EthernetInterface(EMAC &emac = EMAC::get_default_instance(), OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance()) : EMACInterface(emac, stack) { } diff --git a/features/netsocket/InternetSocket.cpp b/features/netsocket/InternetSocket.cpp index 948e25374a..a114b6bbf9 100644 --- a/features/netsocket/InternetSocket.cpp +++ b/features/netsocket/InternetSocket.cpp @@ -26,6 +26,11 @@ InternetSocket::InternetSocket() { } +InternetSocket::~InternetSocket() +{ + close(); +} + nsapi_error_t InternetSocket::open(NetworkStack *stack) { _lock.lock(); @@ -56,13 +61,17 @@ nsapi_error_t InternetSocket::close() _lock.lock(); nsapi_error_t ret = NSAPI_ERROR_OK; - if (_socket) { - _stack->socket_attach(_socket, 0, 0); - nsapi_socket_t socket = _socket; - _socket = 0; - ret = _stack->socket_close(socket); + if (!_socket) { + _lock.unlock(); + return NSAPI_ERROR_NO_SOCKET; } - _stack = 0; + + // Just in case - tell the stack not to callback any more, then remove this socket. + _stack->socket_attach(_socket, 0, 0); + nsapi_socket_t socket = _socket; + _socket = 0; + ret = _stack->socket_close(socket); + _stack = 0; // Invalidate the stack pointer - otherwise open() fails. // Wakeup anything in a blocking operation // on this socket @@ -77,7 +86,7 @@ nsapi_error_t InternetSocket::close() _lock.unlock(); - // When allocated by accept() call, will self desctruct on close(); + // When allocated by accept() call, will destroy itself on close(); if (_factory_allocated) { delete this; } diff --git a/features/netsocket/InternetSocket.h b/features/netsocket/InternetSocket.h index 511ff34b24..b4681cb596 100644 --- a/features/netsocket/InternetSocket.h +++ b/features/netsocket/InternetSocket.h @@ -32,176 +32,104 @@ */ class InternetSocket : public Socket { public: - /** Destroy a socket + /** Destroy the socket. * - * Closes socket if the socket is still open + * @note Closes socket if it's still open. */ - virtual ~InternetSocket() {} + virtual ~InternetSocket(); - /** Opens a socket + /** Open a network socket on the network stack of the given + * network interface. * - * Creates a network socket on the network stack of the given - * network interface. Not needed if stack is passed to the - * socket's constructor. + * @note Not needed if stack is passed to the socket's constructor. * - * @param stack Network stack as target for socket - * @return 0 on success, negative error code on failure + * @param stack Network stack as target for socket. + * @return 0 on success, negative error code on failure (@see nsapi_types.h). */ nsapi_error_t open(NetworkStack *stack); +#if !defined(DOXYGEN_ONLY) template nsapi_error_t open(S *stack) { return open(nsapi_create_stack(stack)); } +#endif //!defined(DOXYGEN_ONLY) - /** Close the socket - * - * Closes any open connection and deallocates any memory associated + /** Close any open connection, and deallocate any memory associated * with the socket. Called from destructor if socket is not closed. * - * @return 0 on success, negative error code on failure + * @return 0 on success, negative error code on failure (@see nsapi_types.h). */ virtual nsapi_error_t close(); - /** Subscribes to an IP multicast group + /** Subscribe to an IP multicast group. * - * @param address Multicast group IP address - * @return Negative error code on failure + * @param address Multicast group IP address. + * @return 0 on success, negative error code on failure (@see nsapi_types.h). */ int join_multicast_group(const SocketAddress &address); - /** Leave an IP multicast group + /** Leave an IP multicast group. * - * @param address Multicast group IP address - * @return Negative error code on failure + * @param address Multicast group IP address. + * @return 0 on success, negative error code on failure (@see nsapi_types.h). */ int leave_multicast_group(const SocketAddress &address); - - /** Bind a specific address to a socket + /** Bind the socket to a port on which to receive data. * - * Binding a socket specifies the address and port on which to receive - * data. - * - * @param port Local port to bind - * @return 0 on success, negative error code on failure. + * @param port Local port to bind. + * @return 0 on success, negative error code on failure (@see nsapi_types.h). */ nsapi_error_t bind(uint16_t port); - /** Bind a specific address to a socket - * - * Binding a socket specifies the address and port on which to receive + /** Bind the socket to a specific address and port on which to receive * data. If the IP address is zeroed, only the port is bound. * - * @param address Null-terminated local address to bind - * @param port Local port to bind - * @return 0 on success, negative error code on failure. + * @param address Null-terminated local address to bind. + * @param port Local port to bind. + * @return 0 on success, negative error code on failure (@see nsapi_types.h). */ nsapi_error_t bind(const char *address, uint16_t port); - /** Bind a specific address to a socket - * - * Binding a socket specifies the address and port on which to receive - * data. If the IP address is zeroed, only the port is bound. - * - * @param address Local address to bind - * @return 0 on success, negative error code on failure. + /** @copydoc Socket::bind */ virtual nsapi_error_t bind(const SocketAddress &address); - /** Set blocking or non-blocking mode of the socket - * - * Initially all sockets are in blocking mode. In non-blocking mode - * blocking operations such as send/recv/accept return - * NSAPI_ERROR_WOULD_BLOCK if they can not continue. - * - * set_blocking(false) is equivalent to set_timeout(-1) - * set_blocking(true) is equivalent to set_timeout(0) - * - * @param blocking true for blocking mode, false for non-blocking mode. + /** @copydoc Socket::set_blocking */ virtual void set_blocking(bool blocking); - /** Set timeout on blocking socket operations - * - * Initially all sockets have unbounded timeouts. NSAPI_ERROR_WOULD_BLOCK - * is returned if a blocking operation takes longer than the specified - * timeout. A timeout of 0 removes the timeout from the socket. A negative - * value give the socket an unbounded timeout. - * - * set_timeout(0) is equivalent to set_blocking(false) - * set_timeout(-1) is equivalent to set_blocking(true) - * - * @param timeout Timeout in milliseconds + /** @copydoc Socket::set_timeout */ virtual void set_timeout(int timeout); - /* Set socket options - * - * setsockopt allows an application to pass stack-specific options - * to the underlying stack using stack-specific level and option names, - * or to request generic options using levels from nsapi_socket_level_t. - * - * For unsupported options, NSAPI_ERROR_UNSUPPORTED is returned - * and the socket is unmodified. - * - * @param level Stack-specific protocol level or nsapi_socket_level_t - * @param optname Level-specific option name - * @param optval Option value - * @param optlen Length of the option value - * @return 0 on success, negative error code on failure + /** @copydoc Socket::setsockopt */ virtual nsapi_error_t setsockopt(int level, int optname, const void *optval, unsigned optlen); - /* Get socket options - * - * getsockopt allows an application to retrieve stack-specific options - * from the underlying stack using stack-specific level and option names, - * or to request generic options using levels from nsapi_socket_level_t. - * - * For unsupported options, NSAPI_ERROR_UNSUPPORTED is returned - * and the socket is unmodified. - * - * @param level Stack-specific protocol level or nsapi_socket_level_t - * @param optname Level-specific option name - * @param optval Destination for option value - * @param optlen Length of the option value - * @return 0 on success, negative error code on failure + /** @copydoc Socket::getsockopt */ virtual nsapi_error_t getsockopt(int level, int optname, void *optval, unsigned *optlen); - /** Register a callback on state change of the socket - * - * The specified callback will be called on state changes such as when - * the socket can recv/send/accept successfully and on when an error - * occurs. The callback may also be called spuriously without reason. - * - * The callback may be called in an interrupt context and should not - * perform expensive operations such as recv/send calls. - * - * Note! This is not intended as a replacement for a poll or attach-like - * asynchronous api, but rather as a building block for constructing - * such functionality. The exact timing of when the registered function - * is called is not guaranteed and susceptible to change. - * - * @param func Function to call on state change + /** @copydoc Socket::sigio */ virtual void sigio(mbed::Callback func); - /** Register a callback on state change of the socket + /** Register a callback on state change of the socket. * * @see Socket::sigio * @deprecated - * The behaviour of Socket::attach differs from other attach functions in - * mbed OS and has been known to cause confusion. Replaced by Socket::sigio. + * The behavior of Socket::attach differs from other attach functions in + * Mbed OS and has been known to cause confusion. Replaced by Socket::sigio. */ MBED_DEPRECATED_SINCE("mbed-os-5.4", - "The behaviour of Socket::attach differs from other attach functions in " - "mbed OS and has been known to cause confusion. Replaced by Socket::sigio.") + "The behavior of Socket::attach differs from other attach functions in " + "Mbed OS and has been known to cause confusion. Replaced by Socket::sigio.") void attach(mbed::Callback func); - /** Register a callback on state change of the socket + /** Register a callback on state change of the socket. * * @see Socket::sigio * @deprecated @@ -217,6 +145,8 @@ public: attach(mbed::callback(obj, method)); } +#if !defined(DOXYGEN_ONLY) + protected: InternetSocket(); virtual nsapi_protocol_t get_proto() = 0; @@ -240,6 +170,8 @@ protected: static const int READ_FLAG = 0x1u; static const int WRITE_FLAG = 0x2u; static const int FINISHED_FLAG = 0x3u; + +#endif //!defined(DOXYGEN_ONLY) }; #endif // INTERNETSOCKET_H diff --git a/features/netsocket/MeshInterface.h b/features/netsocket/MeshInterface.h index e6f4efb673..cd1c7af346 100644 --- a/features/netsocket/MeshInterface.h +++ b/features/netsocket/MeshInterface.h @@ -23,13 +23,12 @@ #include "netsocket/NetworkInterface.h" -/** MeshInterface class - * - * Common interface that is shared between mesh hardware +/** Common interface that is shared between mesh hardware */ class MeshInterface : public virtual NetworkInterface { public: - + /** @copydoc NetworkInterface::meshInterface + */ virtual MeshInterface *meshInterface() { return this; @@ -38,13 +37,14 @@ public: /** Get the default Mesh interface. * * This is provided as a weak method so applications can override. - * Default behaviour is to get the target's default interface, if + * Default behavior is to get the target's default interface, if * any. * - * @return pointer to interface, if any + * @return pointer to interface, if any. */ static MeshInterface *get_default_instance(); +#if !defined(DOXYGEN_ONLY) protected: /** Get the target's default Mesh interface. @@ -53,9 +53,10 @@ protected: * default implementation will invoke LoWPANNDInterface or ThreadInterface * with the default NanostackRfPhy. * - * @return pointer to interface, if any + * @return pointer to interface, if any. */ static MeshInterface *get_target_default_instance(); +#endif //!defined(DOXYGEN_ONLY) }; diff --git a/features/netsocket/NetworkInterface.h b/features/netsocket/NetworkInterface.h index 7eb674df13..6338dbaa62 100644 --- a/features/netsocket/NetworkInterface.h +++ b/features/netsocket/NetworkInterface.h @@ -31,25 +31,26 @@ class MeshInterface; class CellularBase; class EMACInterface; -/** NetworkInterface class +/** Common interface that is shared between network devices. * - * Common interface that is shared between network devices - * @addtogroup netsocket + * @\addtogroup netsocket + * @{ */ class NetworkInterface: public DNS { public: virtual ~NetworkInterface() {}; - /** Return the default network interface + /** Return the default network interface. * * Returns the default network interface, as determined by JSON option * target.network-default-interface-type or other overrides. * - * The type of the interface returned can be tested via the ethInterface() - * etc downcasts. + * The type of the interface returned can be tested by calling ethInterface(), + * wifiInterface(), meshInterface(), cellularBase(), emacInterface() and checking + * for NULL pointers. * - * The default behaviour is to return the default interface for the + * The default behavior is to return the default interface for the * interface type specified by target.network-default-interface-type. Targets * should set this in their targets.json to guide default selection, * and applications may override. @@ -79,75 +80,72 @@ public: */ static NetworkInterface *get_default_instance(); - /** Get the local MAC address + /** Get the local MAC address. * * Provided MAC address is intended for info or debug purposes and - * may not be provided if the underlying network interface does not - * provide a MAC address + * may be not provided if the underlying network interface does not + * provide a MAC address. * * @return Null-terminated representation of the local MAC address - * or null if no MAC address is available + * or null if no MAC address is available. */ virtual const char *get_mac_address(); - /** Get the local IP address + /** Get the local IP address. * * @return Null-terminated representation of the local IP address - * or null if no IP address has been received + * or null if no IP address has been received. */ virtual const char *get_ip_address(); - /** Get the local network mask + /** Get the local network mask. * * @return Null-terminated representation of the local network mask - * or null if no network mask has been received + * or null if no network mask has been received. */ virtual const char *get_netmask(); - /** Get the local gateway + /** Get the local gateway. * * @return Null-terminated representation of the local gateway - * or null if no network mask has been received + * or null if no network mask has been received. */ virtual const char *get_gateway(); - /** Set a static IP address - * - * Configures this network interface to use a static IP address. + /** Configure this network interface to use a static IP address. * Implicitly disables DHCP, which can be enabled in set_dhcp. * Requires that the network is disconnected. * * @param ip_address Null-terminated representation of the local IP address * @param netmask Null-terminated representation of the local network mask * @param gateway Null-terminated representation of the local gateway - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t set_network(const char *ip_address, const char *netmask, const char *gateway); - /** Enable or disable DHCP on the network + /** Enable or disable DHCP on connecting the network. * - * Enables DHCP on connecting the network. Defaults to enabled unless - * a static IP address has been assigned. Requires that the network is - * disconnected. + * Enabled by default unless a static IP address has been assigned. Requires + * that the network is disconnected. * - * @param dhcp True to enable DHCP - * @return 0 on success, negative error code on failure + * @param dhcp True to enable DHCP. + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t set_dhcp(bool dhcp); - /** Start the interface + /** Start the interface. * - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t connect() = 0; - /** Stop the interface + /** Stop the interface. * - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t disconnect() = 0; - /** Translates a hostname to an IP address with specific version + /** Translate a hostname to an IP address with specific version. * * The hostname may be either a domain name or an IP address. If the * hostname is an IP address, no network transactions will be performed. @@ -155,33 +153,33 @@ public: * If no stack-specific DNS resolution is provided, the hostname * will be resolve using a UDP socket on the stack. * - * @param host Hostname to resolve - * @param address Destination for the host SocketAddress + * @param host Hostname to resolve. + * @param address Pointer to a SocketAddress to store the result. * @param version IP version of address to resolve, NSAPI_UNSPEC indicates - * version is chosen by the stack (defaults to NSAPI_UNSPEC) - * @return 0 on success, negative error code on failure + * version is chosen by the stack (defaults to NSAPI_UNSPEC). + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t gethostbyname(const char *host, SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC); - /** Hostname translation callback (asynchronous) + /** Hostname translation callback (for use with gethostbyname_async()). * * Callback will be called after DNS resolution completes or a failure occurs. * - * Callback should not take more than 10ms to execute, otherwise it might + * @note Callback should not take more than 10ms to execute, otherwise it might * prevent underlying thread processing. A portable user of the callback * should not make calls to network operations due to stack size limitations. * The callback should not perform expensive operations such as socket recv/send * calls or blocking operations. * - * @param status 0 on success, negative error code on failure - * @param address On success, destination for the host SocketAddress + * @param result NSAPI_ERROR_OK on success, negative error code on failure. + * @param address On success, destination for the host SocketAddress. */ typedef mbed::Callback hostbyname_cb_t; - /** Translates a hostname to an IP address (asynchronous) + /** Translate a hostname to an IP address (asynchronous). * - * The hostname may be either a domain name or an IP address. If the + * The hostname may be either a domain name or a dotted IP address. If the * hostname is an IP address, no network transactions will be performed. * * If no stack-specific DNS resolution is provided, the hostname @@ -192,87 +190,100 @@ public: * is success (IP address was found from DNS cache), callback will be called * before function returns. * - * @param host Hostname to resolve - * @param callback Callback that is called for result + * @param host Hostname to resolve. + * @param callback Callback that is called for result. * @param version IP version of address to resolve, NSAPI_UNSPEC indicates - * version is chosen by the stack (defaults to NSAPI_UNSPEC) + * version is chosen by the stack (defaults to NSAPI_UNSPEC). * @return 0 on immediate success, * negative error code on immediate failure or * a positive unique id that represents the hostname translation operation - * and can be passed to cancel + * and can be passed to cancel. */ virtual nsapi_value_or_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback, nsapi_version_t version = NSAPI_UNSPEC); - /** Cancels asynchronous hostname translation + /** Cancel asynchronous hostname translation. * * When translation is cancelled, callback will not be called. * - * @param id Unique id of the hostname translation operation - * @return 0 on success, negative error code on failure + * @param id Unique id of the hostname translation operation (returned + * by gethostbyname_async) + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t gethostbyname_async_cancel(int id); /** Add a domain name server to list of servers to query * - * @param address Destination for the host address - * @return 0 on success, negative error code on failure + * @param address Address for the dns host. + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t add_dns_server(const SocketAddress &address); - /** Register callback for status reporting + /** Register callback for status reporting. * * The specified status callback function will be called on status changes * on the network. The parameters on the callback are the event type and * event-type dependent reason parameter. * - * @param status_cb The callback for status changes + * @param status_cb The callback for status changes. */ virtual void attach(mbed::Callback status_cb); - /** Get the connection status + /** Get the connection status. * - * @return The connection status according to ConnectionStatusType + * @return The connection status (@see nsapi_types.h). */ virtual nsapi_connection_status_t get_connection_status() const; - /** Set blocking status of connect() which by default should be blocking + /** Set blocking status of connect() which by default should be blocking. * - * @param blocking true if connect is blocking - * @return 0 on success, negative error code on failure + * @param blocking Use true to make connect() blocking. + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t set_blocking(bool blocking); - /** Dynamic downcast to an EthInterface */ + /** Return pointer to an EthInterface. + * @return Pointer to requested interface type or NULL if this class doesn't implement the interface. + */ virtual EthInterface *ethInterface() { return 0; } - /** Dynamic downcast to a WiFiInterface */ + /** Return pointer to a WiFiInterface. + * @return Pointer to requested interface type or NULL if this class doesn't implement the interface. + */ virtual WiFiInterface *wifiInterface() { return 0; } - /** Dynamic downcast to a MeshInterface */ + /** Return pointer to a MeshInterface. + * @return Pointer to requested interface type or NULL if this class doesn't implement the interface. + */ virtual MeshInterface *meshInterface() { return 0; } - /** Dynamic downcast to a CellularBase */ + /** Return pointer to a CellularBase. + * @return Pointer to requested interface type or NULL if this class doesn't implement the interface. + */ virtual CellularBase *cellularBase() { return 0; } - /** Dynamic downcast to an EMACInterface */ + /** Return pointer to an EMACInterface. + * @return Pointer to requested interface type or NULL if this class doesn't implement the interface. + */ virtual EMACInterface *emacInterface() { return 0; } +#if !defined(DOXYGEN_ONLY) + protected: friend class InternetSocket; friend class UDPSocket; @@ -296,7 +307,7 @@ protected: * need to override in simple cases. * * If a target has more elaborate interface selection, it can completely - * override this behaviour by implementing + * override this behavior by implementing * NetworkInterface::get_target_default_instance() themselves, either * unconditionally, or for a specific network-default-interface-type setting * @@ -318,7 +329,8 @@ protected: * performs the search described by get_default_instance. */ static NetworkInterface *get_target_default_instance(); +#endif //!defined(DOXYGEN_ONLY) }; - +/** @}*/ #endif diff --git a/features/netsocket/NetworkStack.h b/features/netsocket/NetworkStack.h index 2ea7757dca..8edb9e0645 100644 --- a/features/netsocket/NetworkStack.h +++ b/features/netsocket/NetworkStack.h @@ -54,10 +54,10 @@ public: * will be resolve using a UDP socket on the stack. * * @param host Hostname to resolve - * @param address Destination for the host SocketAddress + * @param address Pointer to a SocketAddress to store the result. * @param version IP version of address to resolve, NSAPI_UNSPEC indicates * version is chosen by the stack (defaults to NSAPI_UNSPEC) - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t gethostbyname(const char *host, SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC); @@ -72,7 +72,7 @@ public: * The callback should not perform expensive operations such as socket recv/send * calls or blocking operations. * - * @param status 0 on success, negative error code on failure + * @param status NSAPI_ERROR_OK on success, negative error code on failure * @param address On success, destination for the host SocketAddress */ typedef mbed::Callback hostbyname_cb_t; @@ -107,14 +107,14 @@ public: * When translation is cancelled, callback will not be called. * * @param id Unique id of the hostname translation operation - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t gethostbyname_async_cancel(int id); /** Add a domain name server to list of servers to query * * @param address Destination for the host address - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t add_dns_server(const SocketAddress &address); @@ -125,7 +125,7 @@ public: * * @param index Index of the DNS server, starts from zero * @param address Destination for the host address - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t get_dns_server(int index, SocketAddress *address); @@ -142,7 +142,7 @@ public: * @param optname Level-specific option name * @param optval Option value * @param optlen Length of the option value - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t setstackopt(int level, int optname, const void *optval, unsigned optlen); @@ -156,7 +156,7 @@ public: * @param optname Level-specific option name * @param optval Destination for option value * @param optlen Length of the option value - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t getstackopt(int level, int optname, void *optval, unsigned *optlen); @@ -182,7 +182,7 @@ protected: * * @param handle Destination for the handle to a newly created socket * @param proto Protocol of socket to open, NSAPI_TCP or NSAPI_UDP - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto) = 0; @@ -192,7 +192,7 @@ protected: * with the socket. * * @param handle Socket handle - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t socket_close(nsapi_socket_t handle) = 0; @@ -203,7 +203,7 @@ protected: * * @param handle Socket handle * @param address Local address to bind - * @return 0 on success, negative error code on failure. + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t socket_bind(nsapi_socket_t handle, const SocketAddress &address) = 0; @@ -215,7 +215,7 @@ protected: * @param handle Socket handle * @param backlog Number of pending connections that can be queued * simultaneously - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t socket_listen(nsapi_socket_t handle, int backlog) = 0; @@ -226,7 +226,7 @@ protected: * * @param handle Socket handle * @param address The SocketAddress of the remote host - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address) = 0; @@ -246,7 +246,7 @@ protected: * @param server Socket handle to server to accept from * @param handle Destination for a handle to the newly created socket * @param address Destination for the remote address or NULL - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address = 0) = 0; @@ -336,34 +336,34 @@ protected: */ virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data) = 0; - /* Set stack-specific socket options + /** Set stack-specific socket options. * * The setsockopt allow an application to pass stack-specific hints * to the underlying stack. For unsupported options, * NSAPI_ERROR_UNSUPPORTED is returned and the socket is unmodified. * - * @param handle Socket handle - * @param level Stack-specific protocol level - * @param optname Stack-specific option identifier - * @param optval Option value - * @param optlen Length of the option value - * @return 0 on success, negative error code on failure + * @param handle Socket handle. + * @param level Stack-specific protocol level. + * @param optname Stack-specific option identifier. + * @param optval Option value. + * @param optlen Length of the option value. + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t setsockopt(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen); - /* Get stack-specific socket options + /** Get stack-specific socket options. * * The getstackopt allow an application to retrieve stack-specific hints * from the underlying stack. For unsupported options, * NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified. * - * @param handle Socket handle - * @param level Stack-specific protocol level - * @param optname Stack-specific option identifier - * @param optval Destination for option value - * @param optlen Length of the option value - * @return 0 on success, negative error code on failure + * @param handle Socket handle. + * @param level Stack-specific protocol level. + * @param optname Stack-specific option identifier. + * @param optval Destination for option value. + * @param optlen Length of the option value. + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t getsockopt(nsapi_socket_t handle, int level, int optname, void *optval, unsigned *optlen); @@ -397,7 +397,7 @@ private: * * @param delay Delay in milliseconds * @param func Callback to be called - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t call_in(int delay, mbed::Callback func); }; diff --git a/features/netsocket/Socket.h b/features/netsocket/Socket.h index fe560b4be7..f917575ab3 100644 --- a/features/netsocket/Socket.h +++ b/features/netsocket/Socket.h @@ -38,7 +38,7 @@ public: * Closes any open connection and deallocates any memory associated * with the socket. Called from destructor if socket is not closed. * - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t close() = 0; @@ -50,11 +50,11 @@ public: * Also connectionless protocols use the connected address to filter * incoming packets for recv() and recvfrom() calls. * - * To reset the peer address, zero initialised(default constructor) SocketAddress + * To reset the peer address, zero initialized(default constructor) SocketAddress * object have to be in the address parameter. * * @param address The SocketAddress of the remote peer - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t connect(const SocketAddress &address) = 0; @@ -142,10 +142,11 @@ public: /** Bind a specific address to a socket. * - * Binding assigns a local address to a socket. + * Binding a socket specifies the address and port on which to receive + * data. If the IP address is zeroed, only the port is bound. * * @param address Local address to bind - * @return 0 on success, negative error code on failure. + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t bind(const SocketAddress &address) = 0; @@ -155,8 +156,8 @@ public: * blocking operations such as send/recv/accept return * NSAPI_ERROR_WOULD_BLOCK if they can not continue. * - * set_blocking(false) is equivalent to set_timeout(-1) - * set_blocking(true) is equivalent to set_timeout(0) + * set_blocking(false) is equivalent to set_timeout(0) + * set_blocking(true) is equivalent to set_timeout(-1) * * @param blocking true for blocking mode, false for non-blocking mode. */ @@ -190,11 +191,11 @@ public: * such functionality. The exact timing of when the registered function * is called is not guaranteed and susceptible to change. * - * @param func Function to call on state change + * @param func Function to call on state change. */ virtual void sigio(mbed::Callback func) = 0; - /* Set socket options. + /** Set socket options. * * setsockopt() allows an application to pass stack-specific options * to the underlying stack using stack-specific level and option names, @@ -203,15 +204,15 @@ public: * For unsupported options, NSAPI_ERROR_UNSUPPORTED is returned * and the socket is unmodified. * - * @param level Stack-specific protocol level or nsapi_socket_level_t - * @param optname Level-specific option name - * @param optval Option value - * @param optlen Length of the option value - * @return 0 on success, negative error code on failure + * @param level Stack-specific protocol level or nsapi_socket_level_t. + * @param optname Level-specific option name. + * @param optval Option value. + * @param optlen Length of the option value. + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t setsockopt(int level, int optname, const void *optval, unsigned optlen) = 0; - /* Get socket options. + /** Get socket options. * * getsockopt() allows an application to retrieve stack-specific options * from the underlying stack using stack-specific level and option names, @@ -220,11 +221,11 @@ public: * For unsupported options, NSAPI_ERROR_UNSUPPORTED is returned * and the socket is unmodified. * - * @param level Stack-specific protocol level or nsapi_socket_level_t - * @param optname Level-specific option name - * @param optval Destination for option value - * @param optlen Length of the option value - * @return 0 on success, negative error code on failure + * @param level Stack-specific protocol level or nsapi_socket_level_t. + * @param optname Level-specific option name. + * @param optval Destination for option value. + * @param optlen Length of the option value. + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t getsockopt(int level, int optname, void *optval, unsigned *optlen) = 0; @@ -233,9 +234,9 @@ public: * The server socket must be bound and set to listen for connections. * On a new connection, returns connected network socket which user is expected to call close() * and that deallocates the resources. Referencing a returned pointer after a close() - * call is not allowed and leads to undefined behaviour. + * call is not allowed and leads to undefined behavior. * - * By default, accept blocks until incomming connection occurs. If socket is set to + * By default, accept blocks until incoming connection occurs. If socket is set to * non-blocking or times out, error is set to NSAPI_ERROR_WOULD_BLOCK. * * @param error pointer to storage of the error value or NULL @@ -250,7 +251,7 @@ public: * * @param backlog Number of pending connections that can be queued * simultaneously, defaults to 1 - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t listen(int backlog = 1) = 0; }; diff --git a/features/netsocket/SocketAddress.cpp b/features/netsocket/SocketAddress.cpp index 3e42619a5e..2d0cb75bc8 100644 --- a/features/netsocket/SocketAddress.cpp +++ b/features/netsocket/SocketAddress.cpp @@ -24,26 +24,6 @@ -static bool ipv6_is_valid(const char *addr) -{ - // Check each digit for [0-9a-fA-F:] - // Must also have at least 2 colons - int colons = 0; - for (int i = 0; addr[i]; i++) { - if (!(addr[i] >= '0' && addr[i] <= '9') && - !(addr[i] >= 'a' && addr[i] <= 'f') && - !(addr[i] >= 'A' && addr[i] <= 'F') && - addr[i] != ':') { - return false; - } - if (addr[i] == ':') { - colons++; - } - } - - return colons >= 2; -} - SocketAddress::SocketAddress(nsapi_addr_t addr, uint16_t port) { _ip_address = NULL; @@ -80,9 +60,8 @@ bool SocketAddress::set_ip_address(const char *addr) if (addr && stoip4(addr, strlen(addr), _addr.bytes)) { _addr.version = NSAPI_IPv4; return true; - } else if (addr && ipv6_is_valid(addr)) { + } else if (addr && stoip6(addr, strlen(addr), _addr.bytes)) { _addr.version = NSAPI_IPv6; - stoip6(addr, strlen(addr), _addr.bytes); return true; } else { _addr = nsapi_addr_t(); diff --git a/features/netsocket/SocketAddress.h b/features/netsocket/SocketAddress.h index 5725d0cfe4..b4b68c1a9d 100644 --- a/features/netsocket/SocketAddress.h +++ b/features/netsocket/SocketAddress.h @@ -42,7 +42,7 @@ public: * * @param stack Network stack to use for DNS resolution * @param host Hostname to resolve - * @param port Optional 16-bit port + * @param port Optional 16-bit port, defaults to 0 * @deprecated * Constructors hide possible errors. Replaced by * NetworkInterface::gethostbyname. @@ -57,16 +57,18 @@ public: } /** Create a SocketAddress from a raw IP address and port + * + * To construct from a host name, use NetworkInterface::gethostbyname * * @param addr Raw IP address - * @param port Optional 16-bit port + * @param port Optional 16-bit port, defaults to 0 */ SocketAddress(nsapi_addr_t addr = nsapi_addr_t(), uint16_t port = 0); /** Create a SocketAddress from an IP address and port * * @param addr Null-terminated representation of the IP address - * @param port Optional 16-bit port + * @param port Optional 16-bit port, defaults to 0 */ SocketAddress(const char *addr, uint16_t port = 0); @@ -74,7 +76,7 @@ public: * * @param bytes Raw IP address in big-endian order * @param version IP address version, NSAPI_IPv4 or NSAPI_IPv6 - * @param port Optional 16-bit port + * @param port Optional 16-bit port, defaults to 0 */ SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port = 0); diff --git a/features/netsocket/TCPServer.cpp b/features/netsocket/TCPServer.cpp index 3ddd3b549b..1772b65ef0 100644 --- a/features/netsocket/TCPServer.cpp +++ b/features/netsocket/TCPServer.cpp @@ -15,7 +15,8 @@ */ #include "TCPServer.h" -#include "mbed.h" + +using mbed::Callback; TCPServer::TCPServer() { @@ -23,7 +24,6 @@ TCPServer::TCPServer() TCPServer::~TCPServer() { - close(); } nsapi_error_t TCPServer::accept(TCPSocket *connection, SocketAddress *address) diff --git a/features/netsocket/TCPSocket.cpp b/features/netsocket/TCPSocket.cpp index dc304070ee..ce29384de9 100644 --- a/features/netsocket/TCPSocket.cpp +++ b/features/netsocket/TCPSocket.cpp @@ -22,9 +22,19 @@ TCPSocket::TCPSocket() { } +TCPSocket::TCPSocket(TCPSocket *parent, nsapi_socket_t socket, SocketAddress address) +{ + _socket = socket, + _stack = parent->_stack; + _factory_allocated = true; + _remote_peer = address; + + _event = mbed::Callback(this, &TCPSocket::event); + _stack->socket_attach(socket, &mbed::Callback::thunk, &_event); +} + TCPSocket::~TCPSocket() { - close(); } nsapi_protocol_t TCPSocket::get_proto() @@ -265,16 +275,7 @@ TCPSocket *TCPSocket::accept(nsapi_error_t *error) ret = _stack->socket_accept(_socket, &socket, &address); if (0 == ret) { - connection = new TCPSocket(); - connection->_lock.lock(); - connection->_factory_allocated = true; // Destroy automatically on close() - connection->_remote_peer = address; - connection->_stack = _stack; - connection->_socket = socket; - connection->_event = mbed::Callback(connection, &TCPSocket::event); - _stack->socket_attach(socket, &mbed::Callback::thunk, &connection->_event); - - connection->_lock.unlock(); + connection = new TCPSocket(this, socket, address); break; } else if ((_timeout == 0) || (ret != NSAPI_ERROR_WOULD_BLOCK)) { break; diff --git a/features/netsocket/TCPSocket.h b/features/netsocket/TCPSocket.h index 33e0ae3033..bde477cafb 100644 --- a/features/netsocket/TCPSocket.h +++ b/features/netsocket/TCPSocket.h @@ -158,9 +158,9 @@ public: * The server socket must be bound and set to listen for connections. * On a new connection, returns connected network socket which user is expected to call close() * and that deallocates the resources. Referencing a returned pointer after a close() - * call is not allowed and leads to undefined behaviour. + * call is not allowed and leads to undefined behavior. * - * By default, accept blocks until incomming connection occurs. If socket is set to + * By default, accept blocks until incoming connection occurs. If socket is set to * non-blocking or times out, error is set to NSAPI_ERROR_WOULD_BLOCK. * * @param error pointer to storage of the error value or NULL @@ -182,6 +182,13 @@ public: protected: friend class TCPServer; virtual nsapi_protocol_t get_proto(); + +private: + /** Create a socket out of a given socket + * + * To be used within accept() function. Close() will clean this up. + */ + TCPSocket(TCPSocket *parent, nsapi_socket_t socket, SocketAddress address); }; diff --git a/features/netsocket/TLSSocket.cpp b/features/netsocket/TLSSocket.cpp new file mode 100644 index 0000000000..bf53be6d2c --- /dev/null +++ b/features/netsocket/TLSSocket.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 ARM Limited + * 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. + */ + +#include "TLSSocket.h" + +#define TRACE_GROUP "TLSS" +#include "mbed-trace/mbed_trace.h" + +// This class requires Mbed TLS SSL/TLS client code +#if defined(MBEDTLS_SSL_CLI_C) + +nsapi_error_t TLSSocket::connect(const char *host, uint16_t port) +{ + set_hostname(host); + + nsapi_error_t ret = tcp_socket.connect(host, port); + if (ret) { + return ret; + } + + return TLSSocketWrapper::do_handshake(); +} + +TLSSocket::~TLSSocket() +{ + /* Transport is a member of TLSSocket which is derived from TLSSocketWrapper. + * Make sure that TLSSocketWrapper::close() is called before the transport is + * destroyed. + */ + close(); +} + +#endif // MBEDTLS_SSL_CLI_C \ No newline at end of file diff --git a/features/netsocket/TLSSocket.h b/features/netsocket/TLSSocket.h new file mode 100644 index 0000000000..3a759dc9e9 --- /dev/null +++ b/features/netsocket/TLSSocket.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018 ARM Limited + * 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. + */ + +#ifndef _MBED_HTTPS_TLS_TCP_SOCKET_H_ +#define _MBED_HTTPS_TLS_TCP_SOCKET_H_ + +#include "netsocket/TCPSocket.h" +#include "TLSSocketWrapper.h" + +#include "mbedtls/platform.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" + +// This class requires Mbed TLS SSL/TLS client code +#if defined(MBEDTLS_SSL_CLI_C) + +/** + * \brief TLSSocket a wrapper around TCPSocket for interacting with TLS servers + */ +class TLSSocket : public TLSSocketWrapper { +public: + /** Create an uninitialized socket + * + * Must call open to initialize the socket on a network stack. + */ + TLSSocket() : TLSSocketWrapper(&tcp_socket) {} + + /** Destroy the TLSSocket and closes the transport. + */ + virtual ~TLSSocket(); + + /** Create a socket on a network interface + * + * Creates and opens a socket on the network stack of the given + * network interface. + * If hostname is also given, user is not required to call set_hostname() later. + * + * @param stack Network stack as target for socket + * @param hostname Hostname used for certificate verification + */ + template + TLSSocket(S *stack, const char *hostname = NULL) : TLSSocketWrapper(&tcp_socket, hostname) + { + nsapi_error_t ret = tcp_socket.open(stack); + MBED_ASSERT(ret == NSAPI_ERROR_OK); + } + + /** Opens a socket + * + * Creates a network socket on the network stack of the given + * network interface. Not needed if stack is passed to the + * socket's constructor. + * + * @param stack Network stack as target for socket + * @return 0 on success, negative error code on failure + */ + virtual nsapi_error_t open(NetworkStack *stack) + { + return tcp_socket.open(stack); + } + + template + nsapi_error_t open(S *stack) + { + return open(nsapi_create_stack(stack)); + } + + using TLSSocketWrapper::connect; + + /** Connects TCP socket to a remote host + * + * Initiates a connection to a remote server specified by either + * a domain name or an IP address and a port. + * + * @param host Hostname of the remote host + * @param port Port of the remote host + * @return 0 on success, negative error code on failure + */ + nsapi_error_t connect(const char *host, uint16_t port); + +private: + TCPSocket tcp_socket; +}; + +#endif // MBEDTLS_SSL_CLI_C +#endif // _MBED_HTTPS_TLS_TCP_SOCKET_H_ diff --git a/features/netsocket/TLSSocketWrapper.cpp b/features/netsocket/TLSSocketWrapper.cpp new file mode 100644 index 0000000000..21e2682009 --- /dev/null +++ b/features/netsocket/TLSSocketWrapper.cpp @@ -0,0 +1,580 @@ +/* + * Copyright (c) 2018 ARM Limited + * 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. + */ + +#include "TLSSocketWrapper.h" +#include "drivers/Timer.h" + +#define TRACE_GROUP "TLSW" +#include "mbed-trace/mbed_trace.h" +#include "mbedtls/debug.h" +#include "mbed_error.h" + +// This class requires Mbed TLS SSL/TLS client code +#if defined(MBEDTLS_SSL_CLI_C) + +TLSSocketWrapper::TLSSocketWrapper(Socket *transport, const char *hostname, control_transport control) : + _transport(transport), +#ifdef MBEDTLS_X509_CRT_PARSE_C + _cacert(NULL), + _clicert(NULL), +#endif + _ssl_conf(NULL), + _connect_transport(control == TRANSPORT_CONNECT || control == TRANSPORT_CONNECT_AND_CLOSE), + _close_transport(control == TRANSPORT_CLOSE || control == TRANSPORT_CONNECT_AND_CLOSE), + _handshake_completed(false), + _cacert_allocated(false), + _clicert_allocated(false), + _ssl_conf_allocated(false) +{ + mbedtls_entropy_init(&_entropy); + mbedtls_ctr_drbg_init(&_ctr_drbg); + mbedtls_ssl_init(&_ssl); + mbedtls_pk_init(&_pkctx); + + if (hostname) { + set_hostname(hostname); + } +} + +TLSSocketWrapper::~TLSSocketWrapper() +{ + if (_transport) { + close(); + } + mbedtls_entropy_free(&_entropy); + mbedtls_ctr_drbg_free(&_ctr_drbg); + mbedtls_ssl_free(&_ssl); + mbedtls_pk_free(&_pkctx); + +#ifdef MBEDTLS_X509_CRT_PARSE_C + set_own_cert(NULL); + set_ca_chain(NULL); +#endif + set_ssl_config(NULL); +} + +void TLSSocketWrapper::set_hostname(const char *hostname) +{ +#ifdef MBEDTLS_X509_CRT_PARSE_C + mbedtls_ssl_set_hostname(&_ssl, hostname); +#endif +} + +nsapi_error_t TLSSocketWrapper::set_root_ca_cert(const void *root_ca, size_t len) +{ +#if !defined(MBEDTLS_X509_CRT_PARSE_C) + return NSAPI_ERROR_UNSUPPORTED; +#else + mbedtls_x509_crt *crt; + + crt = new (std::nothrow) mbedtls_x509_crt; + if (!crt) { + return NSAPI_ERROR_NO_MEMORY; + } + + mbedtls_x509_crt_init(crt); + + /* Parse CA certification */ + int ret; + if ((ret = mbedtls_x509_crt_parse(crt, static_cast(root_ca), + len)) != 0) { + print_mbedtls_error("mbedtls_x509_crt_parse", ret); + return NSAPI_ERROR_PARAMETER; + } + set_ca_chain(crt); + _cacert_allocated = true; + return NSAPI_ERROR_OK; +#endif +} + +nsapi_error_t TLSSocketWrapper::set_root_ca_cert(const char *root_ca_pem) +{ + return set_root_ca_cert(root_ca_pem, strlen(root_ca_pem) + 1); +} + +nsapi_error_t TLSSocketWrapper::set_client_cert_key(const char *client_cert_pem, const char *client_private_key_pem) +{ + return set_client_cert_key(client_cert_pem, strlen(client_cert_pem) + 1, client_private_key_pem, strlen(client_private_key_pem) + 1); +} + +nsapi_error_t TLSSocketWrapper::set_client_cert_key(const void *client_cert, size_t client_cert_len, + const void *client_private_key_pem, size_t client_private_key_len) +{ +#if !defined(MBEDTLS_X509_CRT_PARSE_C) + return NSAPI_ERROR_UNSUPPORTED; +#else + + int ret; + mbedtls_x509_crt *crt = new mbedtls_x509_crt; + mbedtls_x509_crt_init(crt); + if ((ret = mbedtls_x509_crt_parse(crt, static_cast(client_cert), + client_cert_len)) != 0) { + print_mbedtls_error("mbedtls_x509_crt_parse", ret); + return NSAPI_ERROR_PARAMETER; + } + mbedtls_pk_init(&_pkctx); + if ((ret = mbedtls_pk_parse_key(&_pkctx, static_cast(client_private_key_pem), + client_private_key_len, NULL, 0)) != 0) { + print_mbedtls_error("mbedtls_pk_parse_key", ret); + return NSAPI_ERROR_PARAMETER; + } + set_own_cert(crt); + _clicert_allocated = true; + + return NSAPI_ERROR_OK; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +} + + +nsapi_error_t TLSSocketWrapper::do_handshake() +{ + nsapi_error_t _error; + const char DRBG_PERS[] = "mbed TLS client"; + + if (!_transport) { + return NSAPI_ERROR_NO_SOCKET; + } + + _transport->set_blocking(true); + /* + * Initialize TLS-related stuf. + */ + int ret; + if ((ret = mbedtls_ctr_drbg_seed(&_ctr_drbg, mbedtls_entropy_func, &_entropy, + (const unsigned char *) DRBG_PERS, + sizeof(DRBG_PERS))) != 0) { + print_mbedtls_error("mbedtls_crt_drbg_init", ret); + _error = ret; + return _error; + } + + tr_info("mbedtls_ssl_conf_rng()"); + mbedtls_ssl_conf_rng(get_ssl_config(), mbedtls_ctr_drbg_random, &_ctr_drbg); + + +#if MBED_CONF_TLS_SOCKET_DEBUG_LEVEL > 0 + mbedtls_ssl_conf_verify(get_ssl_config(), my_verify, NULL); + mbedtls_ssl_conf_dbg(get_ssl_config(), my_debug, NULL); + mbedtls_debug_set_threshold(MBED_CONF_TLS_SOCKET_DEBUG_LEVEL); +#endif + + tr_info("mbedtls_ssl_setup()"); + if ((ret = mbedtls_ssl_setup(&_ssl, get_ssl_config())) != 0) { + print_mbedtls_error("mbedtls_ssl_setup", ret); + _error = ret; + return _error; + } + + mbedtls_ssl_set_bio(&_ssl, this, ssl_send, ssl_recv, NULL); + +#ifdef MBEDTLS_X509_CRT_PARSE_C + /* Start the handshake, the rest will be done in onReceive() */ + tr_info("Starting TLS handshake with %s", _ssl.hostname); +#else + tr_info("Starting TLS handshake"); +#endif + + do { + ret = mbedtls_ssl_handshake(&_ssl); + } while (ret != 0 && (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE)); + if (ret < 0) { + print_mbedtls_error("mbedtls_ssl_handshake", ret); + return ret; + } + +#ifdef MBEDTLS_X509_CRT_PARSE_C + /* It also means the handshake is done, time to print info */ + tr_info("TLS connection to %s established", _ssl.hostname); +#else + tr_info("TLS connection established"); +#endif + +#ifdef MBEDTLS_X509_CRT_PARSE_C + /* Prints the server certificate and verify it. */ + const size_t buf_size = 1024; + char *buf = new char[buf_size]; + mbedtls_x509_crt_info(buf, buf_size, "\r ", + mbedtls_ssl_get_peer_cert(&_ssl)); + tr_debug("Server certificate:\r\n%s\r\n", buf); + + uint32_t flags = mbedtls_ssl_get_verify_result(&_ssl); + if (flags != 0) { + /* Verification failed. */ + mbedtls_x509_crt_verify_info(buf, buf_size, "\r ! ", flags); + tr_error("Certificate verification failed:\r\n%s", buf); + } else { + /* Verification succeeded. */ + tr_info("Certificate verification passed"); + } + delete[] buf; +#endif + + _handshake_completed = true; + + return 0; +} + + +nsapi_error_t TLSSocketWrapper::send(const void *data, nsapi_size_t size) +{ + int ret; + + if (!_transport) { + return NSAPI_ERROR_NO_SOCKET; + } + + tr_debug("send %d", size); + ret = mbedtls_ssl_write(&_ssl, (const unsigned char *) data, size); + + if (ret == MBEDTLS_ERR_SSL_WANT_WRITE || + ret == MBEDTLS_ERR_SSL_WANT_READ) { + // translate to socket error + return NSAPI_ERROR_WOULD_BLOCK; + } + if (ret < 0) { + print_mbedtls_error("mbedtls_ssl_write", ret); + } + return ret; // Assume "non negative errorcode" to be propagated from Socket layer +} + +nsapi_size_or_error_t TLSSocketWrapper::sendto(const SocketAddress &, const void *data, nsapi_size_t size) +{ + // Ignore the SocketAddress + return send(data, size); +} + +nsapi_size_or_error_t TLSSocketWrapper::recv(void *data, nsapi_size_t size) +{ + int ret; + + if (!_transport) { + return NSAPI_ERROR_NO_SOCKET; + } + + ret = mbedtls_ssl_read(&_ssl, (unsigned char *) data, size); + + if (ret == MBEDTLS_ERR_SSL_WANT_WRITE || + ret == MBEDTLS_ERR_SSL_WANT_READ) { + // translate to socket error + return NSAPI_ERROR_WOULD_BLOCK; + } else if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + /* MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY is not considered as error. + * Just ignre here. Once connection is closed, mbedtls_ssl_read() + * will return 0. + */ + return 0; + } else if (ret < 0) { + print_mbedtls_error("mbedtls_ssl_read", ret); + // There is no mapping of TLS error codes to Socket API so return most generic error to application + return NSAPI_ERROR_DEVICE_ERROR; + } + return ret; +} + +nsapi_size_or_error_t TLSSocketWrapper::recvfrom(SocketAddress *address, void *data, nsapi_size_t size) +{ + return recv(data, size); +} + +void TLSSocketWrapper::print_mbedtls_error(const char *name, int err) +{ +#ifdef MBEDTLS_ERROR_C + char *buf = new char[128]; + mbedtls_strerror(err, buf, 128); + tr_err("%s() failed: -0x%04x (%d): %s", name, -err, err, buf); + delete[] buf; +#else + (void)name; + (void)err; +#endif +} + + +#if MBED_CONF_TLS_SOCKET_DEBUG_LEVEL > 0 + +void TLSSocketWrapper::my_debug(void *ctx, int level, const char *file, int line, + const char *str) +{ + const char *p, *basename; + (void) ctx; + + /* Extract basename from file */ + for (p = basename = file; *p != '\0'; p++) { + if (*p == '/' || *p == '\\') { + basename = p + 1; + } + } + + tr_debug("%s:%04d: |%d| %s", basename, line, level, str); +} + + +int TLSSocketWrapper::my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) +{ + const uint32_t buf_size = 1024; + char *buf = new char[buf_size]; + (void) data; + + tr_debug("\nVerifying certificate at depth %d:\n", depth); + mbedtls_x509_crt_info(buf, buf_size - 1, " ", crt); + tr_debug("%s", buf); + + if (*flags == 0) { + tr_info("No verification issue for this certificate\n"); + } else { + mbedtls_x509_crt_verify_info(buf, buf_size, " ! ", *flags); + tr_info("%s\n", buf); + } + + delete[] buf; + + return 0; +} + +#endif /* MBED_CONF_TLS_SOCKET_DEBUG_LEVEL > 0 */ + + +int TLSSocketWrapper::ssl_recv(void *ctx, unsigned char *buf, size_t len) +{ + int recv; + + TLSSocketWrapper *my = static_cast(ctx); + + if (!my->_transport) { + return NSAPI_ERROR_NO_SOCKET; + } + + recv = my->_transport->recv(buf, len); + + if (NSAPI_ERROR_WOULD_BLOCK == recv) { + return MBEDTLS_ERR_SSL_WANT_READ; + } else if (recv < 0) { + tr_error("Socket recv error %d", recv); + } + // Propagate also Socket errors to SSL, it allows negative error codes to be returned here. + return recv; +} + +int TLSSocketWrapper::ssl_send(void *ctx, const unsigned char *buf, size_t len) +{ + int size = -1; + TLSSocketWrapper *my = static_cast(ctx); + + if (!my->_transport) { + return NSAPI_ERROR_NO_SOCKET; + } + + size = my->_transport->send(buf, len); + + if (NSAPI_ERROR_WOULD_BLOCK == size) { + return MBEDTLS_ERR_SSL_WANT_WRITE; + } else if (size < 0) { + tr_error("Socket send error %d", size); + } + // Propagate also Socket errors to SSL, it allows negative error codes to be returned here. + return size; +} + +#ifdef MBEDTLS_X509_CRT_PARSE_C + +mbedtls_x509_crt *TLSSocketWrapper::get_own_cert() +{ + return _clicert; +} + +int TLSSocketWrapper::set_own_cert(mbedtls_x509_crt *crt) +{ + int ret = 0; + if (_clicert && _clicert_allocated) { + mbedtls_x509_crt_free(_clicert); + delete _clicert; + _clicert_allocated = false; + } + _clicert = crt; + if (crt) { + if ((ret = mbedtls_ssl_conf_own_cert(get_ssl_config(), _clicert, &_pkctx)) != 0) { + print_mbedtls_error("mbedtls_ssl_conf_own_cert", ret); + } + } + return ret; +} + +mbedtls_x509_crt *TLSSocketWrapper::get_ca_chain() +{ + return _cacert; +} + +void TLSSocketWrapper::set_ca_chain(mbedtls_x509_crt *crt) +{ + if (_cacert && _cacert_allocated) { + mbedtls_x509_crt_free(_cacert); + delete _cacert; + _cacert_allocated = false; + } + _cacert = crt; + tr_info("mbedtls_ssl_conf_ca_chain()"); + mbedtls_ssl_conf_ca_chain(get_ssl_config(), _cacert, NULL); +} + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +mbedtls_ssl_config *TLSSocketWrapper::get_ssl_config() +{ + if (!_ssl_conf) { + int ret; + _ssl_conf = new mbedtls_ssl_config; + mbedtls_ssl_config_init(_ssl_conf); + _ssl_conf_allocated = true; + + tr_info("mbedtls_ssl_config_defaults()"); + if ((ret = mbedtls_ssl_config_defaults(_ssl_conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + print_mbedtls_error("mbedtls_ssl_config_defaults", ret); + set_ssl_config(NULL); + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_OUT_OF_MEMORY), "mbedtls_ssl_config_defaults() failed"); + return NULL; + } + /* It is possible to disable authentication by passing + * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode() + */ + tr_info("mbedtls_ssl_conf_authmode()"); + mbedtls_ssl_conf_authmode(get_ssl_config(), MBEDTLS_SSL_VERIFY_REQUIRED); + } + return _ssl_conf; +} + +void TLSSocketWrapper::set_ssl_config(mbedtls_ssl_config *conf) +{ + if (_ssl_conf && _ssl_conf_allocated) { + mbedtls_ssl_config_free(_ssl_conf); + delete _ssl_conf; + _ssl_conf_allocated = false; + } + _ssl_conf = conf; +} + +nsapi_error_t TLSSocketWrapper::close() +{ + if (!_transport) { + return NSAPI_ERROR_NO_SOCKET; + } + + tr_info("Closing TLS"); + + int ret = 0; + if (_handshake_completed) { + _transport->set_blocking(true); + ret = mbedtls_ssl_close_notify(&_ssl); + if (ret) { + print_mbedtls_error("mbedtls_ssl_close_notify", ret); + } + _handshake_completed = false; + } + + if (_close_transport) { + int ret2 = _transport->close(); + if (!ret) { + ret = ret2; + } + } + + _transport = NULL; + + return ret; +} + +nsapi_error_t TLSSocketWrapper::connect(const SocketAddress &address) +{ + if (!_transport) { + return NSAPI_ERROR_NO_SOCKET; + } + + if (_connect_transport) { + nsapi_error_t ret = _transport->connect(address); + if (ret) { + return ret; + } + } + return do_handshake(); +} + +nsapi_error_t TLSSocketWrapper::bind(const SocketAddress &address) +{ + if (!_transport) { + return NSAPI_ERROR_NO_SOCKET; + } + return _transport->bind(address); +} + +void TLSSocketWrapper::set_blocking(bool blocking) +{ + if (!_transport) { + return; + } + _transport->set_blocking(blocking); +} + +void TLSSocketWrapper::set_timeout(int timeout) +{ + if (!_transport) { + return; + } + _transport->set_timeout(timeout); +} + +void TLSSocketWrapper::sigio(mbed::Callback func) +{ + if (!_transport) { + return; + } + // Allow sigio() to propagate to upper level and handle errors on recv() and send() + _transport->sigio(func); +} + +nsapi_error_t TLSSocketWrapper::setsockopt(int level, int optname, const void *optval, unsigned optlen) +{ + if (!_transport) { + return NSAPI_ERROR_NO_SOCKET; + } + return _transport->setsockopt(level, optname, optval, optlen); +} + +nsapi_error_t TLSSocketWrapper::getsockopt(int level, int optname, void *optval, unsigned *optlen) +{ + if (!_transport) { + return NSAPI_ERROR_NO_SOCKET; + } + return _transport->getsockopt(level, optname, optval, optlen); +} + +Socket *TLSSocketWrapper::accept(nsapi_error_t *err) +{ + if (err) { + *err = NSAPI_ERROR_UNSUPPORTED; + } + return NULL; +} + +nsapi_error_t TLSSocketWrapper::listen(int) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + +#endif /* MBEDTLS_SSL_CLI_C */ diff --git a/features/netsocket/TLSSocketWrapper.h b/features/netsocket/TLSSocketWrapper.h new file mode 100644 index 0000000000..4accb3c28e --- /dev/null +++ b/features/netsocket/TLSSocketWrapper.h @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2018 ARM Limited + * 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. + */ + +#ifndef _MBED_HTTPS_TLS_SOCKET_WRAPPER_H_ +#define _MBED_HTTPS_TLS_SOCKET_WRAPPER_H_ + +#include "netsocket/Socket.h" + +#include "mbedtls/platform.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" + +// This class requires Mbed TLS SSL/TLS client code +#if defined(MBEDTLS_SSL_CLI_C) + +/** + * \brief TLSSocket a wrapper around Socket for interacting with TLS servers + */ +class TLSSocketWrapper : public Socket { +public: + enum control_transport { + TRANSPORT_KEEP, + TRANSPORT_CONNECT_AND_CLOSE, + TRANSPORT_CONNECT, + TRANSPORT_CLOSE, + }; + + /* Create a TLSSocketWrapper + * + * @param transport Underlying transport socket to wrap + * @param hostname Hostname of the remote host, used for certificate checking + */ + TLSSocketWrapper(Socket *transport, const char *hostname = NULL, control_transport control = TRANSPORT_CONNECT_AND_CLOSE); + + /** Destroy a socket wrapper + * + * Closes socket wrapper if the socket wrapper is still open + */ + virtual ~TLSSocketWrapper(); + + /** Set hostname. + * + * TLSSocket requires hostname that is used to verify the certificate. + * If hostname is not given in constructor, this function must be used before + * starting the TLS handshake. + */ + void set_hostname(const char *hostname); + + /** Sets the certification of Root CA. + * + * @param root_ca Root CA Certificate in any mbed-TLS supported format. + * @param len Length of certificate (including terminating 0 for PEM). + */ + nsapi_error_t set_root_ca_cert(const void *root_ca, size_t len); + + /** Sets the certification of Root CA. + * + * @param root_ca_pem Root CA Certificate in PEM format + */ + nsapi_error_t set_root_ca_cert(const char *root_ca_pem); + + /** Sets client certificate, and client private key. + * + * @param client_cert client certification in PEM or DER format. + * @param client_cert_len certificate size including the terminating null byte for PEM data. + * @param client_private_key_pem client private key in PEM or DER format + * @param client_private_key_len key size including the terminating null byte for PEM data + */ + nsapi_error_t set_client_cert_key(const void *client_cert, size_t client_cert_len, + const void *client_private_key_pem, size_t client_private_key_len); + + /** Sets client certificate, and client private key. + * + * @param client_cert_pem Client certification in PEM format. + * @param client_private_key_pem Client private key in PEM format. + */ + nsapi_error_t set_client_cert_key(const char *client_cert_pem, const char *client_private_key_pem); + + /** Send data over a TLS socket + * + * The socket must be connected to a remote host. Returns the number of + * bytes sent from the buffer. + * + * @param data Buffer of data to send to the host + * @param size Size of the buffer in bytes + * @return Number of sent bytes on success, negative error + * code on failure + */ + virtual nsapi_error_t send(const void *data, nsapi_size_t size); + + /** Receive data over a TLS socket + * + * The socket must be connected to a remote host. Returns the number of + * bytes received into the buffer. + * + * @param data Destination buffer for data received from the host + * @param size Size of the buffer in bytes + * @return Number of received bytes on success, negative error + * code on failure. If no data is available to be received + * and the peer has performed an orderly shutdown, + * recv() returns 0. + */ + virtual nsapi_size_or_error_t recv(void *data, nsapi_size_t size); + + /* = Functions inherited from Socket = */ + virtual nsapi_error_t close(); + virtual nsapi_error_t connect(const SocketAddress &address = SocketAddress()); + virtual nsapi_size_or_error_t sendto(const SocketAddress &address, const void *data, nsapi_size_t size); + virtual nsapi_size_or_error_t recvfrom(SocketAddress *address, + void *data, nsapi_size_t size); + virtual nsapi_error_t bind(const SocketAddress &address); + virtual void set_blocking(bool blocking); + virtual void set_timeout(int timeout); + virtual void sigio(mbed::Callback func); + virtual nsapi_error_t setsockopt(int level, int optname, const void *optval, unsigned optlen); + virtual nsapi_error_t getsockopt(int level, int optname, void *optval, unsigned *optlen); + virtual Socket *accept(nsapi_error_t *error = NULL); + virtual nsapi_error_t listen(int backlog = 1); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(DOXYGEN) + /** Get own certificate directly from Mbed TLS + * @return internal Mbed TLS X509 structure + */ + mbedtls_x509_crt *get_own_cert(); + + /** Set own certificate directly to Mbed TLS + * @param crt Mbed TLS X509 certificate chain. + * @return error code from mbedtls_ssl_conf_own_cert() + */ + int set_own_cert(mbedtls_x509_crt *crt); + + /** Get CA chain structure. + * @return Mbed TLS X509 certificate chain. + */ + mbedtls_x509_crt *get_ca_chain(); + + /** Set CA chain directly to Mbed TLS + * @param crt Mbed TLS X509 certificate chain. + */ + void set_ca_chain(mbedtls_x509_crt *crt); +#endif + + /** Get internal Mbed TLS configuration structure + * @return Mbed TLS SSL config + */ + mbedtls_ssl_config *get_ssl_config(); + + /** Override Mbed TLS configuration. + * @param conf Mbed TLS SSL configuration structure + */ + void set_ssl_config(mbedtls_ssl_config *conf); + +protected: + /** + * Helper for pretty-printing mbed TLS error codes + */ + static void print_mbedtls_error(const char *name, int err); + + /** Initiates TLS Handshake + * + * Initiates a TLS handshake to a remote peer + * Underlying transport socket should already be connected + * + * Root CA certification must be set by set_ssl_ca_pem() before + * call this function. + * + * @return 0 on success, negative error code on failure + */ + nsapi_error_t do_handshake(); + +#if MBED_CONF_TLS_SOCKET_DEBUG_LEVEL > 0 + /** + * Debug callback for mbed TLS + * Just prints on the USB serial port + */ + static void my_debug(void *ctx, int level, const char *file, int line, + const char *str); + + /** + * Certificate verification callback for mbed TLS + * Here we only use it to display information on each cert in the chain + */ + static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags); + +#endif /* MBED_CONF_TLS_SOCKET_DEBUG_LEVEL > 0 */ + + /** + * Receive callback for Mbed TLS + */ + static int ssl_recv(void *ctx, unsigned char *buf, size_t len); + + /** + * Send callback for Mbed TLS + */ + static int ssl_send(void *ctx, const unsigned char *buf, size_t len); + +private: + mbedtls_ssl_context _ssl; + mbedtls_pk_context _pkctx; + mbedtls_ctr_drbg_context _ctr_drbg; + mbedtls_entropy_context _entropy; + + Socket *_transport; + +#ifdef MBEDTLS_X509_CRT_PARSE_C + mbedtls_x509_crt *_cacert; + mbedtls_x509_crt *_clicert; +#endif + mbedtls_ssl_config *_ssl_conf; + + bool _connect_transport: 1; + bool _close_transport: 1; + bool _handshake_completed: 1; + bool _cacert_allocated: 1; + bool _clicert_allocated: 1; + bool _ssl_conf_allocated: 1; + +}; + +#endif /* MBEDTLS_SSL_CLI_C */ +#endif // _MBED_HTTPS_TLS_SOCKET_WRAPPER_H_ diff --git a/features/netsocket/UDPSocket.cpp b/features/netsocket/UDPSocket.cpp index c4f4ed45be..7b8a7d50b6 100644 --- a/features/netsocket/UDPSocket.cpp +++ b/features/netsocket/UDPSocket.cpp @@ -24,7 +24,6 @@ UDPSocket::UDPSocket() UDPSocket::~UDPSocket() { - close(); } nsapi_protocol_t UDPSocket::get_proto() diff --git a/features/netsocket/UDPSocket.h b/features/netsocket/UDPSocket.h index 087bb8932d..49a90fd75a 100644 --- a/features/netsocket/UDPSocket.h +++ b/features/netsocket/UDPSocket.h @@ -26,22 +26,21 @@ #include "rtos/EventFlags.h" -/** UDP socket +/** UDP socket implementation. */ class UDPSocket : public InternetSocket { public: - /** Create an uninitialized socket + /** Create an uninitialized socket. * - * Must call open to initialize the socket on a network stack. + * @note Must call open to initialize the socket on a network stack. */ UDPSocket(); - /** Create a socket on a network interface - * - * Creates and opens a socket on the network stack of the given + /** Create and open a socket on the network stack of the given * network interface. * - * @param stack Network stack as target for socket + * @tparam S Type of the Network stack. + * @param stack Network stack as target for socket. */ template UDPSocket(S *stack) @@ -49,96 +48,84 @@ public: open(stack); } - /** Destroy a socket + /** Destroy a socket. * - * Closes socket if the socket is still open + * @note Closes socket if the socket is still open. */ virtual ~UDPSocket(); - /** Send a packet over a UDP socket - * - * Sends data to the specified address specified by either a domain name - * or an IP address and port. Returns the number of bytes sent from the - * buffer. + /** Send data to the specified host and port. * * By default, sendto blocks until data is sent. If socket is set to - * non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned + * nonblocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned * immediately. * - * @param host Hostname of the remote host - * @param port Port of the remote host - * @param data Buffer of data to send to the host - * @param size Size of the buffer in bytes + * @param host Domain name of the remote host or a dotted notation IP address. + * @param port Port of the remote host. + * @param data Buffer of data to send to the host. + * @param size Size of the buffer in bytes. * @return Number of sent bytes on success, negative error - * code on failure + * code on failure. */ virtual nsapi_size_or_error_t sendto(const char *host, uint16_t port, const void *data, nsapi_size_t size); - /** Send a packet over a UDP socket - * - * Sends data to the specified address. Returns the number of bytes - * sent from the buffer. + /** Send data to the specified address. * * By default, sendto blocks until data is sent. If socket is set to - * non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned + * nonblocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned * immediately. * - * @param address The SocketAddress of the remote host - * @param data Buffer of data to send to the host - * @param size Size of the buffer in bytes + * @param address The SocketAddress of the remote host. + * @param data Buffer of data to send to the host. + * @param size Size of the buffer in bytes. * @return Number of sent bytes on success, negative error - * code on failure + * code on failure. */ virtual nsapi_size_or_error_t sendto(const SocketAddress &address, const void *data, nsapi_size_t size); - /** Receive a datagram over a UDP socket + /** Receive a datagram and store the source address in address if it's not NULL. * - * Receives a datagram and stores the source address in address if address - * is not NULL. Returns the number of bytes written into the buffer. If the - * datagram is larger than the buffer, the excess data is silently discarded. + * By default, recvfrom blocks until a datagram is received. If socket is set to + * nonblocking or times out with no datagram, NSAPI_ERROR_WOULD_BLOCK + * is returned. * - * If socket is connected, only packets coming from connected peer address + * @note If the datagram is larger than the buffer, the excess data is silently discarded. + * + * @note If socket is connected, only packets coming from connected peer address * are accepted. * * @note recvfrom() is allowed write to address and data buffers even if error occurs. * - * By default, recvfrom blocks until a datagram is received. If socket is set to - * non-blocking or times out with no datagram, NSAPI_ERROR_WOULD_BLOCK - * is returned. - * - * @param address Destination for the source address or NULL - * @param data Destination buffer for datagram received from the host - * @param size Size of the buffer in bytes + * @param address Destination for the source address or NULL. + * @param data Destination buffer for datagram received from the host. + * @param size Size of the buffer in bytes. * @return Number of received bytes on success, negative error - * code on failure + * code on failure. */ virtual nsapi_size_or_error_t recvfrom(SocketAddress *address, void *data, nsapi_size_t size); - /** Set remote peer address - * - * Set the remote address for next send() call and filtering - * for incomming packets. To reset the address, zero initialised + /** Set the remote address for next send() call and filtering + * of incoming packets. To reset the address, zero initialized * SocketAddress must be in the address parameter. * - * @param address The SocketAddress of the remote host - * @return 0 on success, negative error code on failure + * @param address The SocketAddress of the remote host. + * @return 0 on success, negative error code on failure. */ virtual nsapi_error_t connect(const SocketAddress &address); - /** Send a datagram to pre-specified remote. - * - * The socket must be connected to a remote host before send() call. - * Returns the number of bytes sent from the buffer. + /** Send a datagram to connected remote address. * * By default, send blocks until all data is sent. If socket is set to - * non-blocking or times out, a partial amount can be written. + * nonblocking or times out, a partial amount can be written. * NSAPI_ERROR_WOULD_BLOCK is returned if no data was written. * - * @param data Buffer of data to send to the host - * @param size Size of the buffer in bytes + * @note The socket must be connected to a remote host before send() call. + * + * @param data Buffer of data to send to the host. + * @param size Size of the buffer in bytes. * @return Number of sent bytes on success, negative error * code on failure. */ @@ -146,40 +133,44 @@ public: /** Receive data from a socket. * - * This is equivalent of calling recvfrom(NULL, data, size). + * This is equivalent to calling recvfrom(NULL, data, size). * - * If socket is connected, only packets coming from connected peer address + * If the socket is connected, only packets coming from a connected peer address * are accepted. * + * By default, recv blocks until some data is received. If socket is set to + * nonblocking or times out, NSAPI_ERROR_WOULD_BLOCK can be returned to + * indicate no data. + * * @note recv() is allowed write to data buffer even if error occurs. * - * By default, recv blocks until some data is received. If socket is set to - * non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK can be returned to - * indicate no data. - * - * @param data Destination buffer for data received from the host - * @param size Size of the buffer in bytes + * @param data Pointer to buffer for data received from the host. + * @param size Size of the buffer in bytes. * @return Number of received bytes on success, negative error * code on failure. */ virtual nsapi_size_or_error_t recv(void *data, nsapi_size_t size); - /** Not implemented for UDP + /** Not implemented for UDP. * - * @param error unused + * @param error Not used. * @return NSAPI_ERROR_UNSUPPORTED */ virtual Socket *accept(nsapi_error_t *error = NULL); - /** Not implemented for UDP + /** Not implemented for UDP. * - * @param backlog unused + * @param backlog Not used. * @return NSAPI_ERROR_UNSUPPORTED */ virtual nsapi_error_t listen(int backlog = 1); +#if !defined(DOXYGEN_ONLY) + protected: virtual nsapi_protocol_t get_proto(); + +#endif //!defined(DOXYGEN_ONLY) }; diff --git a/features/netsocket/WiFiInterface.h b/features/netsocket/WiFiInterface.h index 1b876d7e65..fd2266c882 100644 --- a/features/netsocket/WiFiInterface.h +++ b/features/netsocket/WiFiInterface.h @@ -22,104 +22,103 @@ #include "netsocket/NetworkInterface.h" #include "netsocket/WiFiAccessPoint.h" -/** WiFiInterface class +/** Common interface that is shared between Wi-Fi devices. * - * Common interface that is shared between WiFi devices * @addtogroup netsocket */ class WiFiInterface: public virtual NetworkInterface { public: - /** Get the default WiFi interface. + /** Get the default Wi-Fi interface. * * This is provided as a weak method so applications can override. - * Default behaviour is to get the target's default interface, if + * Default behavior is to get the target's default interface, if * any. * - * @return pointer to interface, if any + * @return pointer to interface, if any. */ static WiFiInterface *get_default_instance(); - /** Set the WiFi network credentials + /** Set the Wi-Fi network credentials. * - * @param ssid Name of the network to connect to - * @param pass Security passphrase to connect to the network + * @param ssid Name of the network to connect to. + * @param pass Security passphrase to connect to the network. * @param security Type of encryption for connection - * (defaults to NSAPI_SECURITY_NONE) - * @return 0 on success, or error code on failure + * (defaults to NSAPI_SECURITY_NONE). + * @return NSAPI_ERROR_OK on success, or error code on failure. */ virtual nsapi_error_t set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE) = 0; - /** Set the WiFi network channel + /** Set the Wi-Fi network channel. * - * @param channel Channel on which the connection is to be made, or 0 for any (Default: 0) - * @return 0 on success, or error code on failure + * @param channel Channel on which the connection is to be made, or 0 for any (Default: 0). + * @return NSAPI_ERROR_OK on success, or error code on failure. */ virtual nsapi_error_t set_channel(uint8_t channel) = 0; - /** Gets the current radio signal strength for active connection + /** Get the current radio signal strength for active connection. * * @return Connection strength in dBm (negative value), - * or 0 if measurement impossible + * or 0 if measurement impossible. */ virtual int8_t get_rssi() = 0; - /** Start the interface + /** Attempt to connect to a Wi-Fi network. * - * Attempts to connect to a WiFi network. - * - * @param ssid Name of the network to connect to - * @param pass Security passphrase to connect to the network - * @param security Type of encryption for connection (Default: NSAPI_SECURITY_NONE) - * @param channel Channel on which the connection is to be made, or 0 for any (Default: 0) - * @return 0 on success, or error code on failure + * @param ssid Name of the network to connect to. + * @param pass Security passphrase to connect to the network. + * @param security Type of encryption for connection (Default: NSAPI_SECURITY_NONE). + * @param channel Channel on which the connection is to be made, or 0 for any (Default: 0). + * @return NSAPI_ERROR_OK on success, or error code on failure. */ virtual nsapi_error_t connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE, uint8_t channel = 0) = 0; - /** Start the interface - * - * Attempts to connect to a WiFi network. Requires ssid and passphrase to be set. + /** Attempt to connect to a Wi-Fi network. Requires ssid and passphrase to be set. * If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned. * - * @return 0 on success, negative error code on failure + * @return NSAPI_ERROR_OK on success, negative error code on failure. */ virtual nsapi_error_t connect() = 0; - /** Stop the interface + /** Stop the interface. * - * @return 0 on success, or error code on failure + * @return NSAPI_ERROR_OK on success, or error code on failure. */ virtual nsapi_error_t disconnect() = 0; - /** Scan for available networks + /** Scan for available networks. * - * This function will block. If the @a count is 0, function will only return count of available networks, so that - * user can allocated necessary memory. If the \p count is grater than 0 and the a \p res is not NULL it'll be populated - * with discovered networks up to value of \p count. + * This function will block. If the count is 0, function will only return count of available networks, so that + * user can allocated necessary memory. If the count is grater than 0 and the a \p res is not NULL it'll be populated + * with discovered networks up to value of count. * - * @param res Pointer to allocated array to store discovered AP - * @param count Size of allocated @a res array, or 0 to only count available AP - * @return Number of entries in \p count, or if \p count was 0 number of available networks, - * negative on error see @a nsapi_error + * @param res Pointer to allocated array to store discovered APs. + * @param count Size of allocated res array, or 0 to only count available APs. + * @return Number of entries in res, or if count was 0 number of available networks. + * Negative on error (@see nsapi_types.h for nsapi_error). */ virtual nsapi_size_or_error_t scan(WiFiAccessPoint *res, nsapi_size_t count) = 0; + /** @copydoc NetworkInterface::wifiInterface + */ virtual WiFiInterface *wifiInterface() { return this; } +#if !defined(DOXYGEN_ONLY) protected: - /** Get the target's default WiFi interface. + /** Get the target's default Wi-Fi interface. * * This is provided as a weak method so targets can override. The * default implementation returns NULL. * - * @return pointer to interface, if any + * @return pointer to interface, if any. */ static WiFiInterface *get_target_default_instance(); +#endif //!defined(DOXYGEN_ONLY) }; #endif diff --git a/features/netsocket/cellular/generic_modem_driver/OnboardCellularInterface.cpp b/features/netsocket/cellular/generic_modem_driver/OnboardCellularInterface.cpp index fba410732b..5d81841984 100644 --- a/features/netsocket/cellular/generic_modem_driver/OnboardCellularInterface.cpp +++ b/features/netsocket/cellular/generic_modem_driver/OnboardCellularInterface.cpp @@ -29,9 +29,9 @@ */ OnboardCellularInterface::OnboardCellularInterface(bool debug) : - UARTCellularInterface(MDMTXD, MDMRXD, MDMDCD, MDMRTS, - MDMCTS, MDMRI, MDMDTR, MDMDSR, - MBED_CONF_PPP_CELL_IFACE_BAUD_RATE, MDM_PIN_POLARITY, debug) + UARTCellularInterface(MDMTXD, MDMRXD, MDMDCD, MDMRTS, + MDMCTS, MDMRI, MDMDTR, MDMDSR, + MBED_CONF_PPP_CELL_IFACE_BAUD_RATE, MDM_PIN_POLARITY, debug) { } diff --git a/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.cpp b/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.cpp index 455ef42bb0..dcf8484b0a 100644 --- a/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.cpp +++ b/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.cpp @@ -91,7 +91,7 @@ static bool get_MEID(ATCmdParser *at) { // Mobile equipment identifier bool success = at->send("AT+GSN") - && at->recv("%18[^\n]\nOK\n", dev_info.meid); + && at->recv("%18[^\n]\nOK\n", dev_info.meid); tr_debug("DevInfo: MEID=%s", dev_info.meid); return success; } @@ -156,10 +156,12 @@ static nsapi_error_t do_sim_pin_check(ATCmdParser *at, const char *pin) success = at->send("AT+CLCK=\"SC\",1,\"%s\"", pin) && at->recv("OK"); } else { /* use the SIM unlocked */ - success = at->send("AT+CLCK=\"SC\",0,\"%s\"",pin) && at->recv("OK"); + success = at->send("AT+CLCK=\"SC\",0,\"%s\"", pin) && at->recv("OK"); } - if (success) return NSAPI_ERROR_OK; + if (success) { + return NSAPI_ERROR_OK; + } return NSAPI_ERROR_AUTH_FAILURE; } @@ -170,12 +172,12 @@ static nsapi_error_t do_sim_pin_check(ATCmdParser *at, const char *pin) static nsapi_error_t do_change_sim_pin(ATCmdParser *at, const char *old_pin, const char *new_pin) { /* changes the SIM pin */ - bool success = at->send("AT+CPWD=\"SC\",\"%s\",\"%s\"", old_pin, new_pin) && at->recv("OK"); - if (success) { - return NSAPI_ERROR_OK; - } + bool success = at->send("AT+CPWD=\"SC\",\"%s\",\"%s\"", old_pin, new_pin) && at->recv("OK"); + if (success) { + return NSAPI_ERROR_OK; + } - return NSAPI_ERROR_AUTH_FAILURE; + return NSAPI_ERROR_AUTH_FAILURE; } static void set_nwk_reg_status_csd(unsigned int status) @@ -240,15 +242,15 @@ static void set_nwk_reg_status_psd(unsigned int status) static bool is_registered_csd() { - return (dev_info.reg_status_csd == CSD_REGISTERED) || - (dev_info.reg_status_csd == CSD_REGISTERED_ROAMING) || - (dev_info.reg_status_csd == CSD_CSFB_NOT_PREFERRED); + return (dev_info.reg_status_csd == CSD_REGISTERED) || + (dev_info.reg_status_csd == CSD_REGISTERED_ROAMING) || + (dev_info.reg_status_csd == CSD_CSFB_NOT_PREFERRED); } static bool is_registered_psd() { return (dev_info.reg_status_psd == PSD_REGISTERED) || - (dev_info.reg_status_psd == PSD_REGISTERED_ROAMING); + (dev_info.reg_status_psd == PSD_REGISTERED_ROAMING); } PPPCellularInterface::PPPCellularInterface(FileHandle *fh, bool debug) @@ -335,70 +337,70 @@ void PPPCellularInterface::set_new_sim_pin(const char *new_pin) bool PPPCellularInterface::nwk_registration(uint8_t nwk_type) { bool success = false; - bool registered = false; + bool registered = false; - char str[35]; - int retcode; - int retry_counter = 0; - unsigned int reg_status; + char str[35]; + int retcode; + int retry_counter = 0; + unsigned int reg_status; - success = nwk_type == PACKET_SWITCHED ? - _at->send("AT+CGREG=0") : - _at->send("AT+CREG=0") && _at->recv("OK\n"); + success = nwk_type == PACKET_SWITCHED ? + _at->send("AT+CGREG=0") : + _at->send("AT+CREG=0") && _at->recv("OK\n"); - success = _at->send("AT+COPS=0") //initiate auto-registration - && _at->recv("OK"); - if (!success) { - tr_error("Modem not responding."); - return false; - } + success = _at->send("AT+COPS=0") //initiate auto-registration + && _at->recv("OK"); + if (!success) { + tr_error("Modem not responding."); + return false; + } - //Network search - //If not registered after 60 attempts, i.e., 30 seconds wait, give up - tr_debug("Searching Network ..."); + //Network search + //If not registered after 60 attempts, i.e., 30 seconds wait, give up + tr_debug("Searching Network ..."); - while (!registered) { + while (!registered) { - if (retry_counter > 60) { - success = false; - goto give_up; - } + if (retry_counter > 60) { + success = false; + goto give_up; + } - success = nwk_type == PACKET_SWITCHED ? - _at->send("AT+CGREG?") - && _at->recv("+CGREG: %34[^\n]\n", str) - && _at->recv("OK\n") : - _at->send("AT+CREG?") - && _at->recv("+CREG: %34[^\n]\n", str) - && _at->recv("OK\n"); + success = nwk_type == PACKET_SWITCHED ? + _at->send("AT+CGREG?") + && _at->recv("+CGREG: %34[^\n]\n", str) + && _at->recv("OK\n") : + _at->send("AT+CREG?") + && _at->recv("+CREG: %34[^\n]\n", str) + && _at->recv("OK\n"); - retcode = sscanf(str, "%*u,%u", ®_status); + retcode = sscanf(str, "%*u,%u", ®_status); - if (retcode >= 1) { - if (nwk_type == PACKET_SWITCHED) { - set_nwk_reg_status_psd(reg_status); - if (is_registered_psd()) { - registered = true; - } - } else if (nwk_type == CIRCUIT_SWITCHED) { - set_nwk_reg_status_csd(reg_status); - if (is_registered_csd()) { - registered = true; - } - } - } + if (retcode >= 1) { + if (nwk_type == PACKET_SWITCHED) { + set_nwk_reg_status_psd(reg_status); + if (is_registered_psd()) { + registered = true; + } + } else if (nwk_type == CIRCUIT_SWITCHED) { + set_nwk_reg_status_csd(reg_status); + if (is_registered_csd()) { + registered = true; + } + } + } - if (registered) { - break; - } else { - wait_ms(500); - } + if (registered) { + break; + } else { + wait_ms(500); + } - retry_counter++; - } + retry_counter++; + } - give_up: - return registered; +give_up: + return registered; } bool PPPCellularInterface::is_connected() @@ -444,7 +446,8 @@ nsapi_error_t PPPCellularInterface::initialize_sim_card() return nsapi_error; } -void PPPCellularInterface::set_sim_pin(const char *pin) { +void PPPCellularInterface::set_sim_pin(const char *pin) +{ /* overwrite the default pin by user provided pin */ _pin = pin; } @@ -473,11 +476,11 @@ nsapi_error_t PPPCellularInterface::setup_context_and_credentials() retry_without_dual_stack: #endif success = _at->send("AT" - "+FCLASS=0;" // set to connection (ATD) to data mode - "+CGDCONT=" CTX ",\"%s\",\"%s%s\"", - pdp_type, auth, _apn - ) - && _at->recv("OK"); + "+FCLASS=0;" // set to connection (ATD) to data mode + "+CGDCONT=" CTX ",\"%s\",\"%s%s\"", + pdp_type, auth, _apn + ) + && _at->recv("OK"); #if NSAPI_PPP_IPV4_AVAILABLE && NSAPI_PPP_IPV6_AVAILABLE if (_stack == IPV4V6_STACK) { @@ -513,7 +516,7 @@ void PPPCellularInterface::setup_at_parser() } _at = new ATCmdParser(_fh, OUTPUT_ENTER_KEY, AT_PARSER_BUFFER_SIZE, AT_PARSER_TIMEOUT, - _debug_trace_on ? true : false); + _debug_trace_on ? true : false); /* Error cases, out of band handling */ _at->oob("ERROR", callback(parser_abort, _at)); @@ -583,7 +586,7 @@ nsapi_error_t PPPCellularInterface::connect() } do { - retry_init: +retry_init: retcode = NSAPI_ERROR_OK; @@ -608,12 +611,12 @@ nsapi_error_t PPPCellularInterface::connect() } success = nwk_registration(PACKET_SWITCHED) //perform network registration - && get_CCID(_at)//get integrated circuit ID of the SIM - && get_IMSI(_at)//get international mobile subscriber information - && get_IMEI(_at)//get international mobile equipment identifier - && get_MEID(_at)//its same as IMEI - && set_CMGF(_at)//set message format for SMS - && set_CNMI(_at);//set new SMS indication + && get_CCID(_at)//get integrated circuit ID of the SIM + && get_IMSI(_at)//get international mobile subscriber information + && get_IMEI(_at)//get international mobile equipment identifier + && get_MEID(_at)//its same as IMEI + && set_CMGF(_at)//set message format for SMS + && set_CNMI(_at);//set new SMS indication if (!success) { retcode = NSAPI_ERROR_NO_CONNECTION; @@ -712,7 +715,7 @@ nsapi_error_t PPPCellularInterface::connect() _connect_status = NSAPI_STATUS_GLOBAL_UP; } } while ((_connect_status == NSAPI_STATUS_CONNECTING && _connect_is_blocking) && - apn_config && *apn_config); + apn_config && *apn_config); if (retcode != NSAPI_ERROR_OK) { diff --git a/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.h b/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.h index 3a30ecc014..525c7c9f9c 100644 --- a/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.h +++ b/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.h @@ -30,14 +30,14 @@ class NetworkStack; * UBX-13001820 - AT Commands Example Application Note (Section 4.1.4.5) */ typedef enum { - GSM=0, - COMPACT_GSM=1, - UTRAN=2, - EDGE=3, - HSDPA=4, - HSUPA=5, - HSDPA_HSUPA=6, - LTE=7 + GSM = 0, + COMPACT_GSM = 1, + UTRAN = 2, + EDGE = 3, + HSDPA = 4, + HSUPA = 5, + HSDPA_HSUPA = 6, + LTE = 7 } radio_access_nwk_type; /** @@ -45,7 +45,7 @@ typedef enum { * to connect. */ typedef enum { - CIRCUIT_SWITCHED=0, + CIRCUIT_SWITCHED = 0, PACKET_SWITCHED } nwk_type; @@ -54,15 +54,15 @@ typedef enum { * UBX-13001820 - AT Commands Example Application Note (Section 7.10.3) */ typedef enum { - CSD_NOT_REGISTERED_NOT_SEARCHING=0, - CSD_REGISTERED=1, - CSD_NOT_REGISTERED_SEARCHING=2, - CSD_REGISTRATION_DENIED=3, - CSD_UNKNOWN_COVERAGE=4, - CSD_REGISTERED_ROAMING=5, - CSD_SMS_ONLY=6, - CSD_SMS_ONLY_ROAMING=7, - CSD_CSFB_NOT_PREFERRED=9 + CSD_NOT_REGISTERED_NOT_SEARCHING = 0, + CSD_REGISTERED = 1, + CSD_NOT_REGISTERED_SEARCHING = 2, + CSD_REGISTRATION_DENIED = 3, + CSD_UNKNOWN_COVERAGE = 4, + CSD_REGISTERED_ROAMING = 5, + CSD_SMS_ONLY = 6, + CSD_SMS_ONLY_ROAMING = 7, + CSD_CSFB_NOT_PREFERRED = 9 } nwk_registration_status_csd; /** @@ -70,20 +70,20 @@ typedef enum { * UBX-13001820 - AT Commands Example Application Note (Section 18.27.3) */ typedef enum { - PSD_NOT_REGISTERED_NOT_SEARCHING=0, - PSD_REGISTERED=1, - PSD_NOT_REGISTERED_SEARCHING=2, - PSD_REGISTRATION_DENIED=3, - PSD_UNKNOWN_COVERAGE=4, - PSD_REGISTERED_ROAMING=5, - PSD_EMERGENCY_SERVICES_ONLY=8 + PSD_NOT_REGISTERED_NOT_SEARCHING = 0, + PSD_REGISTERED = 1, + PSD_NOT_REGISTERED_SEARCHING = 2, + PSD_REGISTRATION_DENIED = 3, + PSD_UNKNOWN_COVERAGE = 4, + PSD_REGISTERED_ROAMING = 5, + PSD_EMERGENCY_SERVICES_ONLY = 8 } nwk_registration_status_psd; typedef struct { - char ccid[20+1]; //!< Integrated Circuit Card ID - char imsi[15+1]; //!< International Mobile Station Identity - char imei[15+1]; //!< International Mobile Equipment Identity - char meid[18+1]; //!< Mobile Equipment IDentifier + char ccid[20 + 1]; //!< Integrated Circuit Card ID + char imsi[15 + 1]; //!< International Mobile Station Identity + char imei[15 + 1]; //!< International Mobile Equipment Identity + char meid[18 + 1]; //!< Mobile Equipment IDentifier int flags; radio_access_nwk_type rat; nwk_registration_status_csd reg_status_csd; @@ -127,7 +127,7 @@ public: * * @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead. * - * Please check documentation of connect() for default behaviour of APN settings. + * Please check documentation of connect() for default behavior of APN settings. * * @param apn Access point name * @param uname optionally, Username @@ -135,7 +135,7 @@ public: */ MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.") virtual void set_credentials(const char *apn, const char *uname = 0, - const char *pwd = 0); + const char *pwd = 0); /** Set the pin code for SIM card * @@ -176,7 +176,7 @@ public: * by the cellular modem over PPP interface. * * If the SIM requires a PIN, and it is not set/invalid, NSAPI_ERROR_AUTH_ERROR is returned. - * For APN setup, default behaviour is to use 'internet' as APN string and assuming no authentication + * For APN setup, default behavior is to use 'internet' as APN string and assuming no authentication * is required, i.e., username and password are not set. Optionally, a database lookup can be requested * by turning on the APN database lookup feature. In order to do so, add 'MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP' * in your mbed_app.json. APN database is by no means exhaustive. It contains a short list of some public @@ -403,7 +403,7 @@ protected: * * @return true if registration is successful */ - bool nwk_registration(uint8_t nwk_type=PACKET_SWITCHED); + bool nwk_registration(uint8_t nwk_type = PACKET_SWITCHED); }; diff --git a/features/netsocket/cellular/generic_modem_driver/TESTS/unit_tests/default/main.cpp b/features/netsocket/cellular/generic_modem_driver/TESTS/unit_tests/default/main.cpp index 037c692963..c2db87a543 100644 --- a/features/netsocket/cellular/generic_modem_driver/TESTS/unit_tests/default/main.cpp +++ b/features/netsocket/cellular/generic_modem_driver/TESTS/unit_tests/default/main.cpp @@ -86,10 +86,10 @@ static void unlock(); * Verification tests for a successful porting * These tests must pass: * - * test_udp_echo() - * test_tcp_echo_async - * test_connect_credentials - * test_connect_preset_credentials + * test_udp_echo() + * test_tcp_echo_async + * test_connect_credentials + * test_connect_preset_credentials */ /** @@ -148,7 +148,7 @@ void test_tcp_echo_async() TEST_ASSERT(do_connect(&driver) == 0); TEST_ASSERT( - driver.gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0); + driver.gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0); host_address.set_port(MBED_CONF_APP_ECHO_TCP_PORT); tr_debug("TCP: Server %s address: %s on port %d.", @@ -172,7 +172,7 @@ void test_tcp_echo_async() drop_connection(&driver); tr_debug("TCP packets of size up to %d byte(s) echoed asynchronously and successfully.", - MBED_CONF_APP_TCP_MAX_PACKET_SIZE); + MBED_CONF_APP_TCP_MAX_PACKET_SIZE); } /** @@ -196,7 +196,7 @@ void test_connect_preset_credentials() driver.disconnect(); driver.set_sim_pin(MBED_CONF_APP_DEFAULT_PIN); driver.set_credentials(MBED_CONF_APP_APN, MBED_CONF_APP_USERNAME, - MBED_CONF_APP_PASSWORD); + MBED_CONF_APP_PASSWORD); int num_retries = 0; nsapi_error_t err = NSAPI_ERROR_OK; while (!driver.is_connected()) { @@ -226,10 +226,11 @@ utest::v1::status_t test_setup(const size_t number_of_cases) */ Case cases[] = { Case("UDP echo test", test_udp_echo), #if MBED_CONF_LWIP_TCP_ENABLED - Case("TCP async echo test", test_tcp_echo_async), + Case("TCP async echo test", test_tcp_echo_async), #endif - Case("Connect with credentials", test_connect_credentials), - Case("Connect with preset credentials", test_connect_preset_credentials) }; + Case("Connect with credentials", test_connect_credentials), + Case("Connect with preset credentials", test_connect_preset_credentials) + }; Specification specification(test_setup, cases); @@ -255,7 +256,7 @@ static nsapi_error_t do_connect(OnboardCellularInterface *iface) nsapi_error_t err = NSAPI_ERROR_OK; while (!iface->is_connected()) { err = driver.connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, - MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD); + MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD); if (err == NSAPI_ERROR_OK || num_retries > MBED_CONF_APP_MAX_RETRIES) { break; } @@ -284,14 +285,14 @@ static int fix(int size, int limit) static void do_udp_echo(UDPSocket *sock, SocketAddress *host_address, int size) { bool success = false; - void * recv_data = malloc(size); + void *recv_data = malloc(size); TEST_ASSERT(recv_data != NULL); // Retry this a few times, don't want to fail due to a flaky link for (int x = 0; !success && (x < NUM_UDP_RETRIES); x++) { tr_debug("Echo testing UDP packet size %d byte(s), try %d.", size, x + 1); - if ((sock->sendto(*host_address, (void*) test_data, size) == size) - && (sock->recvfrom(host_address, recv_data, size) == size)) { + if ((sock->sendto(*host_address, (void *) test_data, size) == size) + && (sock->recvfrom(host_address, recv_data, size) == size)) { TEST_ASSERT(memcmp(test_data, recv_data, size) == 0); success = true; } @@ -340,7 +341,7 @@ static void async_cb(bool *callback_triggered) static void do_tcp_echo_async(TCPSocket *sock, int size, bool *callback_triggered) { - void * recv_data = malloc(size); + void *recv_data = malloc(size); int recv_size = 0; int remaining_size; int x, y; @@ -370,7 +371,7 @@ static void do_tcp_echo_async(TCPSocket *sock, int size, y = memcmp(test_data, recv_data, size); if (y != 0) { tr_debug("Sent %d, |%*.*s|", size, size, size, test_data); - tr_debug("Rcvd %d, |%*.*s|", size, size, size, (char * ) recv_data); + tr_debug("Rcvd %d, |%*.*s|", size, size, size, (char *) recv_data); // We do not assert a failure here because ublox TCP echo server doesn't send // back original data. It actually constructs a ublox message string. They need to fix it as // at the minute in case of TCP, their server is not behaving like a echo TCP server. @@ -386,9 +387,9 @@ static void do_tcp_echo_async(TCPSocket *sock, int size, */ static void use_connection(OnboardCellularInterface *driver) { - const char * ip_address = driver->get_ip_address(); - const char * net_mask = driver->get_netmask(); - const char * gateway = driver->get_gateway(); + const char *ip_address = driver->get_ip_address(); + const char *net_mask = driver->get_netmask(); + const char *gateway = driver->get_gateway(); TEST_ASSERT(driver->is_connected()); diff --git a/features/netsocket/cellular/generic_modem_driver/UARTCellularInterface.cpp b/features/netsocket/cellular/generic_modem_driver/UARTCellularInterface.cpp index 87ee0f3349..17cf64206f 100644 --- a/features/netsocket/cellular/generic_modem_driver/UARTCellularInterface.cpp +++ b/features/netsocket/cellular/generic_modem_driver/UARTCellularInterface.cpp @@ -19,8 +19,8 @@ UARTCellularInterface::UARTCellularInterface(PinName txd, PinName rxd, PinName dcd, PinName rts, PinName cts, PinName ri, PinName dtr, PinName dsr, int baud, bool active_high, bool debug) : - PPPCellularInterface(&_serial, debug), - _serial(txd, rxd, baud) + PPPCellularInterface(&_serial, debug), + _serial(txd, rxd, baud) { _dcd_pin = dcd; _active_high = active_high; diff --git a/features/netsocket/cellular/generic_modem_driver/UARTCellularInterface.h b/features/netsocket/cellular/generic_modem_driver/UARTCellularInterface.h index d5e72d5ea7..b35bfa0a84 100644 --- a/features/netsocket/cellular/generic_modem_driver/UARTCellularInterface.h +++ b/features/netsocket/cellular/generic_modem_driver/UARTCellularInterface.h @@ -42,9 +42,9 @@ public: */ MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.") UARTCellularInterface(PinName tx, PinName rx, PinName dcd = NC, PinName rts = NC, PinName cts = NC, PinName ri = NC, - PinName dtr = NC, PinName dsr = NC, int baud = MBED_CONF_PPP_CELL_IFACE_BAUD_RATE, - bool active_high = false, - bool debug = false); + PinName dtr = NC, PinName dsr = NC, int baud = MBED_CONF_PPP_CELL_IFACE_BAUD_RATE, + bool active_high = false, + bool debug = false); /** Destructor * diff --git a/features/netsocket/cellular/onboard_modem_api.h b/features/netsocket/cellular/onboard_modem_api.h index 0e2a7df52c..702dcba304 100644 --- a/features/netsocket/cellular/onboard_modem_api.h +++ b/features/netsocket/cellular/onboard_modem_api.h @@ -17,9 +17,9 @@ #ifndef ONBOARD_MODEM_API_H_ #define ONBOARD_MODEM_API_H_ -/** onboard_modem_api is a standardizing API for Modem type devices under mbed-os. +/** onboard_modem_api is a standardizing API for Modem type devices under Mbed OS. * It provides a simple hardware abstraction layer on top of the modem drivers - * written for mbed-os. + * written for Mbed OS. * * It is required from the engineers porting any modem type device (e.g., Cellular) * to provide an implementation of this API in their respective target folder as well as diff --git a/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/mbed_lib.json b/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/mbed_lib.json new file mode 100644 index 0000000000..d54a2784ea --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/mbed_lib.json @@ -0,0 +1,7 @@ +{ + "name": "smsc9220-emac", + "config": { + "rx-ring-len": 1, + "tx-ring-len": 1 + } +} diff --git a/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.cpp b/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.cpp new file mode 100644 index 0000000000..167024e11a --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.cpp @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2018 Arm Limited + * + * 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. + */ + +#include +#include +#include +#include + +#include "mbed_interface.h" +#include "mbed_wait_api.h" +#include "mbed_assert.h" +#include "netsocket/nsapi_types.h" +#include "mbed_shared_queues.h" + +#include "smsc9220_emac.h" +#include "smsc9220_eth_drv.h" + +#ifndef SMSC9220_ETH +#error "SMSC9220_ETH should be defined, check device_cfg.h!" +#endif + +#ifndef SMSC9220_Ethernet_Interrupt_Handler +#error "SMSC9220_Ethernet_Interrupt_Handler should be defined to platform's \ +Ethernet IRQ handler!" +#endif + +static SMSC9220_EMAC *board_emac_pointer = NULL; +const struct smsc9220_eth_dev_t* SMSC9220_EMAC::dev = &SMSC9220_ETH_DEV; + +extern "C" void SMSC9220_Ethernet_Interrupt_Handler(void) +{ + if (smsc9220_get_interrupt(SMSC9220_EMAC::dev, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL)) { + board_emac_pointer->rx_isr(); + smsc9220_clear_interrupt(SMSC9220_EMAC::dev, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); + smsc9220_disable_interrupt(SMSC9220_EMAC::dev, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); + } +} + +SMSC9220_EMAC::SMSC9220_EMAC() : receiver_thread(LINK_STATUS_THREAD_PRIORITY, + (uint32_t)LINK_STATUS_THREAD_STACKSIZE) +{ +} + +/** \brief Ethernet receive interrupt handler + * + * This function handles the receive interrupt. + */ +void SMSC9220_EMAC::rx_isr() +{ + receiver_thread.flags_set(FLAG_RX); +} + +/** \brief Allocates a emac_mem_buf_t and returns the data from the incoming + * packet. + * + * \return a emac_mem_buf_t filled with the received packet + * (including MAC header) + */ +emac_mem_buf_t *SMSC9220_EMAC::low_level_input() +{ + emac_mem_buf_t *p = NULL; + uint32_t message_length = 0; + + message_length = smsc9220_peek_next_packet_size(dev); + if (message_length == 0) { + return p; + } else { + /* The Ethernet controller cannot remove CRC from the end of the + * incoming packet, thus it should be taken into account when + * calculating the actual message length.*/ + message_length -= CRC_LENGTH_BYTES; + } + + p = _memory_manager->alloc_heap(message_length, SMSC9220_BUFF_ALIGNMENT); + + if (p != NULL) { + _RXLockMutex.lock(); + smsc9220_receive_by_chunks(dev, (char*)_memory_manager->get_ptr(p), + _memory_manager->get_len(p)); + _RXLockMutex.unlock(); + } + + return p; +} + +/** \brief Receiver thread. + * + * Woken by thread flags to receive packets or clean up transmit + * + * \param[in] params pointer to the interface data + */ +void SMSC9220_EMAC::receiver_thread_function(void* params) +{ + struct SMSC9220_EMAC *smsc9220_enet = static_cast(params); + + while(1) { + uint32_t flags = ThisThread::flags_wait_any(FLAG_RX); + + if (flags & FLAG_RX) { + smsc9220_enet->packet_rx(); + } + } +} + +/** \brief Packet reception task + * + * This task is called when a packet is received. It will + * pass the packet to the Network Stack. + */ +void SMSC9220_EMAC::packet_rx() +{ + emac_mem_buf_t *p; + p = low_level_input(); + if(p != NULL) { + _emac_link_input_cb(p); + } + smsc9220_enable_interrupt(dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); +} + +bool SMSC9220_EMAC::link_out(emac_mem_buf_t *buf) +{ + if(buf == NULL) { + return false; + } else { + uint32_t buffer_chain_length = 0; + enum smsc9220_error_t error = SMSC9220_ERROR_NONE; + /* If buffer is chained or not aligned then + * make a contiguous aligned copy of it */ + if (_memory_manager->get_next(buf) || + reinterpret_cast(_memory_manager->get_ptr(buf)) % + SMSC9220_BUFF_ALIGNMENT) { + emac_mem_buf_t *copy_buf; + copy_buf = _memory_manager->alloc_heap( + _memory_manager->get_total_len(buf), + SMSC9220_BUFF_ALIGNMENT); + if (NULL == copy_buf) { + _memory_manager->free(buf); + return false; + } + + /* Copy to new buffer and free original */ + _memory_manager->copy(copy_buf, buf); + _memory_manager->free(buf); + buf = copy_buf; + } + + buffer_chain_length = _memory_manager->get_total_len(buf); + + _TXLockMutex.lock(); + error = smsc9220_send_by_chunks(dev, + buffer_chain_length, + true, + (const char*)_memory_manager->get_ptr(buf), + _memory_manager->get_len(buf)); + if (error != SMSC9220_ERROR_NONE) { + _TXLockMutex.unlock(); + return false; + } + _TXLockMutex.unlock(); + return true; + } +} + +void SMSC9220_EMAC::link_status_task() +{ + uint32_t phy_basic_status_reg_value = 0; + bool current_link_status_up = false; + + /* Get current status */ + smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_BSTATUS, + &phy_basic_status_reg_value); + + current_link_status_up = (bool)(phy_basic_status_reg_value & + (1ul << (PHY_REG_BSTATUS_LINK_STATUS_INDEX))); + + /* Compare with previous state */ + if (current_link_status_up != _prev_link_status_up) { + _emac_link_state_cb(current_link_status_up); + _prev_link_status_up = current_link_status_up; + } + +} + +bool SMSC9220_EMAC::power_up() +{ + board_emac_pointer = this; + receiver_thread.start(callback(&SMSC9220_EMAC::receiver_thread_function, + this)); + + /* Initialize the hardware */ + enum smsc9220_error_t init_successful = smsc9220_init(dev, &wait_ms); + if (init_successful != SMSC9220_ERROR_NONE) { + return false; + } + + /* Init FIFO level interrupts: use Rx status level irq to trigger + * interrupts for any non-processed packets, while Tx is not irq driven */ + smsc9220_set_fifo_level_irq(dev, SMSC9220_FIFO_LEVEL_IRQ_RX_STATUS_POS, + SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN); + smsc9220_set_fifo_level_irq(dev, SMSC9220_FIFO_LEVEL_IRQ_TX_STATUS_POS, + SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN); + smsc9220_set_fifo_level_irq(dev, SMSC9220_FIFO_LEVEL_IRQ_TX_DATA_POS, + SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX); + + /* Enable Ethernet interrupts in NVIC */ + NVIC_EnableIRQ(ETHERNET_IRQn); + smsc9220_enable_interrupt(dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); + + /* Trigger thread to deal with any RX packets that arrived + * before receiver_thread was started */ + rx_isr(); + _prev_link_status_up = PHY_STATE_LINK_DOWN; + mbed::mbed_event_queue()->call(mbed::callback(this, + &SMSC9220_EMAC::link_status_task)); + + /* Allow the Link Status task to detect the initial link state */ + wait_ms(10); + _link_status_task_handle = mbed::mbed_event_queue()->call_every( + LINK_STATUS_TASK_PERIOD_MS, + mbed::callback(this, + &SMSC9220_EMAC::link_status_task)); + + return true; +} + +uint32_t SMSC9220_EMAC::get_mtu_size() const +{ + return SMSC9220_ETH_MTU_SIZE; +} + +uint32_t SMSC9220_EMAC::get_align_preference() const +{ + return SMSC9220_BUFF_ALIGNMENT; +} + +void SMSC9220_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, SMSC9220_ETH_IF_NAME, (size < sizeof(SMSC9220_ETH_IF_NAME)) ? + size : sizeof(SMSC9220_ETH_IF_NAME)); +} + +uint8_t SMSC9220_EMAC::get_hwaddr_size() const +{ + return SMSC9220_HWADDR_SIZE; +} + +bool SMSC9220_EMAC::get_hwaddr(uint8_t *addr) const +{ + if(smsc9220_read_mac_address(dev, (char*)addr) == SMSC9220_ERROR_NONE) { + return true; + } else { + return false; + } +} + +void SMSC9220_EMAC::set_hwaddr(const uint8_t *addr) +{ + if (!addr) { + return; + } + + memcpy(_hwaddr, addr, sizeof _hwaddr); + uint32_t mac_low = 0; + uint32_t mac_high = 0; + + /* Using local variables to make sure the right alignment is used */ + memcpy((void*)&mac_low, (void*)addr, 4); + memcpy((void*)&mac_high, (void*)(addr+4), 2); + + if (smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_ADDRL, mac_low)) { + return; + } + if (smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_ADDRH, mac_high)) { + return; + } +} + +void SMSC9220_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + _emac_link_input_cb = input_cb; +} + +void SMSC9220_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + _emac_link_state_cb = state_cb; +} + +void SMSC9220_EMAC::add_multicast_group(const uint8_t *addr) +{ + // No action for now +} + +void SMSC9220_EMAC::remove_multicast_group(const uint8_t *addr) +{ + // No action for now +} + +void SMSC9220_EMAC::set_all_multicast(bool all) +{ + // No action for now +} + +void SMSC9220_EMAC::power_down() +{ + // No action for now +} + +void SMSC9220_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + _memory_manager = &mem_mngr; +} + + +SMSC9220_EMAC &SMSC9220_EMAC::get_instance() { + static SMSC9220_EMAC emac; + return emac; +} + +/* Weak so a module can override */ +MBED_WEAK EMAC &EMAC::get_default_instance() { + return SMSC9220_EMAC::get_instance(); +} diff --git a/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.h b/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.h new file mode 100644 index 0000000000..58762d4f59 --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2018 Arm Limited + * + * 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. + */ + +#ifndef SMSC9220_EMAC_H_ +#define SMSC9220_EMAC_H_ + +#include "EMAC.h" +#include "mbed.h" +#include "rtos/Mutex.h" + +#include "smsc9220_emac_config.h" + +class SMSC9220_EMAC : public EMAC { +public: + SMSC9220_EMAC(); + + static SMSC9220_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may + * or may not align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct + * size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own + * HW address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is + * provided the stack would normally use that, but it could be overridden, + * eg for test purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that + * interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given + * interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + + void rx_isr(); + + static const struct smsc9220_eth_dev_t *dev; + +private: + void packet_rx(); + void link_status_task(); + bool low_level_init_successful(); + emac_mem_buf_t *low_level_input(); + static void receiver_thread_function(void* params); + + rtos::Mutex _TXLockMutex; + rtos::Mutex _RXLockMutex; + bool _prev_link_status_up; + int _link_status_task_handle; + uint8_t _hwaddr[SMSC9220_HWADDR_SIZE]; + + Thread receiver_thread; + EMACMemoryManager *_memory_manager; + emac_link_input_cb_t _emac_link_input_cb; + emac_link_state_change_cb_t _emac_link_state_cb; + +}; + +#endif /* SMSC9220_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac_config.h b/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac_config.h new file mode 100644 index 0000000000..f8299a84b6 --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac_config.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018 Arm Limited + * + * 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. + */ + +#ifndef SMSC9220_EMAC_CONFIG_H +#define SMSC9220_EMAC_CONFIG_H + +#include "cmsis_os.h" + +#define SMSC9220_HWADDR_SIZE 6U +#define SMSC9220_BUFF_ALIGNMENT 4U + +/* + * Maximum Transfer Unit + * The IEEE 802.3 specification limits the data portion of the 802.3 frame + * to a minimum of 46 and a maximum of 1522 bytes, this is on L2 level. + */ +#define SMSC9220_ETH_MTU_SIZE 1500U +#define SMSC9220_ETH_IF_NAME "smsc9220" + +/** \brief Defines for receiver thread */ +#define FLAG_RX 1U +#define LINK_STATUS_THREAD_PRIORITY (osPriorityNormal) +#define LINK_STATUS_THREAD_STACKSIZE 2048U +#define LINK_STATUS_TASK_PERIOD_MS 200U +#define PHY_STATE_LINK_DOWN false +#define PHY_STATE_LINK_UP true +#define CRC_LENGTH_BYTES 4U + +#endif /* SMSC9220_EMAC_CONFIG_H */ diff --git a/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_emac.cpp b/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_emac.cpp index 5e19ec2a52..c664d53f2a 100644 --- a/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_emac.cpp +++ b/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_emac.cpp @@ -1,4 +1,5 @@ #include "cmsis_os.h" +#include "rtos/ThisThread.h" #include "netsocket/nsapi_types.h" #include "mbed_shared_queues.h" #include "ethernet_api.h" @@ -157,7 +158,7 @@ void RZ_A1_EMAC::_recv_callback(void) { } void RZ_A1_EMAC::recv_callback(void) { - recvThread.signal_set(1); + recvThread.flags_set(1); } void RZ_A1_EMAC::recv_task(void) { @@ -166,7 +167,7 @@ void RZ_A1_EMAC::recv_task(void) { int cnt; while (1) { - rtos::Thread::signal_wait(1); + rtos::ThisThread::flags_wait_all(1); for (cnt = 0; cnt < 16; cnt++) { recv_size = ethernet_receive(); if (recv_size == 0) { diff --git a/features/netsocket/emac-drivers/TARGET_STM_EMAC/stm32xx_emac.cpp b/features/netsocket/emac-drivers/TARGET_STM_EMAC/stm32xx_emac.cpp index 9d08524175..56e29950ee 100644 --- a/features/netsocket/emac-drivers/TARGET_STM_EMAC/stm32xx_emac.cpp +++ b/features/netsocket/emac-drivers/TARGET_STM_EMAC/stm32xx_emac.cpp @@ -2,6 +2,7 @@ #include "cmsis_os.h" +#include "mbed.h" #include "mbed_interface.h" #include "mbed_assert.h" #include "mbed_shared_queues.h" @@ -474,6 +475,8 @@ void mbed_default_mac_address(char *mac) bool STM32_EMAC::power_up() { + sleep_manager_lock_deep_sleep(); + /* Initialize the hardware */ if (!low_level_init_successful()) { return false; @@ -556,6 +559,7 @@ void STM32_EMAC::set_all_multicast(bool all) void STM32_EMAC::power_down() { /* No-op at this stage */ + sleep_manager_unlock_deep_sleep(); } void STM32_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) diff --git a/features/netsocket/mbed_lib.json b/features/netsocket/mbed_lib.json index 3575b47ebc..6eef56e3b7 100644 --- a/features/netsocket/mbed_lib.json +++ b/features/netsocket/mbed_lib.json @@ -6,6 +6,7 @@ "default-wifi-ssid": null, "default-wifi-password": null, "default-wifi-security": "NONE", + "default-cellular-sim-pin": null, "default-cellular-apn": null, "default-cellular-username": null, "default-cellular-password": null, diff --git a/features/netsocket/nsapi.h b/features/netsocket/nsapi.h index 21047dad73..a9b41932ec 100644 --- a/features/netsocket/nsapi.h +++ b/features/netsocket/nsapi.h @@ -40,6 +40,7 @@ #include "netsocket/UDPSocket.h" #include "netsocket/TCPSocket.h" #include "netsocket/TCPServer.h" +#include "netsocket/TLSSocket.h" #endif diff --git a/features/netsocket/nsapi_types.h b/features/netsocket/nsapi_types.h index 232236b6c6..c819c471a8 100644 --- a/features/netsocket/nsapi_types.h +++ b/features/netsocket/nsapi_types.h @@ -97,7 +97,7 @@ typedef signed int nsapi_error_t; */ typedef unsigned int nsapi_size_t; -/** Type used to represent either a size or error pased through sockets +/** Type used to represent either a size or error passed through sockets * * A valid nsapi_size_or_error_t is either a non-negative size or a * negative error code from the nsapi_error_t @@ -351,7 +351,7 @@ typedef struct nsapi_stack_api { */ nsapi_error_t (*add_dns_server)(nsapi_stack_t *stack, nsapi_addr_t addr); - /* Set stack-specific stack options + /** Set stack-specific stack options * * The setstackopt allow an application to pass stack-specific hints * to the underlying stack. For unsupported options, @@ -367,7 +367,7 @@ typedef struct nsapi_stack_api { nsapi_error_t (*setstackopt)(nsapi_stack_t *stack, int level, int optname, const void *optval, unsigned optlen); - /* Get stack-specific stack options + /** Get stack-specific stack options * * The getstackopt allow an application to retrieve stack-specific hints * from the underlying stack. For unsupported options, @@ -567,7 +567,7 @@ typedef struct nsapi_stack_api { void (*socket_attach)(nsapi_stack_t *stack, nsapi_socket_t socket, void (*callback)(void *), void *data); - /* Set stack-specific socket options + /** Set stack-specific socket options * * The setsockopt allow an application to pass stack-specific hints * to the underlying stack. For unsupported options, @@ -584,7 +584,7 @@ typedef struct nsapi_stack_api { nsapi_error_t (*setsockopt)(nsapi_stack_t *stack, nsapi_socket_t socket, int level, int optname, const void *optval, unsigned optlen); - /* Get stack-specific socket options + /** Get stack-specific socket options * * The getstackopt allow an application to retrieve stack-specific hints * from the underlying stack. For unsupported options, diff --git a/features/nfc/nfc/NFCEEPROM.h b/features/nfc/nfc/NFCEEPROM.h index ad485d2cf7..e431823caf 100644 --- a/features/nfc/nfc/NFCEEPROM.h +++ b/features/nfc/nfc/NFCEEPROM.h @@ -126,8 +126,8 @@ private: nfc_eeprom_idle, nfc_eeprom_write_start_session, - nfc_eeprom_write_write_bytes, nfc_eeprom_write_write_size, + nfc_eeprom_write_write_bytes, nfc_eeprom_write_end_session, nfc_eeprom_read_start_session, diff --git a/features/nfc/source/nfc/NFCEEPROM.cpp b/features/nfc/source/nfc/NFCEEPROM.cpp index 518b652e4c..023bd153b5 100644 --- a/features/nfc/source/nfc/NFCEEPROM.cpp +++ b/features/nfc/source/nfc/NFCEEPROM.cpp @@ -138,8 +138,8 @@ void NFCEEPROM::on_session_started(bool success) handle_error(NFC_ERR_CONTROLLER); // An EEPROM is not really a controller but close enough return; } - _current_op = nfc_eeprom_write_write_bytes; - continue_write(); + _current_op = nfc_eeprom_write_write_size; + _driver->write_size(ac_buffer_reader_readable(&_ndef_buffer_reader)); break; case nfc_eeprom_read_start_session: @@ -272,10 +272,8 @@ void NFCEEPROM::on_size_written(bool success) return; } - // End session - _current_op = nfc_eeprom_write_end_session; - _operation_result = NFC_OK; - _driver->end_session(); + _current_op = nfc_eeprom_write_write_bytes; + continue_write(); break; case nfc_eeprom_erase_write_max_size: if (!success) { @@ -371,9 +369,10 @@ void NFCEEPROM::continue_write() // Continue writing _driver->write_bytes(_eeprom_address, ac_buffer_reader_current_buffer_pointer(&_ndef_buffer_reader), ac_buffer_reader_current_buffer_length(&_ndef_buffer_reader)); } else { - // Now update size - _current_op = nfc_eeprom_write_write_size; - _driver->write_size(_eeprom_address); + // we are done + _current_op = nfc_eeprom_write_end_session; + _operation_result = NFC_OK; + _driver->end_session(); } } diff --git a/features/storage/TESTS/blockdevice/flashsim_block_device/main.cpp b/features/storage/TESTS/blockdevice/flashsim_block_device/main.cpp index 5b75a00e56..8da5794e43 100644 --- a/features/storage/TESTS/blockdevice/flashsim_block_device/main.cpp +++ b/features/storage/TESTS/blockdevice/flashsim_block_device/main.cpp @@ -38,7 +38,7 @@ void functionality_test() uint8_t *dummy = new (std::nothrow) uint8_t[num_blocks * erase_size]; TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory for test"); delete[] dummy; - + HeapBlockDevice heap_bd(num_blocks * erase_size, read_size, prog_size, erase_size); FlashSimBlockDevice bd(&heap_bd, blank); diff --git a/features/storage/TESTS/blockdevice/general_block_device/README.md b/features/storage/TESTS/blockdevice/general_block_device/README.md new file mode 100644 index 0000000000..ceb2672213 --- /dev/null +++ b/features/storage/TESTS/blockdevice/general_block_device/README.md @@ -0,0 +1,71 @@ +# Getting started with the Mbed OS block device test + +You can use the Mbed OS block device test to test existing and new block devices. + +You can find more information about the Mbed OS block device and other related pieces of the Mbed OS storage stack [in the storage overview](https://os.mbed.com/docs/latest/reference/storage.html). + +**Table of contents:** + +1. [Hardware requirements](#hardware-requirements) +2. [Usage](#usage) + - [Compile the test](#compile-the-test) + - [Run the test](#run-the-test) +3. [Changing the block device](#changing-the-block-device) +4. [Tested configurations](#tested-configurations) + +## Hardware requirements + +This test uses a block device as storage. This can be either an external block device (one of SPI flash, DataFlash or an SD card) or simulated on a heap block device on boards with enough RAM. + +## Usage + +#### Compile the test + +Invoke `mbed test`, and specify the name of your platform and your favorite toolchain (`GCC_ARM`, `ARM`, `IAR`). For example, for the ARM Compiler 5: + +``` +mbed test -m K64F -t ARM -n mbed-os-features-storage-tests-blockdevice-general_block_device --compile +``` + +#### Run the test + +Use `mbed test` again: + +``` +mbed test -m K64F -t ARM -n mbed-os-features-storage-tests-blockdevice-general_block_device --run -v +``` + +#### Troubleshooting + +Please review the [documentation](https://os.mbed.com/docs/latest/tutorials/debugging.html) for suggestions about how to fix possible issues you may face. + +## Changing the block device + +In Mbed OS, a C++ class that inherits from the [BlockDevice](https://os.mbed.com/docs/latest/reference/storage.html#block-devices) interface represents each block device. + +This test uses the default block device that the function `get_default_instance()` receives. [SystemStorage.cpp](https://github.com/ARMmbed/mbed-os/blob/master/features/storage/system_storage/SystemStorage.cpp#L35-L77) defines this as `MBED_WEAK`. If you would like to test a new block device, you have to override it. + +First add the new block device .cpp and header files to the [blockdevice folder](https://github.com/ARMmbed/mbed-os/tree/master/features/storage/blockdevice). Then, implement `get_default_instance()` inside the test `main.cpp`. + +For example, to test the HeapBlockDevice, add: + +``` diff ++#define TEST_BLOCK_SIZE 128 ++#define TEST_BLOCK_DEVICE_SIZE 32*TEST_BLOCK_SIZE + ++BlockDevice *BlockDevice::get_default_instance() ++{ ++ utest_printf("NEW test block device!!!\n"); ++ static HeapBlockDevice default_bd(TEST_BLOCK_DEVICE_SIZE, TEST_BLOCK_SIZE); ++ return &default_bd; ++} +``` + +Now you can recompile and run. + +## Tested configurations + +- K64F + SD. +- K64F + Heap. +- K82F + SPIF. +- K82F + Heap. diff --git a/features/storage/TESTS/blockdevice/general_block_device/main.cpp b/features/storage/TESTS/blockdevice/general_block_device/main.cpp new file mode 100644 index 0000000000..e811055317 --- /dev/null +++ b/features/storage/TESTS/blockdevice/general_block_device/main.cpp @@ -0,0 +1,442 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * 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. + */ +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS //Required for PRIu64 +#endif + +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "mbed_trace.h" +#include +#include + +using namespace utest::v1; + +#define TEST_BLOCK_COUNT 10 +#define TEST_ERROR_MASK 16 +#define TEST_NUM_OF_THREADS 5 + +const struct { + const char *name; + bd_size_t (BlockDevice::*method)() const; +} ATTRS[] = { + {"read size", &BlockDevice::get_read_size}, + {"program size", &BlockDevice::get_program_size}, + {"erase size", &BlockDevice::get_erase_size}, + {"total size", &BlockDevice::size}, +}; + +static SingletonPtr _mutex; + +// Mutex is protecting rand() per srand for buffer writing and verification. +// Mutex is also protecting printouts for clear logs. +// Mutex is NOT protecting Block Device actions: erase/program/read - which is the purpose of the multithreaded test! +void basic_erase_program_read_test(BlockDevice *block_device, bd_size_t block_size, uint8_t *write_block, + uint8_t *read_block, unsigned addrwidth) +{ + int err = 0; + _mutex->lock(); + // Find a random block + bd_addr_t block = (rand() * block_size) % (block_device->size()); + + // Use next random number as temporary seed to keep + // the address progressing in the pseudorandom sequence + unsigned seed = rand(); + + // Fill with random sequence + srand(seed); + for (bd_size_t i_ind = 0; i_ind < block_size; i_ind++) { + write_block[i_ind] = 0xff & rand(); + } + // Write, sync, and read the block + utest_printf("\ntest %0*llx:%llu...", addrwidth, block, block_size); + _mutex->unlock(); + + err = block_device->erase(block, block_size); + TEST_ASSERT_EQUAL(0, err); + + err = block_device->program(write_block, block, block_size); + TEST_ASSERT_EQUAL(0, err); + + err = block_device->read(read_block, block, block_size); + TEST_ASSERT_EQUAL(0, err); + + _mutex->lock(); + // Check that the data was unmodified + srand(seed); + int val_rand; + for (bd_size_t i_ind = 0; i_ind < block_size; i_ind++) { + val_rand = rand(); + if ((0xff & val_rand) != read_block[i_ind]) { + utest_printf("\n Assert Failed Buf Read - block:size: %llx:%llu \n", block, block_size); + utest_printf("\n pos: %llu, exp: %02x, act: %02x, wrt: %02x \n", i_ind, (0xff & val_rand), + read_block[i_ind], + write_block[i_ind]); + } + TEST_ASSERT_EQUAL(0xff & val_rand, read_block[i_ind]); + } + _mutex->unlock(); +} + +void test_random_program_read_erase() +{ + utest_printf("\nTest Random Program Read Erase Starts..\n"); + + BlockDevice *block_device = BlockDevice::get_default_instance(); + + if (!block_device) { + utest_printf("\nno block device found.\n"); + return; + } + + int err = block_device->init(); + TEST_ASSERT_EQUAL(0, err); + + for (unsigned atr = 0; atr < sizeof(ATTRS) / sizeof(ATTRS[0]); atr++) { + static const char *prefixes[] = {"", "k", "M", "G"}; + for (int i_ind = 3; i_ind >= 0; i_ind--) { + bd_size_t size = (block_device->*ATTRS[atr].method)(); + if (size >= (1ULL << 10 * i_ind)) { + utest_printf("%s: %llu%sbytes (%llubytes)\n", + ATTRS[atr].name, size >> 10 * i_ind, prefixes[i_ind], size); + break; + } + } + } + + bd_size_t block_size = block_device->get_erase_size(); + unsigned addrwidth = ceil(log(float(block_device->size() - 1)) / log(float(16))) + 1; + + uint8_t *write_block = new (std::nothrow) uint8_t[block_size]; + uint8_t *read_block = new (std::nothrow) uint8_t[block_size]; + if (!write_block || !read_block) { + utest_printf("\n Not enough memory for test"); + goto end; + } + + for (int b = 0; b < TEST_BLOCK_COUNT; b++) { + basic_erase_program_read_test(block_device, block_size, write_block, read_block, addrwidth); + } + + err = block_device->deinit(); + TEST_ASSERT_EQUAL(0, err); + +end: + delete[] write_block; + delete[] read_block; +} + +static void test_thread_job(void *block_device_ptr) +{ + static int thread_num = 0; + thread_num++; + BlockDevice *block_device = (BlockDevice *)block_device_ptr; + + bd_size_t block_size = block_device->get_erase_size(); + unsigned addrwidth = ceil(log(float(block_device->size() - 1)) / log(float(16))) + 1; + + uint8_t *write_block = new (std::nothrow) uint8_t[block_size]; + uint8_t *read_block = new (std::nothrow) uint8_t[block_size]; + + if (!write_block || !read_block) { + utest_printf("\n Not enough memory for test"); + goto end; + } + + for (int b = 0; b < TEST_BLOCK_COUNT; b++) { + basic_erase_program_read_test(block_device, block_size, write_block, read_block, addrwidth); + } + +end: + delete[] write_block; + delete[] read_block; +} + +void test_multi_threads() +{ + utest_printf("\nTest Multi Threaded Erase/Program/Read Starts..\n"); + + BlockDevice *block_device = BlockDevice::get_default_instance(); + + if (!block_device) { + utest_printf("\nno block device found.\n"); + return; + } + + int err = block_device->init(); + TEST_ASSERT_EQUAL(0, err); + + for (unsigned atr = 0; atr < sizeof(ATTRS) / sizeof(ATTRS[0]); atr++) { + static const char *prefixes[] = {"", "k", "M", "G"}; + for (int i_ind = 3; i_ind >= 0; i_ind--) { + bd_size_t size = (block_device->*ATTRS[atr].method)(); + if (size >= (1ULL << 10 * i_ind)) { + utest_printf("%s: %llu%sbytes (%llubytes)\n", + ATTRS[atr].name, size >> 10 * i_ind, prefixes[i_ind], size); + break; + } + } + } + + rtos::Thread bd_thread[TEST_NUM_OF_THREADS]; + + osStatus threadStatus; + int i_ind; + + for (i_ind = 0; i_ind < TEST_NUM_OF_THREADS; i_ind++) { + threadStatus = bd_thread[i_ind].start(callback(test_thread_job, (void *)block_device)); + if (threadStatus != 0) { + utest_printf("\n Thread %d Start Failed!", i_ind + 1); + } + } + + for (i_ind = 0; i_ind < TEST_NUM_OF_THREADS; i_ind++) { + bd_thread[i_ind].join(); + } + + err = block_device->deinit(); + TEST_ASSERT_EQUAL(0, err); +} + +void test_get_erase_value() +{ + utest_printf("\nTest BlockDevice::get_erase_value()..\n"); + + // Test flow: + // 1. Write data to selected region + // - Known starting point + // 2. Erase selected region + // 3. Read erased region and compare with get_erase_value() + + BlockDevice *block_device = BlockDevice::get_default_instance(); + TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "\nno block device found.\n"); + + int err = block_device->init(); + TEST_ASSERT_EQUAL(0, err); + + // Check erase value + int erase_value_int = block_device->get_erase_value(); + utest_printf("\nblock_device->get_erase_value()=%d", erase_value_int); + TEST_SKIP_UNLESS_MESSAGE(erase_value_int >= 0, "\nerase value is negative which means the erase value is unknown\n"); + + // Assuming that get_erase_value() returns byte value as documentation mentions + // "If get_erase_value() returns a non-negative byte value" for unknown case. + TEST_ASSERT(erase_value_int <= 255); + uint8_t erase_value = (uint8_t)erase_value_int; + + // Determine data_buf_size + bd_size_t erase_size = block_device->get_erase_size(); + TEST_ASSERT(erase_size > 0); + bd_size_t data_buf_size = erase_size; + + // Determine start_address + bd_addr_t start_address = rand(); // low 32 bytes + start_address += (uint64_t)rand() << 32; // high 32 bytes + start_address %= block_device->size() - data_buf_size - erase_size; // fit all data + alignment reserve + start_address += erase_size; // add alignment reserve + start_address -= start_address % erase_size; // align with erase_block + utest_printf("\nstart_address=0x%016" PRIx64, start_address); + + // Allocate buffer for read test data + uint8_t *data_buf = (uint8_t*)malloc(data_buf_size); + TEST_ASSERT_NOT_NULL(data_buf); + + // Write random data to selected region to make sure data is not accidentally set to "erased" value. + // With this pre-write, the test case will fail even if block_device->erase() is broken. + for (bd_size_t i=0; iprogram((const void*)data_buf, start_address, data_buf_size); + TEST_ASSERT_EQUAL(0, err); + + // Erase given memory region + utest_printf("\nerasing given memory region"); + err = block_device->erase(start_address, data_buf_size); + TEST_ASSERT_EQUAL(0, err); + + // Read erased memory region + utest_printf("\nreading erased memory region"); + err = block_device->read((void*)data_buf, start_address, data_buf_size); + TEST_ASSERT_EQUAL(0, err); + + // Verify erased memory region + utest_printf("\nverifying erased memory region"); + for (bd_size_t i=0; ideinit(); + TEST_ASSERT_EQUAL(0, err); +} + +void test_contiguous_erase_write_read() +{ + utest_printf("\nTest Contiguous Erase/Program/Read Starts..\n"); + + // Test flow: + // 1. Erase whole test area + // - Tests contiguous erase + // 2. Write smaller memory area + // - Tests contiguous sector writes + // 3. Rerun step 2 for whole erase region + + BlockDevice *block_device = BlockDevice::get_default_instance(); + TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "\nno block device found.\n"); + + // Initialize BlockDevice + int err = block_device->init(); + TEST_ASSERT_EQUAL(0, err); + + // Test parameters + bd_size_t erase_size = block_device->get_erase_size(); + TEST_ASSERT(erase_size > 0); + bd_size_t program_size = block_device->get_program_size(); + TEST_ASSERT(program_size > 0); + utest_printf("\nerase_size=%d", erase_size); + utest_printf("\nprogram_size=%d", program_size); + utest_printf("\nblock_device->size()=%" PRId64, block_device->size()); + + // Determine write/read buffer size + // start write_read_buf_size from 1% block_device->size() + bd_size_t write_read_buf_size = block_device->size() / 100; // 1%, 10k=100, 100k=1k, 1MB=10k, 32MB=32k + // try to limit write_read_buf_size to 10k. If program_size*2 is larger than 10k, that will be used instead. + if (write_read_buf_size > 10000) { + write_read_buf_size = 10000; + } + // 2 program_size blocks is minimum for contiguous write/read test + if (write_read_buf_size < program_size*2) { + write_read_buf_size = program_size*2; // going over 10k + } + bd_size_t contiguous_write_read_blocks_per_region = write_read_buf_size / program_size; // 2 is minimum to test contiguous write + write_read_buf_size = contiguous_write_read_blocks_per_region * program_size; + utest_printf("\ncontiguous_write_read_blocks_per_region=%" PRIu64, contiguous_write_read_blocks_per_region); + utest_printf("\nwrite_read_buf_size=%" PRIu64, write_read_buf_size); + + // Determine test region count + int contiguous_write_read_regions = TEST_BLOCK_COUNT; + utest_printf("\ncontiguous_write_read_regions=%d", contiguous_write_read_regions); + + // Determine whole erase size + bd_size_t contiguous_erase_size = write_read_buf_size * contiguous_write_read_regions; + contiguous_erase_size -= contiguous_erase_size % erase_size; // aligned to erase_size + contiguous_erase_size += erase_size; // but larger than write/read size * regions + utest_printf("\ncontiguous_erase_size=%" PRIu64, contiguous_erase_size); + + // Determine starting address + bd_addr_t start_address = rand(); // low 32 bytes + start_address += (uint64_t)rand() << 32; // high 32 bytes + start_address %= block_device->size() - contiguous_erase_size - erase_size; // fit all data + alignment reserve + start_address += erase_size; // add alignment reserve + start_address -= start_address % erase_size; // align with erase_block + bd_addr_t stop_address = start_address + write_read_buf_size * contiguous_write_read_regions; + utest_printf("\nstart_address=0x%016" PRIx64, start_address); + utest_printf("\nstop_address=0x%016" PRIx64, stop_address); + + // Allocate write/read buffer + uint8_t *write_read_buf = (uint8_t*)malloc(write_read_buf_size); + if (write_read_buf == NULL) { + block_device->deinit(); + TEST_SKIP_MESSAGE("\nnot enough memory for test"); + } + utest_printf("\nwrite_read_buf_size=%" PRIu64 "", (uint64_t)write_read_buf_size); + + // Pre-fill the to-be-erased region. By pre-filling the region, + // we can be sure the test will not pass if the erase doesn't work. + for (bd_size_t offset=0; start_address+offset < stop_address; offset+=write_read_buf_size) { + for (size_t i=0; iprogram((const void*)write_read_buf, start_address+offset, write_read_buf_size); + TEST_ASSERT_EQUAL(0, err); + } + + // Erase the whole region first + utest_printf("\nerasing memory, from 0x%" PRIx64 " of size 0x%" PRIx64, start_address, contiguous_erase_size); + err = block_device->erase(start_address, contiguous_erase_size); + TEST_ASSERT_EQUAL(0, err); + + // Loop through all write/read regions + int region = 0; + for (; start_address < stop_address; start_address+=write_read_buf_size) { + utest_printf("\n\nregion #%d start_address=0x%016" PRIx64, region++, start_address); + + // Generate test data + unsigned int seed = rand(); + utest_printf("\ngenerating test data, seed=%u", seed); + srand(seed); + for (size_t i=0; iprogram((const void*)write_read_buf, start_address, write_read_buf_size); + TEST_ASSERT_EQUAL(0, err); + + // Read test data + memset(write_read_buf, 0, (size_t)write_read_buf_size); + utest_printf("\nreading test data"); + err = block_device->read(write_read_buf, start_address, write_read_buf_size); + TEST_ASSERT_EQUAL(0, err); + + // Verify read data + utest_printf("\nverifying test data"); + srand(seed); + for (size_t i=0; ideinit(); + TEST_ASSERT_EQUAL(0, err); +} + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(60, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Testing read write random blocks", test_random_program_read_erase), + Case("Testing Multi Threads Erase Program Read", test_multi_threads), + Case("Testing contiguous erase, write and read", test_contiguous_erase_write_read), + Case("Test BlockDevice::get_erase_value()", test_get_erase_value) +}; + +Specification specification(test_setup, cases); + +int main() +{ + return !Harness::run(specification); +} diff --git a/features/storage/TESTS/blockdevice/heap_block_device/main.cpp b/features/storage/TESTS/blockdevice/heap_block_device/main.cpp index 367e28d155..1f84f9265b 100644 --- a/features/storage/TESTS/blockdevice/heap_block_device/main.cpp +++ b/features/storage/TESTS/blockdevice/heap_block_device/main.cpp @@ -25,7 +25,7 @@ using namespace utest::v1; // TODO HACK, replace with available ram/heap property #if defined(TARGET_MTB_MTS_XDOT) - #error [NOT_SUPPORTED] Insufficient heap for heap block device tests +#error [NOT_SUPPORTED] Insufficient heap for heap block device tests #endif #define TEST_BLOCK_SIZE 128 @@ -45,7 +45,8 @@ const struct { // Simple test that read/writes random set of blocks -void test_read_write() { +void test_read_write() +{ uint8_t *dummy = new (std::nothrow) uint8_t[TEST_BLOCK_DEVICE_SIZE]; TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory for test"); delete[] dummy; @@ -55,19 +56,19 @@ void test_read_write() { int err = bd.init(); TEST_ASSERT_EQUAL(0, err); - for (unsigned a = 0; a < sizeof(ATTRS)/sizeof(ATTRS[0]); a++) { + for (unsigned a = 0; a < sizeof(ATTRS) / sizeof(ATTRS[0]); a++) { static const char *prefixes[] = {"", "k", "M", "G"}; for (int i = 3; i >= 0; i--) { bd_size_t size = (bd.*ATTRS[a].method)(); - if (size >= (1ULL << 10*i)) { + if (size >= (1ULL << 10 * i)) { printf("%s: %llu%sbytes (%llubytes)\n", - ATTRS[a].name, size >> 10*i, prefixes[i], size); + ATTRS[a].name, size >> 10 * i, prefixes[i], size); break; } } } - unsigned addrwidth = ceil(log(float(bd.size()-1)) / log(float(16)))+1; + unsigned addrwidth = ceil(log(float(bd.size() - 1)) / log(float(16))) + 1; bd_size_t block_size = bd.get_erase_size(); uint8_t *write_block = new (std::nothrow) uint8_t[block_size]; @@ -81,7 +82,7 @@ void test_read_write() { for (int b = 0; b < TEST_BLOCK_COUNT; b++) { // Find a random block - bd_addr_t block = (rand()*block_size) % bd.size(); + bd_addr_t block = (rand() * block_size) % bd.size(); // Use next random number as temporary seed to keep // the address progressing in the pseudorandom sequence @@ -119,13 +120,13 @@ void test_read_write() { // Find error mask for debugging memset(error_mask, 0, TEST_ERROR_MASK); - bd_size_t error_scale = block_size / (TEST_ERROR_MASK*8); + bd_size_t error_scale = block_size / (TEST_ERROR_MASK * 8); srand(seed); - for (bd_size_t i = 0; i < TEST_ERROR_MASK*8; i++) { + for (bd_size_t i = 0; i < TEST_ERROR_MASK * 8; i++) { for (bd_size_t j = 0; j < error_scale; j++) { - if ((0xff & rand()) != read_block[i*error_scale + j]) { - error_mask[i/8] |= 1 << (i%8); + if ((0xff & rand()) != read_block[i * error_scale + j]) { + error_mask[i / 8] |= 1 << (i % 8); } } } @@ -142,7 +143,7 @@ void test_read_write() { TEST_ASSERT_EQUAL(0xff & rand(), read_block[i]); } } - + err = bd.deinit(); TEST_ASSERT_EQUAL(0, err); @@ -155,7 +156,8 @@ end: // Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { +utest::v1::status_t test_setup(const size_t number_of_cases) +{ GREENTEA_SETUP(30, "default_auto"); return verbose_test_setup_handler(number_of_cases); } @@ -166,6 +168,7 @@ Case cases[] = { Specification specification(test_setup, cases); -int main() { +int main() +{ return !Harness::run(specification); } diff --git a/features/storage/TESTS/blockdevice/mbr_block_device/main.cpp b/features/storage/TESTS/blockdevice/mbr_block_device/main.cpp index 87dcfa14f0..489107b5ad 100644 --- a/features/storage/TESTS/blockdevice/mbr_block_device/main.cpp +++ b/features/storage/TESTS/blockdevice/mbr_block_device/main.cpp @@ -26,13 +26,13 @@ using namespace utest::v1; // TODO HACK, replace with available ram/heap property #if defined(TARGET_MTB_MTS_XDOT) - #error [NOT_SUPPORTED] Insufficient heap for heap block device tests +#error [NOT_SUPPORTED] Insufficient heap for heap block device tests #endif #define BLOCK_COUNT 16 #define BLOCK_SIZE 512 -HeapBlockDevice bd(BLOCK_COUNT*BLOCK_SIZE, BLOCK_SIZE); +HeapBlockDevice bd(BLOCK_COUNT *BLOCK_SIZE, BLOCK_SIZE); // Testing formatting of master boot record void test_mbr_format() @@ -42,10 +42,10 @@ void test_mbr_format() delete[] dummy; // Create two partitions splitting device in ~half - int err = MBRBlockDevice::partition(&bd, 1, 0x83, 0, (BLOCK_COUNT/2)*BLOCK_SIZE); + int err = MBRBlockDevice::partition(&bd, 1, 0x83, 0, (BLOCK_COUNT / 2) * BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); - err = MBRBlockDevice::partition(&bd, 2, 0x83, -(BLOCK_COUNT/2)*BLOCK_SIZE); + err = MBRBlockDevice::partition(&bd, 2, 0x83, -(BLOCK_COUNT / 2) * BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); // Load both partitions, as well as a third to check for invalid partitions @@ -95,13 +95,13 @@ void test_mbr_attr() printf("partition 1 erase size: %llu bytes\n", part1.get_erase_size()); printf("partition 1 size: %llu bytes\n", part1.size()); TEST_ASSERT_EQUAL(1, part1.get_partition_number()); - TEST_ASSERT_EQUAL(1*BLOCK_SIZE, part1.get_partition_start()); - TEST_ASSERT_EQUAL((BLOCK_COUNT/2)*BLOCK_SIZE, part1.get_partition_stop()); + TEST_ASSERT_EQUAL(1 * BLOCK_SIZE, part1.get_partition_start()); + TEST_ASSERT_EQUAL((BLOCK_COUNT / 2)*BLOCK_SIZE, part1.get_partition_stop()); TEST_ASSERT_EQUAL(0x83, part1.get_partition_type()); TEST_ASSERT_EQUAL(BLOCK_SIZE, part1.get_read_size()); TEST_ASSERT_EQUAL(BLOCK_SIZE, part1.get_program_size()); TEST_ASSERT_EQUAL(BLOCK_SIZE, part1.get_erase_size()); - TEST_ASSERT_EQUAL(((BLOCK_COUNT/2)-1)*BLOCK_SIZE, part1.size()); + TEST_ASSERT_EQUAL(((BLOCK_COUNT / 2) - 1)*BLOCK_SIZE, part1.size()); printf("partition 2 partition number: %d\n", part2.get_partition_number()); printf("partition 2 partition start: 0x%llx\n", part2.get_partition_start()); @@ -112,13 +112,13 @@ void test_mbr_attr() printf("partition 2 erase size: %llu bytes\n", part2.get_erase_size()); printf("partition 2 size: %llu bytes\n", part2.size()); TEST_ASSERT_EQUAL(2, part2.get_partition_number()); - TEST_ASSERT_EQUAL((BLOCK_COUNT/2)*BLOCK_SIZE, part2.get_partition_start()); - TEST_ASSERT_EQUAL(BLOCK_COUNT*BLOCK_SIZE, part2.get_partition_stop()); + TEST_ASSERT_EQUAL((BLOCK_COUNT / 2)*BLOCK_SIZE, part2.get_partition_start()); + TEST_ASSERT_EQUAL(BLOCK_COUNT * BLOCK_SIZE, part2.get_partition_stop()); TEST_ASSERT_EQUAL(0x83, part2.get_partition_type()); TEST_ASSERT_EQUAL(BLOCK_SIZE, part2.get_read_size()); TEST_ASSERT_EQUAL(BLOCK_SIZE, part2.get_program_size()); TEST_ASSERT_EQUAL(BLOCK_SIZE, part2.get_erase_size()); - TEST_ASSERT_EQUAL((BLOCK_COUNT/2)*BLOCK_SIZE, part2.size()); + TEST_ASSERT_EQUAL((BLOCK_COUNT / 2)*BLOCK_SIZE, part2.size()); // Deinit partitions err = part1.deinit(); @@ -177,7 +177,7 @@ void test_mbr_read_write() } // Check with original block device - err = bd.read(read_block, 1*BLOCK_SIZE, BLOCK_SIZE); + err = bd.read(read_block, 1 * BLOCK_SIZE, BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); // Check that the data was unmodified @@ -209,7 +209,7 @@ void test_mbr_read_write() } // Check with original block device - err = bd.read(read_block, (BLOCK_COUNT/2)*BLOCK_SIZE, BLOCK_SIZE); + err = bd.read(read_block, (BLOCK_COUNT / 2) * BLOCK_SIZE, BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); // Check that the data was unmodified @@ -232,7 +232,8 @@ end: // Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { +utest::v1::status_t test_setup(const size_t number_of_cases) +{ GREENTEA_SETUP(10, "default_auto"); return verbose_test_setup_handler(number_of_cases); } @@ -245,6 +246,7 @@ Case cases[] = { Specification specification(test_setup, cases); -int main() { +int main() +{ return !Harness::run(specification); } diff --git a/features/storage/TESTS/blockdevice/util_block_device/main.cpp b/features/storage/TESTS/blockdevice/util_block_device/main.cpp index f551861824..0f0fe103af 100644 --- a/features/storage/TESTS/blockdevice/util_block_device/main.cpp +++ b/features/storage/TESTS/blockdevice/util_block_device/main.cpp @@ -28,7 +28,7 @@ using namespace utest::v1; // TODO HACK, replace with available ram/heap property #if defined(TARGET_MTB_MTS_XDOT) - #error [NOT_SUPPORTED] Insufficient heap for heap block device tests +#error [NOT_SUPPORTED] Insufficient heap for heap block device tests #endif #define BLOCK_COUNT 16 @@ -36,17 +36,18 @@ using namespace utest::v1; // Simple test which read/writes blocks on a sliced block device -void test_slicing() { +void test_slicing() +{ uint8_t *dummy = new (std::nothrow) uint8_t[BLOCK_COUNT * BLOCK_SIZE]; TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory for test"); delete[] dummy; int err; - HeapBlockDevice bd(BLOCK_COUNT*BLOCK_SIZE, BLOCK_SIZE); + HeapBlockDevice bd(BLOCK_COUNT * BLOCK_SIZE, BLOCK_SIZE); - SlicingBlockDevice slice1(&bd, 0, (BLOCK_COUNT/2)*BLOCK_SIZE); - SlicingBlockDevice slice2(&bd, -(BLOCK_COUNT/2)*BLOCK_SIZE); + SlicingBlockDevice slice1(&bd, 0, (BLOCK_COUNT / 2)*BLOCK_SIZE); + SlicingBlockDevice slice2(&bd, -(BLOCK_COUNT / 2)*BLOCK_SIZE); // Test with first slice of block device err = slice1.init(); @@ -54,7 +55,7 @@ void test_slicing() { TEST_ASSERT_EQUAL(BLOCK_SIZE, slice1.get_program_size()); TEST_ASSERT_EQUAL(BLOCK_SIZE, slice1.get_erase_size(BLOCK_SIZE)); - TEST_ASSERT_EQUAL((BLOCK_COUNT/2)*BLOCK_SIZE, slice1.size()); + TEST_ASSERT_EQUAL((BLOCK_COUNT / 2)*BLOCK_SIZE, slice1.size()); uint8_t *write_block = new (std::nothrow) uint8_t[BLOCK_SIZE]; uint8_t *read_block = new (std::nothrow) uint8_t[BLOCK_SIZE]; @@ -97,7 +98,7 @@ void test_slicing() { TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(BLOCK_SIZE, slice2.get_program_size()); - TEST_ASSERT_EQUAL((BLOCK_COUNT/2)*BLOCK_SIZE, slice2.size()); + TEST_ASSERT_EQUAL((BLOCK_COUNT / 2)*BLOCK_SIZE, slice2.size()); // Fill with random sequence srand(1); @@ -123,7 +124,7 @@ void test_slicing() { } // Check with original block device - err = bd.read(read_block, (BLOCK_COUNT/2)*BLOCK_SIZE, BLOCK_SIZE); + err = bd.read(read_block, (BLOCK_COUNT / 2) * BLOCK_SIZE, BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); // Check that the data was unmodified @@ -141,15 +142,16 @@ end: } // Simple test which read/writes blocks on a chain of block devices -void test_chaining() { +void test_chaining() +{ uint8_t *dummy = new (std::nothrow) uint8_t[BLOCK_COUNT * BLOCK_SIZE]; TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory for test"); delete[] dummy; int err; - HeapBlockDevice bd1((BLOCK_COUNT/2)*BLOCK_SIZE, BLOCK_SIZE); - HeapBlockDevice bd2((BLOCK_COUNT/2)*BLOCK_SIZE, BLOCK_SIZE); + HeapBlockDevice bd1((BLOCK_COUNT / 2)*BLOCK_SIZE, BLOCK_SIZE); + HeapBlockDevice bd2((BLOCK_COUNT / 2)*BLOCK_SIZE, BLOCK_SIZE); // Test with chain of block device BlockDevice *bds[] = {&bd1, &bd2}; @@ -167,8 +169,8 @@ void test_chaining() { TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(BLOCK_SIZE, chain.get_program_size()); - TEST_ASSERT_EQUAL(BLOCK_SIZE, chain.get_erase_size((BLOCK_COUNT/2)*BLOCK_SIZE+1)); - TEST_ASSERT_EQUAL(BLOCK_COUNT*BLOCK_SIZE, chain.size()); + TEST_ASSERT_EQUAL(BLOCK_SIZE, chain.get_erase_size((BLOCK_COUNT / 2)*BLOCK_SIZE + 1)); + TEST_ASSERT_EQUAL(BLOCK_COUNT * BLOCK_SIZE, chain.size()); // Fill with random sequence srand(1); @@ -190,10 +192,10 @@ void test_chaining() { } // Write, sync, and read the block - err = chain.program(write_block, (BLOCK_COUNT/2)*BLOCK_SIZE, BLOCK_SIZE); + err = chain.program(write_block, (BLOCK_COUNT / 2) * BLOCK_SIZE, BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); - err = chain.read(read_block, (BLOCK_COUNT/2)*BLOCK_SIZE, BLOCK_SIZE); + err = chain.read(read_block, (BLOCK_COUNT / 2) * BLOCK_SIZE, BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); // Check that the data was unmodified @@ -211,7 +213,8 @@ end: } // Simple test which read/writes blocks on a chain of block devices -void test_profiling() { +void test_profiling() +{ uint8_t *dummy = new (std::nothrow) uint8_t[BLOCK_COUNT * BLOCK_SIZE]; TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory for test"); delete[] dummy; @@ -219,7 +222,7 @@ void test_profiling() { int err; bd_size_t read_count, program_count, erase_count; - HeapBlockDevice bd(BLOCK_COUNT*BLOCK_SIZE, BLOCK_SIZE); + HeapBlockDevice bd(BLOCK_COUNT * BLOCK_SIZE, BLOCK_SIZE); // Test under profiling ProfilingBlockDevice profiler(&bd); @@ -227,7 +230,7 @@ void test_profiling() { TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(BLOCK_SIZE, profiler.get_erase_size()); - TEST_ASSERT_EQUAL(BLOCK_COUNT*BLOCK_SIZE, profiler.size()); + TEST_ASSERT_EQUAL(BLOCK_COUNT * BLOCK_SIZE, profiler.size()); uint8_t *write_block = new (std::nothrow) uint8_t[BLOCK_SIZE]; uint8_t *read_block = new (std::nothrow) uint8_t[BLOCK_SIZE]; @@ -287,7 +290,8 @@ end: // Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { +utest::v1::status_t test_setup(const size_t number_of_cases) +{ GREENTEA_SETUP(10, "default_auto"); return verbose_test_setup_handler(number_of_cases); } @@ -300,6 +304,7 @@ Case cases[] = { Specification specification(test_setup, cases); -int main() { +int main() +{ return !Harness::run(specification); } diff --git a/features/storage/TESTS/filesystem/fat_filesystem/main.cpp b/features/storage/TESTS/filesystem/fat_filesystem/main.cpp index 45d393ffd9..cca9acca1c 100644 --- a/features/storage/TESTS/filesystem/fat_filesystem/main.cpp +++ b/features/storage/TESTS/filesystem/fat_filesystem/main.cpp @@ -26,16 +26,17 @@ using namespace utest::v1; #ifndef MBED_EXTENDED_TESTS - #error [NOT_SUPPORTED] Filesystem tests not supported by default +#error [NOT_SUPPORTED] Filesystem tests not supported by default #endif // Test block device #define BLOCK_SIZE 512 -HeapBlockDevice bd(128*BLOCK_SIZE, BLOCK_SIZE); +HeapBlockDevice bd(128 * BLOCK_SIZE, BLOCK_SIZE); // Test formatting -void test_format() { +void test_format() +{ int err = FATFileSystem::format(&bd); TEST_ASSERT_EQUAL(0, err); } @@ -43,7 +44,8 @@ void test_format() { // Simple test for reading/writing files template -void test_read_write() { +void test_read_write() +{ FATFileSystem fs("fat"); int err = fs.mount(&bd); @@ -51,7 +53,7 @@ void test_read_write() { uint8_t *buffer = (uint8_t *)malloc(TEST_SIZE); TEST_ASSERT(buffer); - + // Fill with random sequence srand(1); for (int i = 0; i < TEST_SIZE; i++) { @@ -86,7 +88,8 @@ void test_read_write() { // Simple test for iterating dir entries -void test_read_dir() { +void test_read_dir() +{ FATFileSystem fs("fat"); int err = fs.mount(&bd); @@ -147,20 +150,22 @@ void test_read_dir() { // Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { +utest::v1::status_t test_setup(const size_t number_of_cases) +{ GREENTEA_SETUP(10, "default_auto"); return verbose_test_setup_handler(number_of_cases); } Case cases[] = { Case("Testing formating", test_format), - Case("Testing read write < block", test_read_write), - Case("Testing read write > block", test_read_write<2*BLOCK_SIZE>), + Case("Testing read write < block", test_read_write < BLOCK_SIZE / 2 >), + Case("Testing read write > block", test_read_write<2 * BLOCK_SIZE>), Case("Testing dir iteration", test_read_dir), }; Specification specification(test_setup, cases); -int main() { +int main() +{ return !Harness::run(specification); } diff --git a/features/storage/TESTS/filesystem/general_filesystem/main.cpp b/features/storage/TESTS/filesystem/general_filesystem/main.cpp index fb2a7da94c..4f75735b9c 100644 --- a/features/storage/TESTS/filesystem/general_filesystem/main.cpp +++ b/features/storage/TESTS/filesystem/general_filesystem/main.cpp @@ -18,17 +18,23 @@ #include "utest/utest.h" #include "BlockDevice.h" #include "FileSystem.h" + +#include #if COMPONENT_SPIF #include "SPIFBlockDevice.h" #include "LittleFileSystem.h" #elif COMPONENT_SD #include "SDBlockDevice.h" #include "FATFileSystem.h" +#elif COMPONENT_FLASHIAP +#include "FlashIAPBlockDevice.h" +#include "LittleFileSystem.h" #else #error [NOT_SUPPORTED] storage test not supported on this platform #endif using namespace utest::v1; +using namespace mbed; static const size_t small_buf_size = 10; static const size_t medium_buf_size = 250; @@ -1953,7 +1959,7 @@ static void FS_fill_data_and_seek() for (i = 1; i <= 255; i++) { - res = fseek(fd[0], (long)-i, SEEK_END); + res = fseek(fd[0], (long) - i, SEEK_END); TEST_ASSERT_EQUAL(0, res); j = getc(fd[0]); diff --git a/features/storage/TESTS/filesystem/multipart_fat_filesystem/main.cpp b/features/storage/TESTS/filesystem/multipart_fat_filesystem/main.cpp index 47d7b485d2..91dc8c1683 100644 --- a/features/storage/TESTS/filesystem/multipart_fat_filesystem/main.cpp +++ b/features/storage/TESTS/filesystem/multipart_fat_filesystem/main.cpp @@ -27,22 +27,23 @@ using namespace utest::v1; #ifndef MBED_EXTENDED_TESTS - #error [NOT_SUPPORTED] Filesystem tests not supported by default +#error [NOT_SUPPORTED] Filesystem tests not supported by default #endif // Test block device #define BLOCK_SIZE 512 #define BLOCK_COUNT 512 -HeapBlockDevice bd(BLOCK_COUNT*BLOCK_SIZE, BLOCK_SIZE); +HeapBlockDevice bd(BLOCK_COUNT *BLOCK_SIZE, BLOCK_SIZE); // Test formatting and partitioning -void test_format() { +void test_format() +{ // Create two partitions splitting device in ~half - int err = MBRBlockDevice::partition(&bd, 1, 0x83, 0, (BLOCK_COUNT/2)*BLOCK_SIZE); + int err = MBRBlockDevice::partition(&bd, 1, 0x83, 0, (BLOCK_COUNT / 2) * BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); - err = MBRBlockDevice::partition(&bd, 2, 0x83, -(BLOCK_COUNT/2)*BLOCK_SIZE); + err = MBRBlockDevice::partition(&bd, 2, 0x83, -(BLOCK_COUNT / 2) * BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); // Load both partitions @@ -72,7 +73,8 @@ void test_format() { // Simple multipartition test for reading/writing files template -void test_read_write() { +void test_read_write() +{ // Load both partitions MBRBlockDevice part1(&bd, 1); int err = part1.init(); @@ -97,7 +99,7 @@ void test_read_write() { uint8_t *buffer2 = (uint8_t *)malloc(TEST_SIZE); TEST_ASSERT(buffer2); - + // Fill with random sequence srand(1); @@ -163,37 +165,38 @@ void test_read_write() { TEST_ASSERT_EQUAL(0, err); } -void test_single_mbr() { +void test_single_mbr() +{ int err = bd.init(); TEST_ASSERT_EQUAL(0, err); const bd_addr_t MBR_OFFSET = 0; const bd_addr_t FAT1_OFFSET = 1; - const bd_addr_t FAT2_OFFSET = BLOCK_COUNT/2; + const bd_addr_t FAT2_OFFSET = BLOCK_COUNT / 2; uint8_t *buffer = (uint8_t *)malloc(BLOCK_SIZE); TEST_ASSERT(buffer); // Check that all three header blocks have the 0x55aa signature - err = bd.read(buffer, MBR_OFFSET*BLOCK_SIZE, BLOCK_SIZE); + err = bd.read(buffer, MBR_OFFSET * BLOCK_SIZE, BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); - TEST_ASSERT(memcmp(&buffer[BLOCK_SIZE-2], "\x55\xaa", 2) == 0); + TEST_ASSERT(memcmp(&buffer[BLOCK_SIZE - 2], "\x55\xaa", 2) == 0); - err = bd.read(buffer, FAT1_OFFSET*BLOCK_SIZE, BLOCK_SIZE); + err = bd.read(buffer, FAT1_OFFSET * BLOCK_SIZE, BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); - TEST_ASSERT(memcmp(&buffer[BLOCK_SIZE-2], "\x55\xaa", 2) == 0); + TEST_ASSERT(memcmp(&buffer[BLOCK_SIZE - 2], "\x55\xaa", 2) == 0); - err = bd.read(buffer, FAT2_OFFSET*BLOCK_SIZE, BLOCK_SIZE); + err = bd.read(buffer, FAT2_OFFSET * BLOCK_SIZE, BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); - TEST_ASSERT(memcmp(&buffer[BLOCK_SIZE-2], "\x55\xaa", 2) == 0); + TEST_ASSERT(memcmp(&buffer[BLOCK_SIZE - 2], "\x55\xaa", 2) == 0); // Check that the headers for both filesystems contain a jump code // indicating they are actual FAT superblocks and not an extra MBR - err = bd.read(buffer, FAT1_OFFSET*BLOCK_SIZE, BLOCK_SIZE); + err = bd.read(buffer, FAT1_OFFSET * BLOCK_SIZE, BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); TEST_ASSERT(buffer[0] == 0xe9 || buffer[0] == 0xeb || buffer[0] == 0xe8); - err = bd.read(buffer, FAT2_OFFSET*BLOCK_SIZE, BLOCK_SIZE); + err = bd.read(buffer, FAT2_OFFSET * BLOCK_SIZE, BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); TEST_ASSERT(buffer[0] == 0xe9 || buffer[0] == 0xeb || buffer[0] == 0xe8); @@ -205,20 +208,22 @@ void test_single_mbr() { // Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { +utest::v1::status_t test_setup(const size_t number_of_cases) +{ GREENTEA_SETUP(10, "default_auto"); return verbose_test_setup_handler(number_of_cases); } Case cases[] = { Case("Testing formating", test_format), - Case("Testing read write < block", test_read_write), - Case("Testing read write > block", test_read_write<2*BLOCK_SIZE>), + Case("Testing read write < block", test_read_write < BLOCK_SIZE / 2 >), + Case("Testing read write > block", test_read_write<2 * BLOCK_SIZE>), Case("Testing for no extra MBRs", test_single_mbr), }; Specification specification(test_setup, cases); -int main() { +int main() +{ return !Harness::run(specification); } diff --git a/features/storage/blockdevice/BlockDevice.h b/features/storage/blockdevice/BlockDevice.h index c5c1408e35..edf7cbe004 100644 --- a/features/storage/blockdevice/BlockDevice.h +++ b/features/storage/blockdevice/BlockDevice.h @@ -40,8 +40,7 @@ typedef uint64_t bd_size_t; /** A hardware device capable of writing and reading blocks */ -class BlockDevice -{ +class BlockDevice { public: /** Return the default block device @@ -198,9 +197,9 @@ public: bool is_valid_read(bd_addr_t addr, bd_size_t size) const { return ( - addr % get_read_size() == 0 && - size % get_read_size() == 0 && - addr + size <= this->size()); + addr % get_read_size() == 0 && + size % get_read_size() == 0 && + addr + size <= this->size()); } /** Convenience function for checking block program validity @@ -212,9 +211,9 @@ public: bool is_valid_program(bd_addr_t addr, bd_size_t size) const { return ( - addr % get_program_size() == 0 && - size % get_program_size() == 0 && - addr + size <= this->size()); + addr % get_program_size() == 0 && + size % get_program_size() == 0 && + addr + size <= this->size()); } /** Convenience function for checking block erase validity @@ -226,9 +225,9 @@ public: bool is_valid_erase(bd_addr_t addr, bd_size_t size) const { return ( - addr % get_erase_size(addr) == 0 && - (addr + size) % get_erase_size(addr + size - 1) == 0 && - addr + size <= this->size()); + addr % get_erase_size(addr) == 0 && + (addr + size) % get_erase_size(addr + size - 1) == 0 && + addr + size <= this->size()); } }; diff --git a/features/storage/blockdevice/BufferedBlockDevice.cpp b/features/storage/blockdevice/BufferedBlockDevice.cpp index 86c324b26d..24c615710a 100644 --- a/features/storage/blockdevice/BufferedBlockDevice.cpp +++ b/features/storage/blockdevice/BufferedBlockDevice.cpp @@ -15,8 +15,8 @@ */ #include "BufferedBlockDevice.h" -#include "mbed_assert.h" -#include "mbed_critical.h" +#include "platform/mbed_assert.h" +#include "platform/mbed_critical.h" #include #include @@ -119,7 +119,7 @@ int BufferedBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) bd_addr_t aligned_addr = align_down(addr, _bd_program_size); - uint8_t *buf = static_cast (b); + uint8_t *buf = static_cast(b); if (aligned_addr != _curr_aligned_addr) { // Need to flush if moved to another program unit @@ -159,7 +159,7 @@ int BufferedBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) bd_addr_t aligned_addr = align_down(addr, _bd_program_size); - const uint8_t *buf = static_cast (b); + const uint8_t *buf = static_cast (b); // Need to flush if moved to another program unit if (aligned_addr != _curr_aligned_addr) { @@ -251,7 +251,7 @@ bd_size_t BufferedBlockDevice::get_program_size() const bd_size_t BufferedBlockDevice::get_erase_size() const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->get_erase_size(); @@ -260,7 +260,7 @@ bd_size_t BufferedBlockDevice::get_erase_size() const bd_size_t BufferedBlockDevice::get_erase_size(bd_addr_t addr) const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->get_erase_size(addr); @@ -278,7 +278,7 @@ int BufferedBlockDevice::get_erase_value() const bd_size_t BufferedBlockDevice::size() const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->size(); diff --git a/features/storage/blockdevice/ChainingBlockDevice.cpp b/features/storage/blockdevice/ChainingBlockDevice.cpp index 60a87a8e11..d1ce6495f8 100644 --- a/features/storage/blockdevice/ChainingBlockDevice.cpp +++ b/features/storage/blockdevice/ChainingBlockDevice.cpp @@ -15,7 +15,7 @@ */ #include "ChainingBlockDevice.h" -#include "mbed_critical.h" +#include "platform/mbed_critical.h" ChainingBlockDevice::ChainingBlockDevice(BlockDevice **bds, size_t bd_count) @@ -141,7 +141,7 @@ int ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) return BD_ERROR_DEVICE_ERROR; } - uint8_t *buffer = static_cast(b); + uint8_t *buffer = static_cast(b); // Find block devices containing blocks, may span multiple block devices for (size_t i = 0; i < _bd_count && size > 0; i++) { @@ -176,7 +176,7 @@ int ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) return BD_ERROR_DEVICE_ERROR; } - const uint8_t *buffer = static_cast(b); + const uint8_t *buffer = static_cast(b); // Find block devices containing blocks, may span multiple block devices for (size_t i = 0; i < _bd_count && size > 0; i++) { @@ -254,7 +254,7 @@ bd_size_t ChainingBlockDevice::get_erase_size() const bd_size_t ChainingBlockDevice::get_erase_size(bd_addr_t addr) const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } bd_addr_t bd_start_addr = 0; diff --git a/features/storage/blockdevice/ChainingBlockDevice.h b/features/storage/blockdevice/ChainingBlockDevice.h index fe7a3f7e18..94295e13a1 100644 --- a/features/storage/blockdevice/ChainingBlockDevice.h +++ b/features/storage/blockdevice/ChainingBlockDevice.h @@ -23,8 +23,8 @@ #define MBED_CHAINING_BLOCK_DEVICE_H #include "BlockDevice.h" -#include "mbed.h" - +#include "platform/mbed_assert.h" +#include /** Block device for chaining multiple block devices * with the similar block sizes at sequential addresses @@ -45,8 +45,7 @@ * ChainingBlockDevice chainmem(bds); * @endcode */ -class ChainingBlockDevice : public BlockDevice -{ +class ChainingBlockDevice : public BlockDevice { public: /** Lifetime of the memory block device * @@ -62,7 +61,7 @@ public: * @note All block devices must have the same block size */ template - ChainingBlockDevice(BlockDevice *(&bds)[Size]) + ChainingBlockDevice(BlockDevice * (&bds)[Size]) : _bds(bds), _bd_count(sizeof(bds) / sizeof(bds[0])) , _read_size(0), _program_size(0), _erase_size(0), _size(0), _init_ref_count(0) { @@ -179,5 +178,4 @@ protected: bool _is_initialized; }; - #endif diff --git a/features/storage/blockdevice/ExhaustibleBlockDevice.cpp b/features/storage/blockdevice/ExhaustibleBlockDevice.cpp index 36d5d94736..99afd00cf3 100644 --- a/features/storage/blockdevice/ExhaustibleBlockDevice.cpp +++ b/features/storage/blockdevice/ExhaustibleBlockDevice.cpp @@ -15,9 +15,8 @@ */ #include "ExhaustibleBlockDevice.h" -#include "mbed.h" -#include "mbed_critical.h" - +#include "platform/mbed_critical.h" +#include "platform/mbed_assert.h" ExhaustibleBlockDevice::ExhaustibleBlockDevice(BlockDevice *bd, uint32_t erase_cycles) : _bd(bd), _erase_array(NULL), _erase_cycles(erase_cycles), _init_ref_count(0), _is_initialized(false) @@ -142,7 +141,7 @@ int ExhaustibleBlockDevice::erase(bd_addr_t addr, bd_size_t size) bd_size_t ExhaustibleBlockDevice::get_read_size() const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->get_read_size(); @@ -151,7 +150,7 @@ bd_size_t ExhaustibleBlockDevice::get_read_size() const bd_size_t ExhaustibleBlockDevice::get_program_size() const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->get_program_size(); @@ -160,7 +159,7 @@ bd_size_t ExhaustibleBlockDevice::get_program_size() const bd_size_t ExhaustibleBlockDevice::get_erase_size() const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->get_erase_size(); @@ -169,7 +168,7 @@ bd_size_t ExhaustibleBlockDevice::get_erase_size() const bd_size_t ExhaustibleBlockDevice::get_erase_size(bd_addr_t addr) const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->get_erase_size(addr); @@ -187,7 +186,7 @@ int ExhaustibleBlockDevice::get_erase_value() const bd_size_t ExhaustibleBlockDevice::size() const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->size(); diff --git a/features/storage/blockdevice/ExhaustibleBlockDevice.h b/features/storage/blockdevice/ExhaustibleBlockDevice.h index 4559194058..480557430d 100644 --- a/features/storage/blockdevice/ExhaustibleBlockDevice.h +++ b/features/storage/blockdevice/ExhaustibleBlockDevice.h @@ -31,8 +31,7 @@ * after a configurable number of cycles. * */ -class ExhaustibleBlockDevice : public BlockDevice -{ +class ExhaustibleBlockDevice : public BlockDevice { public: /** Lifetime of the block device * diff --git a/features/storage/blockdevice/FlashSimBlockDevice.cpp b/features/storage/blockdevice/FlashSimBlockDevice.cpp index f69e4aa389..288896bd2c 100644 --- a/features/storage/blockdevice/FlashSimBlockDevice.cpp +++ b/features/storage/blockdevice/FlashSimBlockDevice.cpp @@ -15,8 +15,8 @@ */ #include "FlashSimBlockDevice.h" -#include "mbed_assert.h" -#include "mbed_critical.h" +#include "platform/mbed_assert.h" +#include "platform/mbed_critical.h" #include #include #include @@ -96,7 +96,7 @@ int FlashSimBlockDevice::sync() bd_size_t FlashSimBlockDevice::get_read_size() const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->get_read_size(); @@ -105,7 +105,7 @@ bd_size_t FlashSimBlockDevice::get_read_size() const bd_size_t FlashSimBlockDevice::get_program_size() const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->get_program_size(); @@ -114,7 +114,7 @@ bd_size_t FlashSimBlockDevice::get_program_size() const bd_size_t FlashSimBlockDevice::get_erase_size() const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->get_erase_size(); @@ -123,7 +123,7 @@ bd_size_t FlashSimBlockDevice::get_erase_size() const bd_size_t FlashSimBlockDevice::get_erase_size(bd_addr_t addr) const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->get_erase_size(addr); @@ -132,7 +132,7 @@ bd_size_t FlashSimBlockDevice::get_erase_size(bd_addr_t addr) const bd_size_t FlashSimBlockDevice::size() const { if (!_is_initialized) { - return BD_ERROR_DEVICE_ERROR; + return 0; } return _bd->size(); diff --git a/features/storage/blockdevice/HeapBlockDevice.cpp b/features/storage/blockdevice/HeapBlockDevice.cpp index 460e522f67..c0a027acf1 100644 --- a/features/storage/blockdevice/HeapBlockDevice.cpp +++ b/features/storage/blockdevice/HeapBlockDevice.cpp @@ -15,7 +15,7 @@ */ #include "HeapBlockDevice.h" -#include "mbed_critical.h" +#include "platform/mbed_critical.h" HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t block) @@ -53,7 +53,7 @@ int HeapBlockDevice::init() } if (!_blocks) { - _blocks = new uint8_t*[_count]; + _blocks = new uint8_t *[_count]; for (size_t i = 0; i < _count; i++) { _blocks[i] = 0; } @@ -120,7 +120,7 @@ int HeapBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) return BD_ERROR_DEVICE_ERROR; } - uint8_t *buffer = static_cast(b); + uint8_t *buffer = static_cast(b); while (size > 0) { bd_addr_t hi = addr / _erase_size; @@ -148,14 +148,14 @@ int HeapBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) return BD_ERROR_DEVICE_ERROR; } - const uint8_t *buffer = static_cast(b); + const uint8_t *buffer = static_cast(b); while (size > 0) { bd_addr_t hi = addr / _erase_size; bd_addr_t lo = addr % _erase_size; if (!_blocks[hi]) { - _blocks[hi] = (uint8_t*)malloc(_erase_size); + _blocks[hi] = (uint8_t *)malloc(_erase_size); if (!_blocks[hi]) { return BD_ERROR_DEVICE_ERROR; } diff --git a/features/storage/blockdevice/HeapBlockDevice.h b/features/storage/blockdevice/HeapBlockDevice.h index 5791aa67e3..23b36c36fb 100644 --- a/features/storage/blockdevice/HeapBlockDevice.h +++ b/features/storage/blockdevice/HeapBlockDevice.h @@ -23,8 +23,9 @@ #define MBED_MEM_BLOCK_DEVICE_H #include "BlockDevice.h" -#include "mbed.h" - +#include "platform/mbed_assert.h" +#include +#include /** Lazily allocated heap-backed block device * @@ -49,8 +50,7 @@ * } * @endcode */ -class HeapBlockDevice : public BlockDevice -{ +class HeapBlockDevice : public BlockDevice { public: /** Lifetime of the memory block device @@ -59,7 +59,7 @@ public: * @param block Block size in bytes. Minimum read, program, and erase sizes are * configured to this value */ - HeapBlockDevice(bd_size_t size, bd_size_t block=512); + HeapBlockDevice(bd_size_t size, bd_size_t block = 512); /** Lifetime of the memory block device * * @param size Size of the Block Device in bytes diff --git a/features/storage/blockdevice/MBRBlockDevice.cpp b/features/storage/blockdevice/MBRBlockDevice.cpp index 0d7e14ca28..40e8fa6f6d 100644 --- a/features/storage/blockdevice/MBRBlockDevice.cpp +++ b/features/storage/blockdevice/MBRBlockDevice.cpp @@ -15,9 +15,11 @@ */ #include "MBRBlockDevice.h" -#include "mbed_critical.h" +#include "platform/mbed_critical.h" +#include "platform/mbed_toolchain.h" +#include "platform/mbed_assert.h" #include - +#include // On disk structures, all entries are little endian MBED_PACKED(struct) mbr_entry { @@ -58,7 +60,7 @@ static inline uint32_t fromle32(uint32_t a) static void tochs(uint32_t lba, uint8_t chs[3]) { - uint32_t sector = std::min(lba, 0xfffffd)+1; + uint32_t sector = std::min(lba, 0xfffffd) + 1; chs[0] = (sector >> 6) & 0xff; chs[1] = ((sector >> 0) & 0x3f) | ((sector >> 16) & 0xc0); chs[2] = (sector >> 14) & 0xff; @@ -68,28 +70,28 @@ static void tochs(uint32_t lba, uint8_t chs[3]) // Partition after address are turned into absolute // addresses, assumes bd is initialized static int partition_absolute( - BlockDevice *bd, int part, uint8_t type, - bd_size_t offset, bd_size_t size) + BlockDevice *bd, int part, uint8_t type, + bd_size_t offset, bd_size_t size) { // Allocate smallest buffer necessary to write MBR uint32_t buffer_size = std::max(bd->get_program_size(), sizeof(struct mbr_table)); // Prevent alignment issues - if(buffer_size % bd->get_program_size() != 0) { + if (buffer_size % bd->get_program_size() != 0) { buffer_size += bd->get_program_size() - (buffer_size % bd->get_program_size()); } uint8_t *buffer = new uint8_t[buffer_size]; // Check for existing MBR - int err = bd->read(buffer, 512-buffer_size, buffer_size); + int err = bd->read(buffer, 512 - buffer_size, buffer_size); if (err) { delete[] buffer; return err; } - struct mbr_table *table = reinterpret_cast( - &buffer[buffer_size - sizeof(struct mbr_table)]); + struct mbr_table *table = reinterpret_cast( + &buffer[buffer_size - sizeof(struct mbr_table)]); if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) { // Setup default values for MBR table->signature[0] = 0x55; @@ -97,31 +99,43 @@ static int partition_absolute( memset(table->entries, 0, sizeof(table->entries)); } + // For Windows-formatted SD card, it is not partitioned (no MBR), but its PBR has the + // same boot signature (0xaa55) as MBR. We would easily mis-recognize this SD card has valid + // partitions if we only check partition type. We add check by only accepting 0x00 (inactive) + // /0x80 (active) for valid partition status. + for (int i = 1; i <= 4; i++) { + if (table->entries[i - 1].status != 0x00 && + table->entries[i - 1].status != 0x80) { + memset(table->entries, 0, sizeof(table->entries)); + break; + } + } + // Setup new partition MBED_ASSERT(part >= 1 && part <= 4); - table->entries[part-1].status = 0x00; // inactive (not bootable) - table->entries[part-1].type = type; + table->entries[part - 1].status = 0x00; // inactive (not bootable) + table->entries[part - 1].type = type; // lba dimensions MBED_ASSERT(bd->is_valid_erase(offset, size)); uint32_t sector = std::max(bd->get_erase_size(), 512); uint32_t lba_offset = offset / sector; uint32_t lba_size = size / sector; - table->entries[part-1].lba_offset = tole32(lba_offset); - table->entries[part-1].lba_size = tole32(lba_size); + table->entries[part - 1].lba_offset = tole32(lba_offset); + table->entries[part - 1].lba_size = tole32(lba_size); // chs dimensions - tochs(lba_offset, table->entries[part-1].chs_start); - tochs(lba_offset+lba_size-1, table->entries[part-1].chs_stop); + tochs(lba_offset, table->entries[part - 1].chs_start); + tochs(lba_offset + lba_size - 1, table->entries[part - 1].chs_stop); // Check that we don't overlap other entries for (int i = 1; i <= 4; i++) { - if (i != part && table->entries[i-1].type != 0x00) { - uint32_t neighbor_lba_offset = fromle32(table->entries[i-1].lba_offset); - uint32_t neighbor_lba_size = fromle32(table->entries[i-1].lba_size); + if (i != part && table->entries[i - 1].type != 0x00) { + uint32_t neighbor_lba_offset = fromle32(table->entries[i - 1].lba_offset); + uint32_t neighbor_lba_size = fromle32(table->entries[i - 1].lba_size); MBED_ASSERT( - (lba_offset >= neighbor_lba_offset + neighbor_lba_size) || - (lba_offset + lba_size <= neighbor_lba_offset)); + (lba_offset >= neighbor_lba_offset + neighbor_lba_size) || + (lba_offset + lba_size <= neighbor_lba_offset)); (void)neighbor_lba_offset; (void)neighbor_lba_size; } @@ -134,7 +148,7 @@ static int partition_absolute( return err; } - err = bd->program(buffer, 512-buffer_size, buffer_size); + err = bd->program(buffer, 512 - buffer_size, buffer_size); delete[] buffer; return err; } @@ -170,7 +184,7 @@ int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type, bd_addr_t } int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type, - bd_addr_t start, bd_addr_t stop) + bd_addr_t start, bd_addr_t stop) { int err = bd->init(); if (err) { @@ -229,33 +243,41 @@ int MBRBlockDevice::init() buffer_size = std::max(_bd->get_read_size(), sizeof(struct mbr_table)); buffer = new uint8_t[buffer_size]; - err = _bd->read(buffer, 512-buffer_size, buffer_size); + err = _bd->read(buffer, 512 - buffer_size, buffer_size); if (err) { goto fail; } // Check for valid table - table = reinterpret_cast(&buffer[buffer_size - sizeof(struct mbr_table)]); + table = reinterpret_cast(&buffer[buffer_size - sizeof(struct mbr_table)]); if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) { err = BD_ERROR_INVALID_MBR; goto fail; } + // Check for valid partition status + // Same reason as in partition_absolute regarding Windows-formatted SD card + if (table->entries[_part - 1].status != 0x00 && + table->entries[_part - 1].status != 0x80) { + err = BD_ERROR_INVALID_PARTITION; + goto fail; + } + // Check for valid entry // 0x00 = no entry // 0x05, 0x0f = extended partitions, currently not supported - if ((table->entries[_part-1].type == 0x00 || - table->entries[_part-1].type == 0x05 || - table->entries[_part-1].type == 0x0f)) { + if ((table->entries[_part - 1].type == 0x00 || + table->entries[_part - 1].type == 0x05 || + table->entries[_part - 1].type == 0x0f)) { err = BD_ERROR_INVALID_PARTITION; goto fail; } // Get partition attributes sector = std::max(_bd->get_erase_size(), 512); - _type = table->entries[_part-1].type; - _offset = fromle32(table->entries[_part-1].lba_offset) * sector; - _size = fromle32(table->entries[_part-1].lba_size) * sector; + _type = table->entries[_part - 1].type; + _offset = fromle32(table->entries[_part - 1].lba_offset) * sector; + _size = fromle32(table->entries[_part - 1].lba_size) * sector; // Check that block addresses are valid if (!_bd->is_valid_erase(_offset, _size)) { @@ -386,7 +408,7 @@ bd_size_t MBRBlockDevice::get_partition_start() const bd_size_t MBRBlockDevice::get_partition_stop() const { - return _offset+_size; + return _offset + _size; } uint8_t MBRBlockDevice::get_partition_type() const diff --git a/features/storage/blockdevice/MBRBlockDevice.h b/features/storage/blockdevice/MBRBlockDevice.h index 99fefef456..0d544b9e2a 100644 --- a/features/storage/blockdevice/MBRBlockDevice.h +++ b/features/storage/blockdevice/MBRBlockDevice.h @@ -23,7 +23,6 @@ #define MBED_MBR_BLOCK_DEVICE_H #include "BlockDevice.h" -#include "mbed.h" /** Additional error codes used for MBR records @@ -88,15 +87,14 @@ enum { * - At most 4 partitions are supported * - Extended partitions are currently not supported and will error during init */ -class MBRBlockDevice : public BlockDevice -{ +class MBRBlockDevice : public BlockDevice { public: /** Format the MBR to contain the following partition * * @param bd Block device to partition * @param part Partition to use, 1-4 * @param type 8-bit partition type to identitfy partition's contents - * @param start Start block address to map to block 0 of partition, + * @param start Start block address to map to block 0 of partition, * negative addresses are calculated from the end of the * underlying block devices. Block 0 is implicitly ignored * from the range to store the MBR. @@ -110,7 +108,7 @@ public: * @param bd Block device to partition * @param part Partition to use, 1-4 * @param type 8-bit partition type to identitfy partition's contents - * @param start Start block address to map to block 0 of partition, + * @param start Start block address to map to block 0 of partition, * negative addresses are calculated from the end of the * underlying block devices. Block 0 is implicitly ignored * from the range to store the MBR. diff --git a/features/storage/blockdevice/ObservingBlockDevice.cpp b/features/storage/blockdevice/ObservingBlockDevice.cpp index d484a57213..d343cb47a9 100644 --- a/features/storage/blockdevice/ObservingBlockDevice.cpp +++ b/features/storage/blockdevice/ObservingBlockDevice.cpp @@ -22,7 +22,6 @@ #include "ObservingBlockDevice.h" #include "ReadOnlyBlockDevice.h" -#include "mbed.h" ObservingBlockDevice::ObservingBlockDevice(BlockDevice *bd) @@ -36,7 +35,7 @@ ObservingBlockDevice::~ObservingBlockDevice() // Does nothing } -void ObservingBlockDevice::attach(Callback cb) +void ObservingBlockDevice::attach(mbed::Callback cb) { _change = cb; } diff --git a/features/storage/blockdevice/ObservingBlockDevice.h b/features/storage/blockdevice/ObservingBlockDevice.h index 9dce5fdf20..53ecc09f3d 100644 --- a/features/storage/blockdevice/ObservingBlockDevice.h +++ b/features/storage/blockdevice/ObservingBlockDevice.h @@ -23,12 +23,11 @@ #define MBED_OBSERVING_BLOCK_DEVICE_H #include "BlockDevice.h" -#include "PlatformMutex.h" -#include "Callback.h" +#include "platform/PlatformMutex.h" +#include "platform/Callback.h" -class ObservingBlockDevice : public BlockDevice -{ +class ObservingBlockDevice : public BlockDevice { public: /** Lifetime of the block device diff --git a/features/storage/blockdevice/ProfilingBlockDevice.h b/features/storage/blockdevice/ProfilingBlockDevice.h index 5d3a01323c..9f89a381ae 100644 --- a/features/storage/blockdevice/ProfilingBlockDevice.h +++ b/features/storage/blockdevice/ProfilingBlockDevice.h @@ -23,7 +23,6 @@ #define MBED_PROFILING_BLOCK_DEVICE_H #include "BlockDevice.h" -#include "mbed.h" /** Block device for measuring storage operations of another block device @@ -44,8 +43,7 @@ * printf("erase count: %lld\n", profiler.get_erase_count()); * @endcode */ -class ProfilingBlockDevice : public BlockDevice -{ +class ProfilingBlockDevice : public BlockDevice { public: /** Lifetime of the memory block device * diff --git a/features/storage/blockdevice/ReadOnlyBlockDevice.cpp b/features/storage/blockdevice/ReadOnlyBlockDevice.cpp index fe6e40c93d..f67d3738d5 100644 --- a/features/storage/blockdevice/ReadOnlyBlockDevice.cpp +++ b/features/storage/blockdevice/ReadOnlyBlockDevice.cpp @@ -23,7 +23,6 @@ #include "ReadOnlyBlockDevice.h" #include "mbed_error.h" - ReadOnlyBlockDevice::ReadOnlyBlockDevice(BlockDevice *bd) : _bd(bd) { diff --git a/features/storage/blockdevice/ReadOnlyBlockDevice.h b/features/storage/blockdevice/ReadOnlyBlockDevice.h index c7c59e638f..03f4d195e7 100644 --- a/features/storage/blockdevice/ReadOnlyBlockDevice.h +++ b/features/storage/blockdevice/ReadOnlyBlockDevice.h @@ -26,8 +26,7 @@ #include "PlatformMutex.h" -class ReadOnlyBlockDevice : public BlockDevice -{ +class ReadOnlyBlockDevice : public BlockDevice { public: /** Lifetime of the block device diff --git a/features/storage/blockdevice/SlicingBlockDevice.h b/features/storage/blockdevice/SlicingBlockDevice.h index 611fba2aba..0faf346860 100644 --- a/features/storage/blockdevice/SlicingBlockDevice.h +++ b/features/storage/blockdevice/SlicingBlockDevice.h @@ -23,8 +23,7 @@ #define MBED_SLICING_BLOCK_DEVICE_H #include "BlockDevice.h" -#include "mbed.h" - +#include "platform/mbed_assert.h" /** Block device for mapping to a slice of another block device * @@ -46,8 +45,7 @@ * SlicingBlockDevice slice3(&mem, 16*512, -16*512); * @endcode */ -class SlicingBlockDevice : public BlockDevice -{ +class SlicingBlockDevice : public BlockDevice { public: /** Lifetime of the memory block device * diff --git a/features/storage/filesystem/Dir.h b/features/storage/filesystem/Dir.h index 9ed97f837a..4e933bfa4b 100644 --- a/features/storage/filesystem/Dir.h +++ b/features/storage/filesystem/Dir.h @@ -35,7 +35,7 @@ public: */ Dir(); - /** Open a directory on a filesystem + /** Open a directory on a filesystem * * @param fs Filesystem as target for a directory * @param path Name of the directory to open @@ -86,7 +86,7 @@ public: */ virtual void rewind(); - /** Get the sizeof the directory + /** Get the sizeof the directory * * @return Number of files in the directory */ diff --git a/features/storage/filesystem/File.h b/features/storage/filesystem/File.h index d08cf7c0d7..3135763b6a 100644 --- a/features/storage/filesystem/File.h +++ b/features/storage/filesystem/File.h @@ -35,7 +35,7 @@ public: */ File(); - /** Create a file on a filesystem + /** Create a file on a filesystem * * Creates and opens a file on a filesystem * @@ -60,7 +60,7 @@ public: * bitwise or'd with one of O_CREAT, O_TRUNC, O_APPEND * @return 0 on success, negative error code on failure */ - virtual int open(FileSystem *fs, const char *path, int flags=O_RDONLY); + virtual int open(FileSystem *fs, const char *path, int flags = O_RDONLY); /** Close a file * @@ -80,7 +80,7 @@ public: /** Write the contents of a buffer to a file * * @param buffer The buffer to write from - * @param size The number of bytes to write + * @param size The number of bytes to write * @return The number of bytes written, negative error on failure */ virtual ssize_t write(const void *buffer, size_t size); diff --git a/features/storage/filesystem/FileSystem.cpp b/features/storage/filesystem/FileSystem.cpp index 047f3d7eb0..aeb79e37f4 100644 --- a/features/storage/filesystem/FileSystem.cpp +++ b/features/storage/filesystem/FileSystem.cpp @@ -139,7 +139,8 @@ size_t FileSystem::dir_size(fs_dir_t dir) template class Managed : public F { public: - virtual int close() { + virtual int close() + { int err = F::close(); delete this; return err; @@ -159,7 +160,8 @@ int FileSystem::open(FileHandle **file, const char *path, int flags) return 0; } -int FileSystem::open(DirHandle **dir, const char *path) { +int FileSystem::open(DirHandle **dir, const char *path) +{ Dir *d = new Managed; int err = d->open(this, path); if (err) { diff --git a/features/storage/filesystem/FileSystem.h b/features/storage/filesystem/FileSystem.h index 504d220167..c073139e43 100644 --- a/features/storage/filesystem/FileSystem.h +++ b/features/storage/filesystem/FileSystem.h @@ -131,7 +131,7 @@ public: * @param buf The stat buffer to write to * @return 0 on success, negative error code on failure */ - virtual int statvfs(const char *path, struct statvfs *buf); + virtual int statvfs(const char *path, struct statvfs *buf); protected: friend class File; diff --git a/features/storage/filesystem/fat/FATFileSystem.cpp b/features/storage/filesystem/fat/FATFileSystem.cpp index 38916ba2ba..3e808272e0 100644 --- a/features/storage/filesystem/fat/FATFileSystem.cpp +++ b/features/storage/filesystem/fat/FATFileSystem.cpp @@ -29,9 +29,11 @@ #include ////// Error handling ///// +using namespace mbed; + static int fat_error_remap(FRESULT res) { - switch(res) { + switch (res) { case FR_OK: // (0) Succeeded return 0; case FR_DISK_ERR: // (1) A hard error occurred in the low level disk I/O layer @@ -84,8 +86,8 @@ public: T _t; Callback _ondefer; - Deferred(const Deferred&); - Deferred &operator=(const Deferred&); + Deferred(const Deferred &); + Deferred &operator=(const Deferred &); public: Deferred(T t, Callback ondefer = NULL) @@ -113,7 +115,7 @@ static void dodelete(const char *data) // Adds prefix needed internally by fatfs, this can be avoided for the first fatfs // (id 0) otherwise a prefix of "id:/" is inserted in front of the string. -static Deferred fat_path_prefix(int id, const char *path) +static Deferred fat_path_prefix(int id, const char *path) { // We can avoid dynamic allocation when only on fatfs is in use if (id == 0) { @@ -130,7 +132,7 @@ static Deferred fat_path_prefix(int id, const char *path) buffer[1] = ':'; buffer[2] = '/'; strcpy(buffer + strlen("0:/"), path); - return Deferred(buffer, dodelete); + return Deferred(buffer, dodelete); } @@ -148,11 +150,11 @@ DWORD get_fattime(void) time(&rawtime); struct tm *ptm = localtime(&rawtime); return (DWORD)(ptm->tm_year - 80) << 25 - | (DWORD)(ptm->tm_mon + 1 ) << 21 - | (DWORD)(ptm->tm_mday ) << 16 - | (DWORD)(ptm->tm_hour ) << 11 - | (DWORD)(ptm->tm_min ) << 5 - | (DWORD)(ptm->tm_sec/2 ); + | (DWORD)(ptm->tm_mon + 1) << 21 + | (DWORD)(ptm->tm_mday) << 16 + | (DWORD)(ptm->tm_hour) << 11 + | (DWORD)(ptm->tm_min) << 5 + | (DWORD)(ptm->tm_sec / 2); } void *ff_memalloc(UINT size) @@ -168,7 +170,10 @@ void ff_memfree(void *p) // Implementation of diskio functions (see ChaN/diskio.h) static WORD disk_get_sector_size(BYTE pdrv) { - WORD ssize = _ffs[pdrv]->get_erase_size(); + bd_size_t sector_size = _ffs[pdrv]->get_erase_size(); + MBED_ASSERT(sector_size <= WORD(-1)); + + WORD ssize = sector_size; if (ssize < 512) { ssize = 512; } @@ -200,20 +205,20 @@ DSTATUS disk_initialize(BYTE pdrv) DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count) { - debug_if(FFS_DBG, "disk_read(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv); + debug_if(FFS_DBG, "disk_read(sector %lu, count %u) on pdrv [%d]\n", sector, count, pdrv); DWORD ssize = disk_get_sector_size(pdrv); - bd_addr_t addr = (bd_addr_t)sector*ssize; - bd_size_t size = (bd_size_t)count*ssize; + bd_addr_t addr = (bd_addr_t)sector * ssize; + bd_size_t size = (bd_size_t)count * ssize; int err = _ffs[pdrv]->read(buff, addr, size); return err ? RES_PARERR : RES_OK; } DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) { - debug_if(FFS_DBG, "disk_write(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv); + debug_if(FFS_DBG, "disk_write(sector %lu, count %u) on pdrv [%d]\n", sector, count, pdrv); DWORD ssize = disk_get_sector_size(pdrv); - bd_addr_t addr = (bd_addr_t)sector*ssize; - bd_size_t size = (bd_size_t)count*ssize; + bd_addr_t addr = (bd_addr_t)sector * ssize; + bd_size_t size = (bd_size_t)count * ssize; int err = _ffs[pdrv]->erase(addr, size); if (err) { return RES_PARERR; @@ -241,27 +246,27 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) if (_ffs[pdrv] == NULL) { return RES_NOTRDY; } else { - *((DWORD*)buff) = disk_get_sector_count(pdrv); + *((DWORD *)buff) = disk_get_sector_count(pdrv); return RES_OK; } case GET_SECTOR_SIZE: if (_ffs[pdrv] == NULL) { return RES_NOTRDY; } else { - *((WORD*)buff) = disk_get_sector_size(pdrv); + *((WORD *)buff) = disk_get_sector_size(pdrv); return RES_OK; } case GET_BLOCK_SIZE: - *((DWORD*)buff) = 1; // default when not known + *((DWORD *)buff) = 1; // default when not known return RES_OK; case CTRL_TRIM: if (_ffs[pdrv] == NULL) { return RES_NOTRDY; } else { - DWORD *sectors = (DWORD*)buff; + DWORD *sectors = (DWORD *)buff; DWORD ssize = disk_get_sector_size(pdrv); - bd_addr_t addr = (bd_addr_t)sectors[0]*ssize; - bd_size_t size = (bd_size_t)(sectors[1]-sectors[0]+1)*ssize; + bd_addr_t addr = (bd_addr_t)sectors[0] * ssize; + bd_size_t size = (bd_size_t)(sectors[1] - sectors[0] + 1) * ssize; int err = _ffs[pdrv]->trim(addr, size); return err ? RES_PARERR : RES_OK; } @@ -275,7 +280,8 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) // Filesystem implementation (See FATFilySystem.h) FATFileSystem::FATFileSystem(const char *name, BlockDevice *bd) - : FileSystem(name), _id(-1) { + : FileSystem(name), _id(-1) +{ if (bd) { mount(bd); } @@ -348,7 +354,7 @@ int FATFileSystem::format(BlockDevice *bd, bd_size_t cluster_size) } // erase first handful of blocks - bd_size_t header = 2*bd->get_erase_size(); + bd_size_t header = 2 * bd->get_erase_size(); err = bd->erase(0, header); if (err) { bd->deinit(); @@ -452,7 +458,7 @@ int FATFileSystem::reformat(BlockDevice *bd, int allocation_unit) int FATFileSystem::remove(const char *path) { - Deferred fpath = fat_path_prefix(_id, path); + Deferred fpath = fat_path_prefix(_id, path); lock(); FRESULT res = f_unlink(fpath); @@ -469,8 +475,8 @@ int FATFileSystem::remove(const char *path) int FATFileSystem::rename(const char *oldpath, const char *newpath) { - Deferred oldfpath = fat_path_prefix(_id, oldpath); - Deferred newfpath = fat_path_prefix(_id, newpath); + Deferred oldfpath = fat_path_prefix(_id, oldpath); + Deferred newfpath = fat_path_prefix(_id, newpath); lock(); FRESULT res = f_rename(oldfpath, newfpath); @@ -484,7 +490,7 @@ int FATFileSystem::rename(const char *oldpath, const char *newpath) int FATFileSystem::mkdir(const char *path, mode_t mode) { - Deferred fpath = fat_path_prefix(_id, path); + Deferred fpath = fat_path_prefix(_id, path); lock(); FRESULT res = f_mkdir(fpath); @@ -498,7 +504,7 @@ int FATFileSystem::mkdir(const char *path, mode_t mode) int FATFileSystem::stat(const char *path, struct stat *st) { - Deferred fpath = fat_path_prefix(_id, path); + Deferred fpath = fat_path_prefix(_id, path); lock(); FILINFO f; @@ -516,8 +522,8 @@ int FATFileSystem::stat(const char *path, struct stat *st) st->st_mode = 0; st->st_mode |= (f.fattrib & AM_DIR) ? S_IFDIR : S_IFREG; st->st_mode |= (f.fattrib & AM_RDO) ? - (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) : - (S_IRWXU | S_IRWXG | S_IRWXO); + (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) : + (S_IRWXU | S_IRWXG | S_IRWXO); #endif /* TOOLCHAIN_GCC */ unlock(); @@ -567,10 +573,10 @@ void FATFileSystem::unlock() ////// File operations ////// int FATFileSystem::file_open(fs_file_t *file, const char *path, int flags) { - debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%s]\n", path, getName(), _id); + debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%d]\n", path, getName(), _id); FIL *fh = new FIL; - Deferred fpath = fat_path_prefix(_id, path); + Deferred fpath = fat_path_prefix(_id, path); /* POSIX flags -> FatFS open mode */ BYTE openmode; @@ -612,7 +618,7 @@ int FATFileSystem::file_open(fs_file_t *file, const char *path, int flags) int FATFileSystem::file_close(fs_file_t file) { - FIL *fh = static_cast(file); + FIL *fh = static_cast(file); lock(); FRESULT res = f_close(fh); @@ -624,7 +630,7 @@ int FATFileSystem::file_close(fs_file_t file) ssize_t FATFileSystem::file_read(fs_file_t file, void *buffer, size_t len) { - FIL *fh = static_cast(file); + FIL *fh = static_cast(file); lock(); UINT n; @@ -641,7 +647,7 @@ ssize_t FATFileSystem::file_read(fs_file_t file, void *buffer, size_t len) ssize_t FATFileSystem::file_write(fs_file_t file, const void *buffer, size_t len) { - FIL *fh = static_cast(file); + FIL *fh = static_cast(file); lock(); UINT n; @@ -658,7 +664,7 @@ ssize_t FATFileSystem::file_write(fs_file_t file, const void *buffer, size_t len int FATFileSystem::file_sync(fs_file_t file) { - FIL *fh = static_cast(file); + FIL *fh = static_cast(file); lock(); FRESULT res = f_sync(fh); @@ -672,12 +678,12 @@ int FATFileSystem::file_sync(fs_file_t file) off_t FATFileSystem::file_seek(fs_file_t file, off_t offset, int whence) { - FIL *fh = static_cast(file); + FIL *fh = static_cast(file); lock(); if (whence == SEEK_END) { offset += f_size(fh); - } else if(whence==SEEK_CUR) { + } else if (whence == SEEK_CUR) { offset += f_tell(fh); } @@ -695,7 +701,7 @@ off_t FATFileSystem::file_seek(fs_file_t file, off_t offset, int whence) off_t FATFileSystem::file_tell(fs_file_t file) { - FIL *fh = static_cast(file); + FIL *fh = static_cast(file); lock(); off_t res = f_tell(fh); @@ -706,7 +712,7 @@ off_t FATFileSystem::file_tell(fs_file_t file) off_t FATFileSystem::file_size(fs_file_t file) { - FIL *fh = static_cast(file); + FIL *fh = static_cast(file); lock(); off_t res = f_size(fh); @@ -720,7 +726,7 @@ off_t FATFileSystem::file_size(fs_file_t file) int FATFileSystem::dir_open(fs_dir_t *dir, const char *path) { FATFS_DIR *dh = new FATFS_DIR; - Deferred fpath = fat_path_prefix(_id, path); + Deferred fpath = fat_path_prefix(_id, path); lock(); FRESULT res = f_opendir(dh, fpath); @@ -738,7 +744,7 @@ int FATFileSystem::dir_open(fs_dir_t *dir, const char *path) int FATFileSystem::dir_close(fs_dir_t dir) { - FATFS_DIR *dh = static_cast(dir); + FATFS_DIR *dh = static_cast(dir); lock(); FRESULT res = f_closedir(dh); @@ -750,7 +756,7 @@ int FATFileSystem::dir_close(fs_dir_t dir) ssize_t FATFileSystem::dir_read(fs_dir_t dir, struct dirent *ent) { - FATFS_DIR *dh = static_cast(dir); + FATFS_DIR *dh = static_cast(dir); FILINFO finfo; lock(); @@ -779,7 +785,7 @@ ssize_t FATFileSystem::dir_read(fs_dir_t dir, struct dirent *ent) void FATFileSystem::dir_seek(fs_dir_t dir, off_t offset) { - FATFS_DIR *dh = static_cast(dir); + FATFS_DIR *dh = static_cast(dir); off_t dptr = static_cast(dh->dptr); lock(); @@ -804,7 +810,7 @@ void FATFileSystem::dir_seek(fs_dir_t dir, off_t offset) off_t FATFileSystem::dir_tell(fs_dir_t dir) { - FATFS_DIR *dh = static_cast(dir); + FATFS_DIR *dh = static_cast(dir); lock(); off_t offset = dh->dptr; @@ -815,7 +821,7 @@ off_t FATFileSystem::dir_tell(fs_dir_t dir) void FATFileSystem::dir_rewind(fs_dir_t dir) { - FATFS_DIR *dh = static_cast(dir); + FATFS_DIR *dh = static_cast(dir); lock(); f_rewinddir(dh); diff --git a/features/storage/filesystem/fat/FATFileSystem.h b/features/storage/filesystem/fat/FATFileSystem.h index ed9fedaef4..5006a1b7f7 100644 --- a/features/storage/filesystem/fat/FATFileSystem.h +++ b/features/storage/filesystem/fat/FATFileSystem.h @@ -32,6 +32,8 @@ /** * FATFileSystem based on ChaN's Fat Filesystem library v0.8 + * + * Synchronization level: Thread safe */ class FATFileSystem : public mbed::FileSystem { public: @@ -144,7 +146,7 @@ public: * @param buf The stat buffer to write to * @return 0 on success, negative error code on failure */ - virtual int statvfs(const char *path, struct statvfs *buf); + virtual int statvfs(const char *path, struct statvfs *buf); protected: /** Open a file on the filesystem diff --git a/features/storage/filesystem/littlefs/LittleFileSystem.cpp b/features/storage/filesystem/littlefs/LittleFileSystem.cpp index 8e17af9a2f..63964431bd 100644 --- a/features/storage/filesystem/littlefs/LittleFileSystem.cpp +++ b/features/storage/filesystem/littlefs/LittleFileSystem.cpp @@ -20,9 +20,11 @@ #include "lfs_util.h" #include "MbedCRC.h" +using namespace mbed; + extern "C" void lfs_crc(uint32_t *crc, const void *buffer, size_t size) { - uint32_t initial_xor = *crc; + uint32_t initial_xor = *crc; MbedCRC ct(initial_xor, 0x0, true, false); ct.compute((void *)buffer, size, (uint32_t *) crc); } @@ -31,39 +33,54 @@ extern "C" void lfs_crc(uint32_t *crc, const void *buffer, size_t size) static int lfs_toerror(int err) { switch (err) { - case LFS_ERR_OK: return 0; - case LFS_ERR_IO: return -EIO; - case LFS_ERR_NOENT: return -ENOENT; - case LFS_ERR_EXIST: return -EEXIST; - case LFS_ERR_NOTDIR: return -ENOTDIR; - case LFS_ERR_ISDIR: return -EISDIR; - case LFS_ERR_INVAL: return -EINVAL; - case LFS_ERR_NOSPC: return -ENOSPC; - case LFS_ERR_NOMEM: return -ENOMEM; - case LFS_ERR_CORRUPT: return -EILSEQ; - default: return err; + case LFS_ERR_OK: + return 0; + case LFS_ERR_IO: + return -EIO; + case LFS_ERR_NOENT: + return -ENOENT; + case LFS_ERR_EXIST: + return -EEXIST; + case LFS_ERR_NOTDIR: + return -ENOTDIR; + case LFS_ERR_ISDIR: + return -EISDIR; + case LFS_ERR_INVAL: + return -EINVAL; + case LFS_ERR_NOSPC: + return -ENOSPC; + case LFS_ERR_NOMEM: + return -ENOMEM; + case LFS_ERR_CORRUPT: + return -EILSEQ; + default: + return err; } } static int lfs_fromflags(int flags) { return ( - (((flags & 3) == O_RDONLY) ? LFS_O_RDONLY : 0) | - (((flags & 3) == O_WRONLY) ? LFS_O_WRONLY : 0) | - (((flags & 3) == O_RDWR) ? LFS_O_RDWR : 0) | - ((flags & O_CREAT) ? LFS_O_CREAT : 0) | - ((flags & O_EXCL) ? LFS_O_EXCL : 0) | - ((flags & O_TRUNC) ? LFS_O_TRUNC : 0) | - ((flags & O_APPEND) ? LFS_O_APPEND : 0)); + (((flags & 3) == O_RDONLY) ? LFS_O_RDONLY : 0) | + (((flags & 3) == O_WRONLY) ? LFS_O_WRONLY : 0) | + (((flags & 3) == O_RDWR) ? LFS_O_RDWR : 0) | + ((flags & O_CREAT) ? LFS_O_CREAT : 0) | + ((flags & O_EXCL) ? LFS_O_EXCL : 0) | + ((flags & O_TRUNC) ? LFS_O_TRUNC : 0) | + ((flags & O_APPEND) ? LFS_O_APPEND : 0)); } static int lfs_fromwhence(int whence) { switch (whence) { - case SEEK_SET: return LFS_SEEK_SET; - case SEEK_CUR: return LFS_SEEK_CUR; - case SEEK_END: return LFS_SEEK_END; - default: return whence; + case SEEK_SET: + return LFS_SEEK_SET; + case SEEK_CUR: + return LFS_SEEK_CUR; + case SEEK_END: + return LFS_SEEK_END; + default: + return whence; } } @@ -71,39 +88,47 @@ static int lfs_tomode(int type) { int mode = S_IRWXU | S_IRWXG | S_IRWXO; switch (type) { - case LFS_TYPE_DIR: return mode | S_IFDIR; - case LFS_TYPE_REG: return mode | S_IFREG; - default: return 0; + case LFS_TYPE_DIR: + return mode | S_IFDIR; + case LFS_TYPE_REG: + return mode | S_IFREG; + default: + return 0; } } static int lfs_totype(int type) { switch (type) { - case LFS_TYPE_DIR: return DT_DIR; - case LFS_TYPE_REG: return DT_REG; - default: return DT_UNKNOWN; + case LFS_TYPE_DIR: + return DT_DIR; + case LFS_TYPE_REG: + return DT_REG; + default: + return DT_UNKNOWN; } } ////// Block device operations ////// static int lfs_bd_read(const struct lfs_config *c, lfs_block_t block, - lfs_off_t off, void *buffer, lfs_size_t size) { + lfs_off_t off, void *buffer, lfs_size_t size) +{ BlockDevice *bd = (BlockDevice *)c->context; - return bd->read(buffer, (bd_addr_t)block*c->block_size + off, size); + return bd->read(buffer, (bd_addr_t)block * c->block_size + off, size); } static int lfs_bd_prog(const struct lfs_config *c, lfs_block_t block, - lfs_off_t off, const void *buffer, lfs_size_t size) { + lfs_off_t off, const void *buffer, lfs_size_t size) +{ BlockDevice *bd = (BlockDevice *)c->context; - return bd->program(buffer, (bd_addr_t)block*c->block_size + off, size); + return bd->program(buffer, (bd_addr_t)block * c->block_size + off, size); } static int lfs_bd_erase(const struct lfs_config *c, lfs_block_t block) { BlockDevice *bd = (BlockDevice *)c->context; - return bd->erase((bd_addr_t)block*c->block_size, c->block_size); + return bd->erase((bd_addr_t)block * c->block_size, c->block_size); } static int lfs_bd_sync(const struct lfs_config *c) @@ -117,19 +142,21 @@ static int lfs_bd_sync(const struct lfs_config *c) // Filesystem implementation (See LittleFileSystem.h) LittleFileSystem::LittleFileSystem(const char *name, BlockDevice *bd, - lfs_size_t read_size, lfs_size_t prog_size, - lfs_size_t block_size, lfs_size_t lookahead) - : FileSystem(name) - , _read_size(read_size) - , _prog_size(prog_size) - , _block_size(block_size) - , _lookahead(lookahead) { + lfs_size_t read_size, lfs_size_t prog_size, + lfs_size_t block_size, lfs_size_t lookahead) + : FileSystem(name) + , _read_size(read_size) + , _prog_size(prog_size) + , _block_size(block_size) + , _lookahead(lookahead) +{ if (bd) { mount(bd); } } -LittleFileSystem::~LittleFileSystem() { +LittleFileSystem::~LittleFileSystem() +{ // nop if unmounted unmount(); } @@ -166,7 +193,7 @@ int LittleFileSystem::mount(BlockDevice *bd) _config.block_size = _block_size; } _config.block_count = bd->size() / _config.block_size; - _config.lookahead = 32 * ((_config.block_count+31)/32); + _config.lookahead = 32 * ((_config.block_count + 31) / 32); if (_config.lookahead > _lookahead) { _config.lookahead = _lookahead; } @@ -202,17 +229,18 @@ int LittleFileSystem::unmount() _bd = NULL; } - + LFS_INFO("unmount -> %d", res); _mutex.unlock(); return res; } int LittleFileSystem::format(BlockDevice *bd, - lfs_size_t read_size, lfs_size_t prog_size, - lfs_size_t block_size, lfs_size_t lookahead) { + lfs_size_t read_size, lfs_size_t prog_size, + lfs_size_t block_size, lfs_size_t lookahead) +{ LFS_INFO("format(%p, %ld, %ld, %ld, %ld)", - bd, read_size, prog_size, block_size, lookahead); + bd, read_size, prog_size, block_size, lookahead); int err = bd->init(); if (err) { LFS_INFO("format -> %d", err); @@ -221,7 +249,7 @@ int LittleFileSystem::format(BlockDevice *bd, lfs_t _lfs; struct lfs_config _config; - + memset(&_config, 0, sizeof(_config)); _config.context = bd; _config.read = lfs_bd_read; @@ -241,7 +269,7 @@ int LittleFileSystem::format(BlockDevice *bd, _config.block_size = block_size; } _config.block_count = bd->size() / _config.block_size; - _config.lookahead = 32 * ((_config.block_count+31)/32); + _config.lookahead = 32 * ((_config.block_count + 31) / 32); if (_config.lookahead > lookahead) { _config.lookahead = lookahead; } @@ -286,7 +314,7 @@ int LittleFileSystem::reformat(BlockDevice *bd) } int err = LittleFileSystem::format(bd, - _read_size, _prog_size, _block_size, _lookahead); + _read_size, _prog_size, _block_size, _lookahead); if (err) { LFS_INFO("reformat -> %d", err); _mutex.unlock(); diff --git a/features/storage/filesystem/littlefs/LittleFileSystem.h b/features/storage/filesystem/littlefs/LittleFileSystem.h index 57cd676563..5e2a4ec1ed 100644 --- a/features/storage/filesystem/littlefs/LittleFileSystem.h +++ b/features/storage/filesystem/littlefs/LittleFileSystem.h @@ -24,6 +24,8 @@ /** * LittleFileSystem, a little filesystem + * + * Synchronization level: Thread safe */ class LittleFileSystem : public mbed::FileSystem { public: @@ -49,13 +51,13 @@ public: * The lookahead buffer requires only 1 bit per block so it can be quite * large with little ram impact. Should be a multiple of 32. */ - LittleFileSystem(const char *name=NULL, BlockDevice *bd=NULL, - lfs_size_t read_size=MBED_LFS_READ_SIZE, - lfs_size_t prog_size=MBED_LFS_PROG_SIZE, - lfs_size_t block_size=MBED_LFS_BLOCK_SIZE, - lfs_size_t lookahead=MBED_LFS_LOOKAHEAD); + LittleFileSystem(const char *name = NULL, BlockDevice *bd = NULL, + lfs_size_t read_size = MBED_LFS_READ_SIZE, + lfs_size_t prog_size = MBED_LFS_PROG_SIZE, + lfs_size_t block_size = MBED_LFS_BLOCK_SIZE, + lfs_size_t lookahead = MBED_LFS_LOOKAHEAD); virtual ~LittleFileSystem(); - + /** Formats a block device with the LittleFileSystem * * The block device to format should be mounted when this function is called. @@ -80,10 +82,10 @@ public: * large with little ram impact. Should be a multiple of 32. */ static int format(BlockDevice *bd, - lfs_size_t read_size=MBED_LFS_READ_SIZE, - lfs_size_t prog_size=MBED_LFS_PROG_SIZE, - lfs_size_t block_size=MBED_LFS_BLOCK_SIZE, - lfs_size_t lookahead=MBED_LFS_LOOKAHEAD); + lfs_size_t read_size = MBED_LFS_READ_SIZE, + lfs_size_t prog_size = MBED_LFS_PROG_SIZE, + lfs_size_t block_size = MBED_LFS_BLOCK_SIZE, + lfs_size_t lookahead = MBED_LFS_LOOKAHEAD); /** Mounts a filesystem to a block device * @@ -180,7 +182,7 @@ protected: * * @param file File handle * @param buffer The buffer to write from - * @param size The number of bytes to write + * @param size The number of bytes to write * @return The number of bytes written, negative error on failure */ virtual ssize_t file_write(mbed::fs_file_t file, const void *buffer, size_t size); @@ -261,7 +263,7 @@ protected: * @param dir Dir handle */ virtual void dir_rewind(mbed::fs_dir_t dir); - + private: lfs_t _lfs; // _the actual filesystem struct lfs_config _config; diff --git a/features/storage/filesystem/littlefs/TESTS/COMMON/atomic_usage.cpp b/features/storage/filesystem/littlefs/TESTS/COMMON/atomic_usage.cpp index bd445b0089..181e9383fd 100644 --- a/features/storage/filesystem/littlefs/TESTS/COMMON/atomic_usage.cpp +++ b/features/storage/filesystem/littlefs/TESTS/COMMON/atomic_usage.cpp @@ -157,9 +157,9 @@ static int file_scanf(File *file, const char *format, ...) int res = file->read(buf, sizeof(buf) - 1); TEST_ASSERT_OR_EXIT(res >= 0); - va_start (args, format); - int count = vsscanf((char*)buf, format, args); - va_end (args); + va_start(args, format); + int count = vsscanf((char *)buf, format, args); + va_end(args); TEST_ASSERT_OR_EXIT(count >= 0); return count; @@ -176,9 +176,9 @@ static int file_printf(File *file, const char *format, ...) { uint8_t buf[BUFFER_SIZE]; va_list args; - va_start (args, format); - int size = vsprintf((char*)buf, format, args); - va_end (args); + va_start(args, format); + int size = vsprintf((char *)buf, format, args); + va_end(args); TEST_ASSERT_OR_EXIT((size >= 0) && (size <= (int)sizeof(buf))); if (file_write(file, buf, size)) { @@ -254,7 +254,7 @@ static void check_file_rename(FileSystem *fs) int files = 0; int valids = 0; - const char * const filenames[] = {FILE_RENAME_A, FILE_RENAME_B}; + const char *const filenames[] = {FILE_RENAME_A, FILE_RENAME_B}; for (int i = 0; i < 2; i++) { File file; @@ -300,7 +300,7 @@ static void setup_file_rename_replace(FileSystem *fs) uint32_t count = 0; uint8_t buf[BUFFER_SIZE]; memset(buf, 0, sizeof(buf)); - const int length = sprintf((char*)buf, FILE_RENAME_REPLACE_FMT, count); + const int length = sprintf((char *)buf, FILE_RENAME_REPLACE_FMT, count); TEST_ASSERT_OR_EXIT(length > 0); res = file.write(buf, length); @@ -602,7 +602,7 @@ static bool format_required(BlockDevice *bd) // Get the test version uint32_t version = 0; - res = sscanf((char*)buf, FILE_SETUP_COMPLETE_FMT, &version); + res = sscanf((char *)buf, FILE_SETUP_COMPLETE_FMT, &version); if (res != 1) { return true; } diff --git a/features/storage/filesystem/littlefs/TESTS/filesystem/dirs/main.cpp b/features/storage/filesystem/littlefs/TESTS/filesystem/dirs/main.cpp index f88b6280da..8225baba11 100644 --- a/features/storage/filesystem/littlefs/TESTS/filesystem/dirs/main.cpp +++ b/features/storage/filesystem/littlefs/TESTS/filesystem/dirs/main.cpp @@ -300,8 +300,8 @@ void test_multi_block_directory() res = fs.mkdir("cactus", 0777); TEST_ASSERT_EQUAL(0, res); for (int i = 0; i < 128; i++) { - sprintf((char*)buffer, "cactus/test%d", i); - res = fs.mkdir((char*)buffer, 0777); + sprintf((char *)buffer, "cactus/test%d", i); + res = fs.mkdir((char *)buffer, 0777); TEST_ASSERT_EQUAL(0, res); } res = fs.unmount(); @@ -326,10 +326,10 @@ void test_multi_block_directory() res = ent.d_type; TEST_ASSERT_EQUAL(DT_DIR, res); for (int i = 0; i < 128; i++) { - sprintf((char*)buffer, "test%d", i); + sprintf((char *)buffer, "test%d", i); res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char*)buffer); + res = strcmp(ent.d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); } res = dir[0].read(&ent); diff --git a/features/storage/filesystem/littlefs/TESTS/filesystem/files/main.cpp b/features/storage/filesystem/littlefs/TESTS/filesystem/files/main.cpp index 658867bdb7..e852a0ee7b 100644 --- a/features/storage/filesystem/littlefs/TESTS/filesystem/files/main.cpp +++ b/features/storage/filesystem/littlefs/TESTS/filesystem/files/main.cpp @@ -167,7 +167,7 @@ void test_small_file_test() chunk = (chunk < size - i) ? chunk : size - i; res = file[0].read(buffer, chunk); TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i+b < size; b++) { + for (size_t b = 0; b < chunk && i + b < size; b++) { res = buffer[b]; TEST_ASSERT_EQUAL(rand() & 0xff, res); } @@ -221,7 +221,7 @@ void test_medium_file_test() chunk = (chunk < size - i) ? chunk : size - i; res = file[0].read(buffer, chunk); TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i+b < size; b++) { + for (size_t b = 0; b < chunk && i + b < size; b++) { res = buffer[b]; TEST_ASSERT_EQUAL(rand() & 0xff, res); } @@ -275,7 +275,7 @@ void test_large_file_test() chunk = (chunk < size - i) ? chunk : size - i; res = file[0].read(buffer, chunk); TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i+b < size; b++) { + for (size_t b = 0; b < chunk && i + b < size; b++) { res = buffer[b]; TEST_ASSERT_EQUAL(rand() & 0xff, res); } @@ -307,7 +307,7 @@ void test_non_overlap_check() chunk = (chunk < size - i) ? chunk : size - i; res = file[0].read(buffer, chunk); TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i+b < size; b++) { + for (size_t b = 0; b < chunk && i + b < size; b++) { res = buffer[b]; TEST_ASSERT_EQUAL(rand() & 0xff, res); } @@ -330,7 +330,7 @@ void test_non_overlap_check() chunk = (chunk < size - i) ? chunk : size - i; res = file[0].read(buffer, chunk); TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i+b < size; b++) { + for (size_t b = 0; b < chunk && i + b < size; b++) { res = buffer[b]; TEST_ASSERT_EQUAL(rand() & 0xff, res); } @@ -353,7 +353,7 @@ void test_non_overlap_check() chunk = (chunk < size - i) ? chunk : size - i; res = file[0].read(buffer, chunk); TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i+b < size; b++) { + for (size_t b = 0; b < chunk && i + b < size; b++) { res = buffer[b]; TEST_ASSERT_EQUAL(rand() & 0xff, res); } @@ -388,28 +388,28 @@ void test_dir_check() TEST_ASSERT_EQUAL(0, res); res = ent.d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); res = strcmp(ent.d_name, "smallavacado"); TEST_ASSERT_EQUAL(0, res); res = ent.d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); res = strcmp(ent.d_name, "mediumavacado"); TEST_ASSERT_EQUAL(0, res); res = ent.d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); res = strcmp(ent.d_name, "largeavacado"); TEST_ASSERT_EQUAL(0, res); res = ent.d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = dir[0].read(&ent); TEST_ASSERT_EQUAL(0, res); res = dir[0].close(); diff --git a/features/storage/filesystem/littlefs/TESTS/filesystem/interspersed/main.cpp b/features/storage/filesystem/littlefs/TESTS/filesystem/interspersed/main.cpp index c16a6f5629..51f198af4e 100644 --- a/features/storage/filesystem/littlefs/TESTS/filesystem/interspersed/main.cpp +++ b/features/storage/filesystem/littlefs/TESTS/filesystem/interspersed/main.cpp @@ -111,18 +111,18 @@ void test_parallel_file_test() TEST_ASSERT_EQUAL(0, res); res = file[3].open(&fs, "d", O_WRONLY | O_CREAT); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 10; i++) { - res = file[0].write((const void*)"a", 1); + res = file[0].write((const void *)"a", 1); TEST_ASSERT_EQUAL(1, res); - res = file[1].write((const void*)"b", 1); + res = file[1].write((const void *)"b", 1); TEST_ASSERT_EQUAL(1, res); - res = file[2].write((const void*)"c", 1); + res = file[2].write((const void *)"c", 1); TEST_ASSERT_EQUAL(1, res); - res = file[3].write((const void*)"d", 1); + res = file[3].write((const void *)"d", 1); TEST_ASSERT_EQUAL(1, res); } - + file[0].close(); file[1].close(); file[2].close(); @@ -147,28 +147,28 @@ void test_parallel_file_test() TEST_ASSERT_EQUAL(0, res); res = ent.d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); res = strcmp(ent.d_name, "b"); TEST_ASSERT_EQUAL(0, res); res = ent.d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); res = strcmp(ent.d_name, "c"); TEST_ASSERT_EQUAL(0, res); res = ent.d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); res = strcmp(ent.d_name, "d"); TEST_ASSERT_EQUAL(0, res); res = ent.d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = dir[0].read(&ent); TEST_ASSERT_EQUAL(0, res); res = dir[0].close(); @@ -181,7 +181,7 @@ void test_parallel_file_test() TEST_ASSERT_EQUAL(0, res); res = file[3].open(&fs, "d", O_RDONLY); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 10; i++) { res = file[0].read(buffer, 1); TEST_ASSERT_EQUAL(1, res); @@ -200,7 +200,7 @@ void test_parallel_file_test() res = buffer[0]; TEST_ASSERT_EQUAL('d', res); } - + file[0].close(); file[1].close(); file[2].close(); @@ -223,9 +223,9 @@ void test_parallel_remove_file_test() TEST_ASSERT_EQUAL(0, res); res = file[0].open(&fs, "e", O_WRONLY | O_CREAT); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 5; i++) { - res = file[0].write((const void*)"e", 1); + res = file[0].write((const void *)"e", 1); TEST_ASSERT_EQUAL(1, res); } res = fs.remove("a"); @@ -236,12 +236,12 @@ void test_parallel_remove_file_test() TEST_ASSERT_EQUAL(0, res); res = fs.remove("d"); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 5; i++) { - res = file[0].write((const void*)"e", 1); + res = file[0].write((const void *)"e", 1); TEST_ASSERT_EQUAL(1, res); } - + file[0].close(); res = dir[0].open(&fs, "/"); TEST_ASSERT_EQUAL(0, res); @@ -263,21 +263,21 @@ void test_parallel_remove_file_test() TEST_ASSERT_EQUAL(0, res); res = ent.d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = dir[0].read(&ent); TEST_ASSERT_EQUAL(0, res); res = dir[0].close(); TEST_ASSERT_EQUAL(0, res); res = file[0].open(&fs, "e", O_RDONLY); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 10; i++) { res = file[0].read(buffer, 1); TEST_ASSERT_EQUAL(1, res); res = buffer[0]; TEST_ASSERT_EQUAL('e', res); } - + file[0].close(); res = fs.unmount(); TEST_ASSERT_EQUAL(0, res); @@ -301,27 +301,27 @@ void test_remove_inconveniently_test() TEST_ASSERT_EQUAL(0, res); res = file[2].open(&fs, "g", O_WRONLY | O_CREAT); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 5; i++) { - res = file[0].write((const void*)"e", 1); + res = file[0].write((const void *)"e", 1); TEST_ASSERT_EQUAL(1, res); - res = file[1].write((const void*)"f", 1); + res = file[1].write((const void *)"f", 1); TEST_ASSERT_EQUAL(1, res); - res = file[2].write((const void*)"g", 1); + res = file[2].write((const void *)"g", 1); TEST_ASSERT_EQUAL(1, res); } res = fs.remove("f"); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 5; i++) { - res = file[0].write((const void*)"e", 1); + res = file[0].write((const void *)"e", 1); TEST_ASSERT_EQUAL(1, res); - res = file[1].write((const void*)"f", 1); + res = file[1].write((const void *)"f", 1); TEST_ASSERT_EQUAL(1, res); - res = file[2].write((const void*)"g", 1); + res = file[2].write((const void *)"g", 1); TEST_ASSERT_EQUAL(1, res); } - + file[0].close(); file[1].close(); file[2].close(); @@ -345,14 +345,14 @@ void test_remove_inconveniently_test() TEST_ASSERT_EQUAL(0, res); res = ent.d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); res = strcmp(ent.d_name, "g"); TEST_ASSERT_EQUAL(0, res); res = ent.d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = dir[0].read(&ent); TEST_ASSERT_EQUAL(0, res); res = dir[0].close(); @@ -361,7 +361,7 @@ void test_remove_inconveniently_test() TEST_ASSERT_EQUAL(0, res); res = file[1].open(&fs, "g", O_RDONLY); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 10; i++) { res = file[0].read(buffer, 1); TEST_ASSERT_EQUAL(1, res); @@ -372,7 +372,7 @@ void test_remove_inconveniently_test() res = buffer[0]; TEST_ASSERT_EQUAL('g', res); } - + file[0].close(); file[1].close(); res = fs.unmount(); diff --git a/features/storage/filesystem/littlefs/TESTS/filesystem/seek/main.cpp b/features/storage/filesystem/littlefs/TESTS/filesystem/seek/main.cpp index 1f00ca476b..0b41321c31 100644 --- a/features/storage/filesystem/littlefs/TESTS/filesystem/seek/main.cpp +++ b/features/storage/filesystem/littlefs/TESTS/filesystem/seek/main.cpp @@ -94,11 +94,11 @@ void test_seek_tests() res = fs.mkdir("hello", 0777); TEST_ASSERT_EQUAL(0, res); for (int i = 0; i < 132; i++) { - sprintf((char*)buffer, "hello/kitty%d", i); - res = file[0].open(&fs, (char*)buffer, - O_WRONLY | O_CREAT | O_APPEND); + sprintf((char *)buffer, "hello/kitty%d", i); + res = file[0].open(&fs, (char *)buffer, + O_WRONLY | O_CREAT | O_APPEND); TEST_ASSERT_EQUAL(0, res); - + size = strlen("kittycatcat"); memcpy(buffer, "kittycatcat", size); for (int j = 0; j < 132; j++) { @@ -133,29 +133,29 @@ void test_simple_dir_seek() TEST_ASSERT_EQUAL(1, res); res = strcmp(ent.d_name, ".."); TEST_ASSERT_EQUAL(0, res); - + off_t pos; int i; for (i = 0; i < 4; i++) { - sprintf((char*)buffer, "kitty%d", i); + sprintf((char *)buffer, "kitty%d", i); res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char*)buffer); + res = strcmp(ent.d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); pos = dir[0].tell(); } res = pos >= 0; TEST_ASSERT_EQUAL(1, res); - + dir[0].seek(pos); - sprintf((char*)buffer, "kitty%d", i); + sprintf((char *)buffer, "kitty%d", i); res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char*)buffer); + res = strcmp(ent.d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); - + dir[0].rewind(); - sprintf((char*)buffer, "kitty%d", 0); + sprintf((char *)buffer, "kitty%d", 0); res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); res = strcmp(ent.d_name, "."); @@ -166,14 +166,14 @@ void test_simple_dir_seek() TEST_ASSERT_EQUAL(0, res); res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char*)buffer); + res = strcmp(ent.d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); - + dir[0].seek(pos); - sprintf((char*)buffer, "kitty%d", i); + sprintf((char *)buffer, "kitty%d", i); res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char*)buffer); + res = strcmp(ent.d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); res = dir[0].close(); TEST_ASSERT_EQUAL(0, res); @@ -203,29 +203,29 @@ void test_large_dir_seek() TEST_ASSERT_EQUAL(1, res); res = strcmp(ent.d_name, ".."); TEST_ASSERT_EQUAL(0, res); - + off_t pos; int i; for (i = 0; i < 128; i++) { - sprintf((char*)buffer, "kitty%d", i); + sprintf((char *)buffer, "kitty%d", i); res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char*)buffer); + res = strcmp(ent.d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); pos = dir[0].tell(); } res = pos >= 0; TEST_ASSERT_EQUAL(1, res); - + dir[0].seek(pos); - sprintf((char*)buffer, "kitty%d", i); + sprintf((char *)buffer, "kitty%d", i); res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char*)buffer); + res = strcmp(ent.d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); - + dir[0].rewind(); - sprintf((char*)buffer, "kitty%d", 0); + sprintf((char *)buffer, "kitty%d", 0); res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); res = strcmp(ent.d_name, "."); @@ -236,14 +236,14 @@ void test_large_dir_seek() TEST_ASSERT_EQUAL(0, res); res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char*)buffer); + res = strcmp(ent.d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); - + dir[0].seek(pos); - sprintf((char*)buffer, "kitty%d", i); + sprintf((char *)buffer, "kitty%d", i); res = dir[0].read(&ent); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char*)buffer); + res = strcmp(ent.d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); res = dir[0].close(); TEST_ASSERT_EQUAL(0, res); @@ -265,7 +265,7 @@ void test_simple_file_seek() TEST_ASSERT_EQUAL(0, res); res = file[0].open(&fs, "hello/kitty42", O_RDONLY); TEST_ASSERT_EQUAL(0, res); - + off_t pos; size = strlen("kittycatcat"); for (int i = 0; i < 4; i++) { @@ -283,7 +283,7 @@ void test_simple_file_seek() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "kittycatcat", size); TEST_ASSERT_EQUAL(0, res); - + file[0].rewind(); res = file[0].read(buffer, size); TEST_ASSERT_EQUAL(size, res); @@ -307,7 +307,7 @@ void test_simple_file_seek() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "kittycatcat", size); TEST_ASSERT_EQUAL(0, res); - + size_t size = file[0].size(); res = file[0].seek(0, SEEK_CUR); TEST_ASSERT_EQUAL(size, res); @@ -331,7 +331,7 @@ void test_large_file_seek() TEST_ASSERT_EQUAL(0, res); res = file[0].open(&fs, "hello/kitty42", O_RDONLY); TEST_ASSERT_EQUAL(0, res); - + off_t pos; size = strlen("kittycatcat"); for (int i = 0; i < 128; i++) { @@ -349,7 +349,7 @@ void test_large_file_seek() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "kittycatcat", size); TEST_ASSERT_EQUAL(0, res); - + file[0].rewind(); res = file[0].read(buffer, size); TEST_ASSERT_EQUAL(size, res); @@ -373,7 +373,7 @@ void test_large_file_seek() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "kittycatcat", size); TEST_ASSERT_EQUAL(0, res); - + size_t size = file[0].size(); res = file[0].seek(0, SEEK_CUR); TEST_ASSERT_EQUAL(size, res); @@ -397,7 +397,7 @@ void test_simple_file_seek_and_write() TEST_ASSERT_EQUAL(0, res); res = file[0].open(&fs, "hello/kitty42", O_RDWR); TEST_ASSERT_EQUAL(0, res); - + off_t pos; size = strlen("kittycatcat"); for (int i = 0; i < 4; i++) { @@ -409,7 +409,7 @@ void test_simple_file_seek_and_write() } res = pos >= 0; TEST_ASSERT_EQUAL(1, res); - + memcpy(buffer, "doggodogdog", size); res = file[0].seek(pos, SEEK_SET); TEST_ASSERT_EQUAL(pos, res); @@ -421,7 +421,7 @@ void test_simple_file_seek_and_write() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "doggodogdog", size); TEST_ASSERT_EQUAL(0, res); - + file[0].rewind(); res = file[0].read(buffer, size); TEST_ASSERT_EQUAL(size, res); @@ -439,7 +439,7 @@ void test_simple_file_seek_and_write() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "kittycatcat", size); TEST_ASSERT_EQUAL(0, res); - + size_t size = file[0].size(); res = file[0].seek(0, SEEK_CUR); TEST_ASSERT_EQUAL(size, res); @@ -463,7 +463,7 @@ void test_large_file_seek_and_write() TEST_ASSERT_EQUAL(0, res); res = file[0].open(&fs, "hello/kitty42", O_RDWR); TEST_ASSERT_EQUAL(0, res); - + off_t pos; size = strlen("kittycatcat"); for (int i = 0; i < 128; i++) { @@ -477,7 +477,7 @@ void test_large_file_seek_and_write() } res = pos >= 0; TEST_ASSERT_EQUAL(1, res); - + memcpy(buffer, "doggodogdog", size); res = file[0].seek(pos, SEEK_SET); TEST_ASSERT_EQUAL(pos, res); @@ -489,7 +489,7 @@ void test_large_file_seek_and_write() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "doggodogdog", size); TEST_ASSERT_EQUAL(0, res); - + file[0].rewind(); res = file[0].read(buffer, size); TEST_ASSERT_EQUAL(size, res); @@ -507,7 +507,7 @@ void test_large_file_seek_and_write() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "kittycatcat", size); TEST_ASSERT_EQUAL(0, res); - + size_t size = file[0].size(); res = file[0].seek(0, SEEK_CUR); TEST_ASSERT_EQUAL(size, res); @@ -531,10 +531,10 @@ void test_boundary_seek_and_write() TEST_ASSERT_EQUAL(0, res); res = file[0].open(&fs, "hello/kitty42", O_RDWR); TEST_ASSERT_EQUAL(0, res); - + size = strlen("hedgehoghog"); const off_t offsets[] = {512, 1020, 513, 1021, 511, 1019}; - + for (int i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++) { off_t off = offsets[i]; memcpy(buffer, "hedgehoghog", size); @@ -577,29 +577,29 @@ void test_out_of_bounds_seek() TEST_ASSERT_EQUAL(0, res); res = file[0].open(&fs, "hello/kitty42", O_RDWR); TEST_ASSERT_EQUAL(0, res); - + size = strlen("kittycatcat"); res = file[0].size(); - TEST_ASSERT_EQUAL(132*size, res); - res = file[0].seek((132+4)*size, - SEEK_SET); - TEST_ASSERT_EQUAL((132+4)*size, res); + TEST_ASSERT_EQUAL(132 * size, res); + res = file[0].seek((132 + 4) * size, + SEEK_SET); + TEST_ASSERT_EQUAL((132 + 4)*size, res); res = file[0].read(buffer, size); TEST_ASSERT_EQUAL(0, res); - + memcpy(buffer, "porcupineee", size); res = file[0].write(buffer, size); TEST_ASSERT_EQUAL(size, res); - res = file[0].seek((132+4)*size, - SEEK_SET); - TEST_ASSERT_EQUAL((132+4)*size, res); + res = file[0].seek((132 + 4) * size, + SEEK_SET); + TEST_ASSERT_EQUAL((132 + 4)*size, res); res = file[0].read(buffer, size); TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "porcupineee", size); TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(132*size, - SEEK_SET); - TEST_ASSERT_EQUAL(132*size, res); + res = file[0].seek(132 * size, + SEEK_SET); + TEST_ASSERT_EQUAL(132 * size, res); res = file[0].read(buffer, size); TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "\0\0\0\0\0\0\0\0\0\0\0", size); diff --git a/features/storage/filesystem/littlefs/TESTS/filesystem_integration/format/main.cpp b/features/storage/filesystem/littlefs/TESTS/filesystem_integration/format/main.cpp index b841daec52..eab5359c68 100644 --- a/features/storage/filesystem/littlefs/TESTS/filesystem_integration/format/main.cpp +++ b/features/storage/filesystem/littlefs/TESTS/filesystem_integration/format/main.cpp @@ -117,10 +117,10 @@ void test_bad_mount() TEST_ASSERT_EQUAL(0, res); { - res = bd.erase(0, 2*bd.get_erase_size()); + res = bd.erase(0, 2 * bd.get_erase_size()); TEST_ASSERT_EQUAL(0, res); memset(buffer, 0, bd.get_program_size()); - for (int i = 0; i < 2*bd.get_erase_size(); i += bd.get_program_size()) { + for (int i = 0; i < 2 * bd.get_erase_size(); i += bd.get_program_size()) { res = bd.program(buffer, i, bd.get_program_size()); TEST_ASSERT_EQUAL(0, res); } diff --git a/features/storage/filesystem/littlefs/TESTS/filesystem_recovery/resilience/main.cpp b/features/storage/filesystem/littlefs/TESTS/filesystem_recovery/resilience/main.cpp index c3419afa98..802fb65a84 100644 --- a/features/storage/filesystem/littlefs/TESTS/filesystem_recovery/resilience/main.cpp +++ b/features/storage/filesystem/littlefs/TESTS/filesystem_recovery/resilience/main.cpp @@ -68,7 +68,7 @@ void test_resilience() bd_size_t block_size = bd.get_erase_size(); bd.deinit(); - SlicingBlockDevice slice(&bd, 0, MBED_TEST_BLOCK_COUNT*block_size); + SlicingBlockDevice slice(&bd, 0, MBED_TEST_BLOCK_COUNT * block_size); // Setup the test setup_atomic_operations(&slice, true); diff --git a/features/storage/filesystem/littlefs/TESTS/filesystem_recovery/wear_leveling/main.cpp b/features/storage/filesystem/littlefs/TESTS/filesystem_recovery/wear_leveling/main.cpp index 95efe3eff8..a9b8973ce8 100644 --- a/features/storage/filesystem/littlefs/TESTS/filesystem_recovery/wear_leveling/main.cpp +++ b/features/storage/filesystem/littlefs/TESTS/filesystem_recovery/wear_leveling/main.cpp @@ -62,11 +62,11 @@ static uint32_t test_wear_leveling_size(uint32_t block_count) bd_size_t block_size = bd.get_erase_size(); bd.deinit(); - SlicingBlockDevice slice(&bd, 0, block_count*block_size); + SlicingBlockDevice slice(&bd, 0, block_count * block_size); ExhaustibleBlockDevice ebd(&slice, MBED_TEST_ERASE_CYCLES); printf("Testing size %llu bytes (%lux%llu) blocks\n", - block_count*block_size, block_count, block_size); + block_count * block_size, block_count, block_size); setup_atomic_operations(&ebd, true); int64_t cycles = 0; diff --git a/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/dirs/main.cpp b/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/dirs/main.cpp index 0c91ef5a5f..8793040512 100644 --- a/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/dirs/main.cpp +++ b/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/dirs/main.cpp @@ -301,8 +301,8 @@ void test_multi_block_directory() res = mkdir("/fs/" "cactus", 0777); TEST_ASSERT_EQUAL(0, res); for (int i = 0; i < 128; i++) { - sprintf((char*)buffer, "/fs/" "cactus/test%d", i); - res = mkdir((char*)buffer, 0777); + sprintf((char *)buffer, "/fs/" "cactus/test%d", i); + res = mkdir((char *)buffer, 0777); TEST_ASSERT_EQUAL(0, res); } res = fs.unmount(); @@ -327,10 +327,10 @@ void test_multi_block_directory() res = ed->d_type; TEST_ASSERT_EQUAL(DT_DIR, res); for (int i = 0; i < 128; i++) { - sprintf((char*)buffer, "test%d", i); + sprintf((char *)buffer, "test%d", i); res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ed->d_name, (char*)buffer); + res = strcmp(ed->d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); } res = ((ed = readdir(dd[0])) != NULL); diff --git a/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/files/main.cpp b/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/files/main.cpp index c9deae2d92..120eff1612 100644 --- a/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/files/main.cpp +++ b/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/files/main.cpp @@ -167,7 +167,7 @@ void test_small_file_test() chunk = (chunk < size - i) ? chunk : size - i; res = fread(buffer, 1, chunk, fd[0]); TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i+b < size; b++) { + for (size_t b = 0; b < chunk && i + b < size; b++) { res = buffer[b]; TEST_ASSERT_EQUAL(rand() & 0xff, res); } @@ -221,7 +221,7 @@ void test_medium_file_test() chunk = (chunk < size - i) ? chunk : size - i; res = fread(buffer, 1, chunk, fd[0]); TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i+b < size; b++) { + for (size_t b = 0; b < chunk && i + b < size; b++) { res = buffer[b]; TEST_ASSERT_EQUAL(rand() & 0xff, res); } @@ -275,7 +275,7 @@ void test_large_file_test() chunk = (chunk < size - i) ? chunk : size - i; res = fread(buffer, 1, chunk, fd[0]); TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i+b < size; b++) { + for (size_t b = 0; b < chunk && i + b < size; b++) { res = buffer[b]; TEST_ASSERT_EQUAL(rand() & 0xff, res); } @@ -307,7 +307,7 @@ void test_non_overlap_check() chunk = (chunk < size - i) ? chunk : size - i; res = fread(buffer, 1, chunk, fd[0]); TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i+b < size; b++) { + for (size_t b = 0; b < chunk && i + b < size; b++) { res = buffer[b]; TEST_ASSERT_EQUAL(rand() & 0xff, res); } @@ -330,7 +330,7 @@ void test_non_overlap_check() chunk = (chunk < size - i) ? chunk : size - i; res = fread(buffer, 1, chunk, fd[0]); TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i+b < size; b++) { + for (size_t b = 0; b < chunk && i + b < size; b++) { res = buffer[b]; TEST_ASSERT_EQUAL(rand() & 0xff, res); } @@ -353,7 +353,7 @@ void test_non_overlap_check() chunk = (chunk < size - i) ? chunk : size - i; res = fread(buffer, 1, chunk, fd[0]); TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i+b < size; b++) { + for (size_t b = 0; b < chunk && i + b < size; b++) { res = buffer[b]; TEST_ASSERT_EQUAL(rand() & 0xff, res); } @@ -388,28 +388,28 @@ void test_dir_check() TEST_ASSERT_EQUAL(0, res); res = ed->d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); res = strcmp(ed->d_name, "smallavacado"); TEST_ASSERT_EQUAL(0, res); res = ed->d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); res = strcmp(ed->d_name, "mediumavacado"); TEST_ASSERT_EQUAL(0, res); res = ed->d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); res = strcmp(ed->d_name, "largeavacado"); TEST_ASSERT_EQUAL(0, res); res = ed->d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(0, res); res = closedir(dd[0]); diff --git a/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/interspersed/main.cpp b/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/interspersed/main.cpp index f622c01a6a..46ee79d447 100644 --- a/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/interspersed/main.cpp +++ b/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/interspersed/main.cpp @@ -111,18 +111,18 @@ void test_parallel_file_test() TEST_ASSERT_EQUAL(0, res); res = !((fd[3] = fopen("/fs/" "d", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 10; i++) { - res = fwrite((const void*)"a", 1, 1, fd[0]); + res = fwrite((const void *)"a", 1, 1, fd[0]); TEST_ASSERT_EQUAL(1, res); - res = fwrite((const void*)"b", 1, 1, fd[1]); + res = fwrite((const void *)"b", 1, 1, fd[1]); TEST_ASSERT_EQUAL(1, res); - res = fwrite((const void*)"c", 1, 1, fd[2]); + res = fwrite((const void *)"c", 1, 1, fd[2]); TEST_ASSERT_EQUAL(1, res); - res = fwrite((const void*)"d", 1, 1, fd[3]); + res = fwrite((const void *)"d", 1, 1, fd[3]); TEST_ASSERT_EQUAL(1, res); } - + fclose(fd[0]); fclose(fd[1]); fclose(fd[2]); @@ -147,28 +147,28 @@ void test_parallel_file_test() TEST_ASSERT_EQUAL(0, res); res = ed->d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); res = strcmp(ed->d_name, "b"); TEST_ASSERT_EQUAL(0, res); res = ed->d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); res = strcmp(ed->d_name, "c"); TEST_ASSERT_EQUAL(0, res); res = ed->d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); res = strcmp(ed->d_name, "d"); TEST_ASSERT_EQUAL(0, res); res = ed->d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(0, res); res = closedir(dd[0]); @@ -181,7 +181,7 @@ void test_parallel_file_test() TEST_ASSERT_EQUAL(0, res); res = !((fd[3] = fopen("/fs/" "d", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 10; i++) { res = fread(buffer, 1, 1, fd[0]); TEST_ASSERT_EQUAL(1, res); @@ -200,7 +200,7 @@ void test_parallel_file_test() res = buffer[0]; TEST_ASSERT_EQUAL('d', res); } - + fclose(fd[0]); fclose(fd[1]); fclose(fd[2]); @@ -223,9 +223,9 @@ void test_parallel_remove_file_test() TEST_ASSERT_EQUAL(0, res); res = !((fd[0] = fopen("/fs/" "e", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 5; i++) { - res = fwrite((const void*)"e", 1, 1, fd[0]); + res = fwrite((const void *)"e", 1, 1, fd[0]); TEST_ASSERT_EQUAL(1, res); } res = remove("/fs/" "a"); @@ -236,12 +236,12 @@ void test_parallel_remove_file_test() TEST_ASSERT_EQUAL(0, res); res = remove("/fs/" "d"); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 5; i++) { - res = fwrite((const void*)"e", 1, 1, fd[0]); + res = fwrite((const void *)"e", 1, 1, fd[0]); TEST_ASSERT_EQUAL(1, res); } - + fclose(fd[0]); res = !((dd[0] = opendir("/fs/" "/")) != NULL); TEST_ASSERT_EQUAL(0, res); @@ -263,21 +263,21 @@ void test_parallel_remove_file_test() TEST_ASSERT_EQUAL(0, res); res = ed->d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(0, res); res = closedir(dd[0]); TEST_ASSERT_EQUAL(0, res); res = !((fd[0] = fopen("/fs/" "e", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 10; i++) { res = fread(buffer, 1, 1, fd[0]); TEST_ASSERT_EQUAL(1, res); res = buffer[0]; TEST_ASSERT_EQUAL('e', res); } - + fclose(fd[0]); res = fs.unmount(); TEST_ASSERT_EQUAL(0, res); @@ -301,27 +301,27 @@ void test_remove_inconveniently_test() TEST_ASSERT_EQUAL(0, res); res = !((fd[2] = fopen("/fs/" "g", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 5; i++) { - res = fwrite((const void*)"e", 1, 1, fd[0]); + res = fwrite((const void *)"e", 1, 1, fd[0]); TEST_ASSERT_EQUAL(1, res); - res = fwrite((const void*)"f", 1, 1, fd[1]); + res = fwrite((const void *)"f", 1, 1, fd[1]); TEST_ASSERT_EQUAL(1, res); - res = fwrite((const void*)"g", 1, 1, fd[2]); + res = fwrite((const void *)"g", 1, 1, fd[2]); TEST_ASSERT_EQUAL(1, res); } res = remove("/fs/" "f"); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 5; i++) { - res = fwrite((const void*)"e", 1, 1, fd[0]); + res = fwrite((const void *)"e", 1, 1, fd[0]); TEST_ASSERT_EQUAL(1, res); - res = fwrite((const void*)"f", 1, 1, fd[1]); + res = fwrite((const void *)"f", 1, 1, fd[1]); TEST_ASSERT_EQUAL(1, res); - res = fwrite((const void*)"g", 1, 1, fd[2]); + res = fwrite((const void *)"g", 1, 1, fd[2]); TEST_ASSERT_EQUAL(1, res); } - + fclose(fd[0]); fclose(fd[1]); fclose(fd[2]); @@ -345,14 +345,14 @@ void test_remove_inconveniently_test() TEST_ASSERT_EQUAL(0, res); res = ed->d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); res = strcmp(ed->d_name, "g"); TEST_ASSERT_EQUAL(0, res); res = ed->d_type; TEST_ASSERT_EQUAL(DT_REG, res); - + res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(0, res); res = closedir(dd[0]); @@ -361,7 +361,7 @@ void test_remove_inconveniently_test() TEST_ASSERT_EQUAL(0, res); res = !((fd[1] = fopen("/fs/" "g", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); - + for (int i = 0; i < 10; i++) { res = fread(buffer, 1, 1, fd[0]); TEST_ASSERT_EQUAL(1, res); @@ -372,7 +372,7 @@ void test_remove_inconveniently_test() res = buffer[0]; TEST_ASSERT_EQUAL('g', res); } - + fclose(fd[0]); fclose(fd[1]); res = fs.unmount(); diff --git a/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/seek/main.cpp b/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/seek/main.cpp index 24ad870533..6e904fce20 100644 --- a/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/seek/main.cpp +++ b/features/storage/filesystem/littlefs/TESTS/filesystem_retarget/seek/main.cpp @@ -94,11 +94,11 @@ void test_seek_tests() res = mkdir("/fs/" "hello", 0777); TEST_ASSERT_EQUAL(0, res); for (int i = 0; i < 132; i++) { - sprintf((char*)buffer, "/fs/" "hello/kitty%d", i); - res = !((fd[0] = fopen((char*)buffer, - "ab")) != NULL); + sprintf((char *)buffer, "/fs/" "hello/kitty%d", i); + res = !((fd[0] = fopen((char *)buffer, + "ab")) != NULL); TEST_ASSERT_EQUAL(0, res); - + size = strlen("kittycatcat"); memcpy(buffer, "kittycatcat", size); for (int j = 0; j < 132; j++) { @@ -133,29 +133,29 @@ void test_simple_dir_seek() TEST_ASSERT_EQUAL(1, res); res = strcmp(ed->d_name, ".."); TEST_ASSERT_EQUAL(0, res); - + off_t pos; int i; for (i = 0; i < 4; i++) { - sprintf((char*)buffer, "kitty%d", i); + sprintf((char *)buffer, "kitty%d", i); res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ed->d_name, (char*)buffer); + res = strcmp(ed->d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); pos = telldir(dd[0]); } res = pos >= 0; TEST_ASSERT_EQUAL(1, res); - + seekdir(dd[0], pos); - sprintf((char*)buffer, "kitty%d", i); + sprintf((char *)buffer, "kitty%d", i); res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ed->d_name, (char*)buffer); + res = strcmp(ed->d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); - + rewinddir(dd[0]); - sprintf((char*)buffer, "kitty%d", 0); + sprintf((char *)buffer, "kitty%d", 0); res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); res = strcmp(ed->d_name, "."); @@ -166,14 +166,14 @@ void test_simple_dir_seek() TEST_ASSERT_EQUAL(0, res); res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ed->d_name, (char*)buffer); + res = strcmp(ed->d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); - + seekdir(dd[0], pos); - sprintf((char*)buffer, "kitty%d", i); + sprintf((char *)buffer, "kitty%d", i); res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ed->d_name, (char*)buffer); + res = strcmp(ed->d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); res = closedir(dd[0]); TEST_ASSERT_EQUAL(0, res); @@ -203,29 +203,29 @@ void test_large_dir_seek() TEST_ASSERT_EQUAL(1, res); res = strcmp(ed->d_name, ".."); TEST_ASSERT_EQUAL(0, res); - + off_t pos; int i; for (i = 0; i < 128; i++) { - sprintf((char*)buffer, "kitty%d", i); + sprintf((char *)buffer, "kitty%d", i); res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ed->d_name, (char*)buffer); + res = strcmp(ed->d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); pos = telldir(dd[0]); } res = pos >= 0; TEST_ASSERT_EQUAL(1, res); - + seekdir(dd[0], pos); - sprintf((char*)buffer, "kitty%d", i); + sprintf((char *)buffer, "kitty%d", i); res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ed->d_name, (char*)buffer); + res = strcmp(ed->d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); - + rewinddir(dd[0]); - sprintf((char*)buffer, "kitty%d", 0); + sprintf((char *)buffer, "kitty%d", 0); res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); res = strcmp(ed->d_name, "."); @@ -236,14 +236,14 @@ void test_large_dir_seek() TEST_ASSERT_EQUAL(0, res); res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ed->d_name, (char*)buffer); + res = strcmp(ed->d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); - + seekdir(dd[0], pos); - sprintf((char*)buffer, "kitty%d", i); + sprintf((char *)buffer, "kitty%d", i); res = ((ed = readdir(dd[0])) != NULL); TEST_ASSERT_EQUAL(1, res); - res = strcmp(ed->d_name, (char*)buffer); + res = strcmp(ed->d_name, (char *)buffer); TEST_ASSERT_EQUAL(0, res); res = closedir(dd[0]); TEST_ASSERT_EQUAL(0, res); @@ -265,7 +265,7 @@ void test_simple_file_seek() TEST_ASSERT_EQUAL(0, res); res = !((fd[0] = fopen("/fs/" "hello/kitty42", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); - + off_t pos; size = strlen("kittycatcat"); for (int i = 0; i < 4; i++) { @@ -283,7 +283,7 @@ void test_simple_file_seek() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "kittycatcat", size); TEST_ASSERT_EQUAL(0, res); - + rewind(fd[0]); res = fread(buffer, 1, size, fd[0]); TEST_ASSERT_EQUAL(size, res); @@ -307,7 +307,7 @@ void test_simple_file_seek() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "kittycatcat", size); TEST_ASSERT_EQUAL(0, res); - + res = fseek(fd[0], 0, SEEK_CUR); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); @@ -330,7 +330,7 @@ void test_large_file_seek() TEST_ASSERT_EQUAL(0, res); res = !((fd[0] = fopen("/fs/" "hello/kitty42", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); - + off_t pos; size = strlen("kittycatcat"); for (int i = 0; i < 128; i++) { @@ -348,7 +348,7 @@ void test_large_file_seek() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "kittycatcat", size); TEST_ASSERT_EQUAL(0, res); - + rewind(fd[0]); res = fread(buffer, 1, size, fd[0]); TEST_ASSERT_EQUAL(size, res); @@ -372,7 +372,7 @@ void test_large_file_seek() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "kittycatcat", size); TEST_ASSERT_EQUAL(0, res); - + res = fseek(fd[0], 0, SEEK_CUR); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); @@ -395,7 +395,7 @@ void test_simple_file_seek_and_write() TEST_ASSERT_EQUAL(0, res); res = !((fd[0] = fopen("/fs/" "hello/kitty42", "r+b")) != NULL); TEST_ASSERT_EQUAL(0, res); - + off_t pos; size = strlen("kittycatcat"); for (int i = 0; i < 4; i++) { @@ -407,7 +407,7 @@ void test_simple_file_seek_and_write() } res = pos >= 0; TEST_ASSERT_EQUAL(1, res); - + memcpy(buffer, "doggodogdog", size); res = fseek(fd[0], pos, SEEK_SET); TEST_ASSERT_EQUAL(0, res); @@ -419,7 +419,7 @@ void test_simple_file_seek_and_write() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "doggodogdog", size); TEST_ASSERT_EQUAL(0, res); - + rewind(fd[0]); res = fread(buffer, 1, size, fd[0]); TEST_ASSERT_EQUAL(size, res); @@ -437,7 +437,7 @@ void test_simple_file_seek_and_write() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "kittycatcat", size); TEST_ASSERT_EQUAL(0, res); - + res = fseek(fd[0], 0, SEEK_CUR); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); @@ -460,7 +460,7 @@ void test_large_file_seek_and_write() TEST_ASSERT_EQUAL(0, res); res = !((fd[0] = fopen("/fs/" "hello/kitty42", "r+b")) != NULL); TEST_ASSERT_EQUAL(0, res); - + off_t pos; size = strlen("kittycatcat"); for (int i = 0; i < 128; i++) { @@ -474,7 +474,7 @@ void test_large_file_seek_and_write() } res = pos >= 0; TEST_ASSERT_EQUAL(1, res); - + memcpy(buffer, "doggodogdog", size); res = fseek(fd[0], pos, SEEK_SET); TEST_ASSERT_EQUAL(0, res); @@ -486,7 +486,7 @@ void test_large_file_seek_and_write() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "doggodogdog", size); TEST_ASSERT_EQUAL(0, res); - + rewind(fd[0]); res = fread(buffer, 1, size, fd[0]); TEST_ASSERT_EQUAL(size, res); @@ -504,7 +504,7 @@ void test_large_file_seek_and_write() TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "kittycatcat", size); TEST_ASSERT_EQUAL(0, res); - + res = fseek(fd[0], 0, SEEK_CUR); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); @@ -527,10 +527,10 @@ void test_boundary_seek_and_write() TEST_ASSERT_EQUAL(0, res); res = !((fd[0] = fopen("/fs/" "hello/kitty42", "r+b")) != NULL); TEST_ASSERT_EQUAL(0, res); - + size = strlen("hedgehoghog"); const off_t offsets[] = {512, 1020, 513, 1021, 511, 1019}; - + for (int i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++) { off_t off = offsets[i]; memcpy(buffer, "hedgehoghog", size); @@ -573,30 +573,30 @@ void test_out_of_bounds_seek() TEST_ASSERT_EQUAL(0, res); res = !((fd[0] = fopen("/fs/" "hello/kitty42", "r+b")) != NULL); TEST_ASSERT_EQUAL(0, res); - + size = strlen("kittycatcat"); res = fseek(fd[0], 0, SEEK_END); TEST_ASSERT_EQUAL(0, res); res = ftell(fd[0]); - TEST_ASSERT_EQUAL(132*size, res); - res = fseek(fd[0], (132+4)*size, - SEEK_SET); + TEST_ASSERT_EQUAL(132 * size, res); + res = fseek(fd[0], (132 + 4) * size, + SEEK_SET); TEST_ASSERT_EQUAL(0, res); res = fread(buffer, 1, size, fd[0]); TEST_ASSERT_EQUAL(0, res); - + memcpy(buffer, "porcupineee", size); res = fwrite(buffer, 1, size, fd[0]); TEST_ASSERT_EQUAL(size, res); - res = fseek(fd[0], (132+4)*size, - SEEK_SET); + res = fseek(fd[0], (132 + 4) * size, + SEEK_SET); TEST_ASSERT_EQUAL(0, res); res = fread(buffer, 1, size, fd[0]); TEST_ASSERT_EQUAL(size, res); res = memcmp(buffer, "porcupineee", size); TEST_ASSERT_EQUAL(0, res); - res = fseek(fd[0], 132*size, - SEEK_SET); + res = fseek(fd[0], 132 * size, + SEEK_SET); TEST_ASSERT_EQUAL(0, res); res = fread(buffer, 1, size, fd[0]); TEST_ASSERT_EQUAL(size, res); diff --git a/features/storage/nvstore/TESTS/nvstore/functionality/main.cpp b/features/storage/nvstore/TESTS/nvstore/functionality/main.cpp index a58ae13310..dade9a7d2c 100644 --- a/features/storage/nvstore/TESTS/nvstore/functionality/main.cpp +++ b/features/storage/nvstore/TESTS/nvstore/functionality/main.cpp @@ -465,7 +465,7 @@ static void nvstore_multi_thread_test() if (!threads) { goto mem_fail; } - memset(threads, 0, thr_test_num_threads * sizeof(rtos::Thread*)); + memset(threads, 0, thr_test_num_threads * sizeof(rtos::Thread *)); ret = nvstore.reset(); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, ret); @@ -510,7 +510,7 @@ static void nvstore_multi_thread_test() if (!threads[i]) { goto mem_fail; } - threads[i]->start(callback(thread_test_worker)); + threads[i]->start(mbed::callback(thread_test_worker)); } wait_ms(thr_test_num_secs * 1000); @@ -635,7 +635,7 @@ static void nvstore_race_test() } delete[] dummy; - threads[i]->start(callback(race_test_worker, (void *) buffs[i])); + threads[i]->start(mbed::callback(race_test_worker, (void *) buffs[i])); threads[i]->join(); } @@ -666,7 +666,8 @@ clean: -utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) { +utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) +{ greentea_case_failure_abort_handler(source, reason); return STATUS_CONTINUE; } diff --git a/features/storage/nvstore/mbed_lib.json b/features/storage/nvstore/mbed_lib.json index d13cdbd4b2..a7f72acad0 100644 --- a/features/storage/nvstore/mbed_lib.json +++ b/features/storage/nvstore/mbed_lib.json @@ -27,5 +27,19 @@ "macro_name": "NVSTORE_AREA_2_SIZE", "help": "Area 2 size" } + }, + "target_overrides": { + "FUTURE_SEQUANA": { + "area_1_address": "0x100F8000", + "area_1_size": 16384, + "area_2_address": "0x100FC000", + "area_2_size": 16384 + }, + "FUTURE_SEQUANA_M0": { + "area_1_address": "0x10078000", + "area_1_size": 16384, + "area_2_address": "0x1007C000", + "area_2_size": 16384 + } } } diff --git a/features/storage/nvstore/source/nvstore.cpp b/features/storage/nvstore/source/nvstore.cpp index 3fb2e1f6ad..f049062af1 100644 --- a/features/storage/nvstore/source/nvstore.cpp +++ b/features/storage/nvstore/source/nvstore.cpp @@ -38,8 +38,7 @@ static const uint16_t master_record_key = 0xFFE; static const uint16_t no_key = 0xFFF; static const uint16_t last_reserved_key = master_record_key; -typedef struct -{ +typedef struct { uint16_t key_and_flags; uint16_t size_and_owner; uint32_t crc; @@ -88,10 +87,12 @@ static const uint8_t blank_flash_val = 0xFF; #endif NVStore::nvstore_area_data_t NVStore::initial_area_params[] = {{NVSTORE_AREA_1_ADDRESS, NVSTORE_AREA_1_SIZE}, - {NVSTORE_AREA_2_ADDRESS, NVSTORE_AREA_2_SIZE}}; + {NVSTORE_AREA_2_ADDRESS, NVSTORE_AREA_2_SIZE} +}; #else NVStore::nvstore_area_data_t NVStore::initial_area_params[] = {{0, 0}, - {0, 0}}; + {0, 0} +}; #endif typedef enum { @@ -130,18 +131,18 @@ static uint32_t crc32(uint32_t init_crc, uint32_t data_size, uint8_t *data_buf) crc = init_crc; for (i = 0; i < data_size; i++) { - crc = crc ^ (uint32_t) (data_buf[i]); + crc = crc ^ (uint32_t)(data_buf[i]); for (j = 0; j < 8; j++) { - mask = -(crc & 1); - crc = (crc >> 1) ^ (0xEDB88320 & mask); + mask = -(crc & 1); + crc = (crc >> 1) ^ (0xEDB88320 & mask); } } return crc; } NVStore::NVStore() : _init_done(0), _init_attempts(0), _active_area(0), _max_keys(NVSTORE_MAX_KEYS), - _active_area_version(0), _free_space_offset(0), _size(0), _mutex(0), _offset_by_key(0), _flash(0), - _min_prog_size(0), _page_buf(0) + _active_area_version(0), _free_space_offset(0), _size(0), _mutex(0), _offset_by_key(0), _flash(0), + _min_prog_size(0), _page_buf(0) { } @@ -270,7 +271,7 @@ void NVStore::calc_validate_area_params() _flash_area_params[area].size = 0; int i; for (i = num_sectors - 1; i >= 0; i--) { - sector_size = sector_map[i+1] - sector_map[i]; + sector_size = sector_map[i + 1] - sector_map[i]; _flash_area_params[area].size += sector_size; if (_flash_area_params[area].size >= min_area_size) { _flash_area_params[area].address = sector_map[i]; @@ -534,8 +535,8 @@ int NVStore::garbage_collection(uint16_t key, uint16_t flags, uint8_t owner, uin return ret; } _offset_by_key[key] = new_area_offset | (1 - _active_area) << offs_by_key_area_bit_pos | - (((flags & set_once_flag) != 0) << offs_by_key_set_once_bit_pos) | - (owner << offs_by_key_owner_bit_pos); + (((flags & set_once_flag) != 0) << offs_by_key_set_once_bit_pos) | + (owner << offs_by_key_owner_bit_pos); new_area_offset = next_offset; } @@ -608,7 +609,7 @@ int NVStore::do_get(uint16_t key, uint16_t buf_size, void *buf, uint16_t &actual } _mutex->lock(); - + record_offset = _offset_by_key[key]; area = (uint8_t)(record_offset >> offs_by_key_area_bit_pos) & 1; record_offset &= offs_by_key_offset_mask; diff --git a/features/storage/nvstore/source/nvstore.h b/features/storage/nvstore/source/nvstore.h index 7665d37904..53f3f7dcdf 100644 --- a/features/storage/nvstore/source/nvstore.h +++ b/features/storage/nvstore/source/nvstore.h @@ -84,7 +84,7 @@ public: * * @returns Singleton instance reference. */ - static NVStore& get_instance() + static NVStore &get_instance() { // Use this implementation of singleton (Meyer's) rather than the one that allocates // the instance on the heap because it ensures destruction at program end (preventing warnings diff --git a/features/storage/system_storage/SystemStorage.cpp b/features/storage/system_storage/SystemStorage.cpp index 5ce4146ef7..0277700264 100644 --- a/features/storage/system_storage/SystemStorage.cpp +++ b/features/storage/system_storage/SystemStorage.cpp @@ -22,6 +22,10 @@ #include "SPIFBlockDevice.h" #endif +#if COMPONENT_QSPIF +#include "QSPIFBlockDevice.h" +#endif + #if COMPONENT_DATAFLASH #include "DataFlashBlockDevice.h" #endif @@ -30,8 +34,22 @@ #include "SDBlockDevice.h" #endif +#if COMPONENT_FLASHIAP +#include "FlashIAPBlockDevice.h" +#endif + using namespace mbed; +// Align a value to a specified size. +// Parameters : +// val - [IN] Value. +// size - [IN] Size. +// Return : Aligned value. +static inline uint32_t align_up(uint32_t val, uint32_t size) +{ + return (((val - 1) / size) + 1) * size; +} + MBED_WEAK BlockDevice *BlockDevice::get_default_instance() { #if COMPONENT_SPIF @@ -46,6 +64,21 @@ MBED_WEAK BlockDevice *BlockDevice::get_default_instance() return &default_bd; +#elif COMPONENT_QSPIF + + static QSPIFBlockDevice default_bd( + MBED_CONF_QSPIF_QSPI_IO0, + MBED_CONF_QSPIF_QSPI_IO1, + MBED_CONF_QSPIF_QSPI_IO2, + MBED_CONF_QSPIF_QSPI_IO3, + MBED_CONF_QSPIF_QSPI_SCK, + MBED_CONF_QSPIF_QSPI_CSN, + MBED_CONF_QSPIF_QSPI_POLARITY_MODE, + MBED_CONF_QSPIF_QSPI_FREQ + ); + + return &default_bd; + #elif COMPONENT_DATAFLASH static DataFlashBlockDevice default_bd( @@ -68,6 +101,37 @@ MBED_WEAK BlockDevice *BlockDevice::get_default_instance() return &default_bd; +#elif COMPONENT_FLASHIAP + +#if (MBED_CONF_FLASHIAP_BLOCK_DEVICE_SIZE == 0) && (MBED_CONF_FLASHIAP_BLOCK_DEVICE_BASE_ADDRESS == 0xFFFFFFFF) + + size_t flash_size; + uint32_t start_address; + uint32_t bottom_address; + FlashIAP flash; + + int ret = flash.init(); + if (ret != 0) { + return 0; + } + + //Find the start of first sector after text area + bottom_address = align_up(FLASHIAP_ROM_END, flash.get_sector_size(FLASHIAP_ROM_END)); + start_address = flash.get_flash_start(); + flash_size = flash.get_flash_size(); + + ret = flash.deinit(); + + static FlashIAPBlockDevice default_bd(bottom_address, start_address + flash_size - bottom_address); + +#else + + static FlashIAPBlockDevice default_bd; + +#endif + + return &default_bd; + #else return NULL; @@ -78,7 +142,7 @@ MBED_WEAK BlockDevice *BlockDevice::get_default_instance() MBED_WEAK FileSystem *FileSystem::get_default_instance() { -#if COMPONENT_SPIF || COMPONENT_DATAFLASH +#if COMPONENT_SPIF || COMPONENT_QSPIF || COMPONENT_DATAFLASH static LittleFileSystem flash("flash", BlockDevice::get_default_instance()); flash.set_as_default(); @@ -92,6 +156,13 @@ MBED_WEAK FileSystem *FileSystem::get_default_instance() return &sdcard; +#elif COMPONENT_FLASHIAP + + static LittleFileSystem flash("flash", BlockDevice::get_default_instance()); + flash.set_as_default(); + + return &flash; + #else return NULL; diff --git a/features/unsupported/USBHost/USBHost/USBHost.cpp b/features/unsupported/USBHost/USBHost/USBHost.cpp index 704e28001c..c86196c3c2 100644 --- a/features/unsupported/USBHost/USBHost/USBHost.cpp +++ b/features/unsupported/USBHost/USBHost/USBHost.cpp @@ -171,7 +171,7 @@ void USBHost::usb_process() break; } - Thread::wait(100); + ThisThread::sleep_for(100); } USB_INFO("New device connected: %p [hub: %d - port: %d]", &devices[i], usb_msg->hub, usb_msg->port); @@ -599,7 +599,7 @@ USB_TYPE USBHost::resetDevice(USBDeviceConnected * dev) int index = findDevice(dev); if (index != -1) { USB_DBG("Resetting hub %d, port %d\n", dev->getHub(), dev->getPort()); - Thread::wait(100); + ThisThread::sleep_for(100); if (dev->getHub() == 0) { resetRootHub(); } @@ -608,7 +608,7 @@ USB_TYPE USBHost::resetDevice(USBDeviceConnected * dev) dev->getHubParent()->portReset(dev->getPort()); } #endif - Thread::wait(100); + ThisThread::sleep_for(100); deviceReset[index] = true; return USB_TYPE_OK; } @@ -974,7 +974,7 @@ USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerato } while(0); // Some devices may require this delay - Thread::wait(100); + ThisThread::sleep_for(100); return USB_TYPE_OK; } diff --git a/features/unsupported/USBHost/USBHost3GModule/WANDongleSerialPort.cpp b/features/unsupported/USBHost/USBHost3GModule/WANDongleSerialPort.cpp index 96343f15cc..cf279306aa 100644 --- a/features/unsupported/USBHost/USBHost3GModule/WANDongleSerialPort.cpp +++ b/features/unsupported/USBHost/USBHost3GModule/WANDongleSerialPort.cpp @@ -90,7 +90,7 @@ int WANDongleSerialPort::readPacket() { //lock_rx.unlock(); USB_ERR("host->bulkRead() returned %d", res); - Thread::wait(100); + ThisThread::sleep_for(100); return -1; } return 0; @@ -123,7 +123,7 @@ int WANDongleSerialPort::writePacket() { //lock_tx.unlock(); USB_ERR("host->bulkWrite() returned %d", res); - Thread::wait(100); + ThisThread::sleep_for(100); return -1; } return 0; diff --git a/features/unsupported/USBHost/USBHostHub/USBHostHub.cpp b/features/unsupported/USBHost/USBHostHub/USBHostHub.cpp index 946029039a..28e4bed22c 100644 --- a/features/unsupported/USBHost/USBHostHub/USBHostHub.cpp +++ b/features/unsupported/USBHost/USBHostHub/USBHostHub.cpp @@ -232,7 +232,7 @@ void USBHostHub::portReset(uint8_t port) USB_DBG("reset port %d on hub: %p [this: %p]", port, dev, this) setPortFeature(PORT_RESET_FEATURE, port); #if defined(TARGET_RZ_A1H) - Thread::wait(50); // Reset release waiting for Hi-Speed check. + ThisThread::sleep_for(50); // Reset release waiting for Hi-Speed check. #endif while(1) { status = getPortStatus(port); @@ -249,7 +249,7 @@ void USBHostHub::portReset(uint8_t port) host->deviceDisconnected(dev->getHub() + 1, port, this, 0); break; } - Thread::wait(10); + ThisThread::sleep_for(10); } } diff --git a/features/unsupported/USBHost/USBHostMSD/USBHostMSD.cpp b/features/unsupported/USBHost/USBHostMSD/USBHostMSD.cpp index 46250b16fd..6279f0f528 100644 --- a/features/unsupported/USBHost/USBHostMSD/USBHostMSD.cpp +++ b/features/unsupported/USBHost/USBHostMSD/USBHostMSD.cpp @@ -322,7 +322,7 @@ int USBHostMSD::init() uint16_t i, timeout = 10, ret; getMaxLun(); for (i = 0; i < timeout; i++) { - Thread::wait(100); + ThisThread::sleep_for(100); if (!testUnitReady()) break; } diff --git a/features/unsupported/USBHost/USBHostSerial/MtxCircBuffer.h b/features/unsupported/USBHost/USBHostSerial/MtxCircBuffer.h index ff79affad6..68038ac7b8 100644 --- a/features/unsupported/USBHost/USBHostSerial/MtxCircBuffer.h +++ b/features/unsupported/USBHost/USBHostSerial/MtxCircBuffer.h @@ -53,7 +53,7 @@ public: mtx.lock(); while (((write + 1) % size) == read) { mtx.unlock(); - Thread::wait(10); + ThisThread::sleep_for(10); mtx.lock(); } buf[write++] = k; diff --git a/features/unsupported/tests/rtos/cmsis/isr/main.cpp b/features/unsupported/tests/rtos/cmsis/isr/main.cpp index 41bcaaf54f..402a28144e 100644 --- a/features/unsupported/tests/rtos/cmsis/isr/main.cpp +++ b/features/unsupported/tests/rtos/cmsis/isr/main.cpp @@ -17,7 +17,7 @@ void queue_isr() { void queue_thread(void const *argument) { while (true) { queue.put((uint32_t*)1); - Thread::wait(1000); + ThisThread::sleep_for(1000); } } diff --git a/features/unsupported/tests/rtos/mbed/basic/main.cpp b/features/unsupported/tests/rtos/mbed/basic/main.cpp index abf195e9b3..f522342222 100644 --- a/features/unsupported/tests/rtos/mbed/basic/main.cpp +++ b/features/unsupported/tests/rtos/mbed/basic/main.cpp @@ -36,7 +36,7 @@ DigitalOut led2(LED2); void led2_thread(void const *argument) { while (true) { led2 = !led2; - Thread::wait(1000); + ThisThread::sleep_for(1000); print_char(); } } @@ -51,6 +51,6 @@ int main() { while (true) { led1 = !led1; - Thread::wait(500); + ThisThread::sleep_for(500); } } diff --git a/features/unsupported/tests/rtos/mbed/file/main.cpp b/features/unsupported/tests/rtos/mbed/file/main.cpp index be92ac70d3..9cd40ddecc 100644 --- a/features/unsupported/tests/rtos/mbed/file/main.cpp +++ b/features/unsupported/tests/rtos/mbed/file/main.cpp @@ -108,6 +108,6 @@ int main() { while (true) { led2 = !led2; - Thread::wait(1000); + ThisThread::sleep_for(1000); } } diff --git a/features/unsupported/tests/rtos/mbed/isr/main.cpp b/features/unsupported/tests/rtos/mbed/isr/main.cpp index 8e79bf0b4a..1c3adb772d 100644 --- a/features/unsupported/tests/rtos/mbed/isr/main.cpp +++ b/features/unsupported/tests/rtos/mbed/isr/main.cpp @@ -43,7 +43,7 @@ void queue_isr() { void queue_thread(void const *argument) { while (true) { queue.put((uint32_t*)QUEUE_PUT_THREAD_VALUE); - Thread::wait(THREAD_DELAY); + ThisThread::sleep_for(THREAD_DELAY); } } diff --git a/features/unsupported/tests/rtos/mbed/mail/main.cpp b/features/unsupported/tests/rtos/mbed/mail/main.cpp index 832360f99f..6e5fb55091 100644 --- a/features/unsupported/tests/rtos/mbed/mail/main.cpp +++ b/features/unsupported/tests/rtos/mbed/mail/main.cpp @@ -47,7 +47,7 @@ void send_thread (void const *argument) { mail->current = CREATE_CURRENT(i); mail->counter = i; mail_box.put(mail); - Thread::wait(QUEUE_PUT_DELAY); + ThisThread::sleep_for(QUEUE_PUT_DELAY); } } diff --git a/features/unsupported/tests/rtos/mbed/mutex/main.cpp b/features/unsupported/tests/rtos/mbed/mutex/main.cpp index da10822b3b..f237035512 100644 --- a/features/unsupported/tests/rtos/mbed/mutex/main.cpp +++ b/features/unsupported/tests/rtos/mbed/mutex/main.cpp @@ -66,7 +66,7 @@ bool manipulate_protected_zone(const int thread_delay) { led = !led; change_counter++; print_char('.'); - Thread::wait(thread_delay); + ThisThread::sleep_for(thread_delay); changing_counter = false; stdio_mutex.unlock(); // UNLOCK @@ -94,7 +94,7 @@ int main() { while (true) { // Thread 1 action - Thread::wait(t1_delay); + ThisThread::sleep_for(t1_delay); manipulate_protected_zone(t1_delay); if (change_counter >= SIGNALS_TO_EMIT or mutex_defect == true) { t2.terminate(); diff --git a/features/unsupported/tests/rtos/mbed/queue/main.cpp b/features/unsupported/tests/rtos/mbed/queue/main.cpp index 7075721a9b..eeb4e207cb 100644 --- a/features/unsupported/tests/rtos/mbed/queue/main.cpp +++ b/features/unsupported/tests/rtos/mbed/queue/main.cpp @@ -49,7 +49,7 @@ void send_thread (void const *argument) { message->current = CREATE_CURRENT(i); message->counter = i; queue.put(message); - Thread::wait(QUEUE_PUT_DELAY); + ThisThread::sleep_for(QUEUE_PUT_DELAY); } } diff --git a/features/unsupported/tests/rtos/mbed/semaphore/main.cpp b/features/unsupported/tests/rtos/mbed/semaphore/main.cpp index 8873534d34..d971a03778 100644 --- a/features/unsupported/tests/rtos/mbed/semaphore/main.cpp +++ b/features/unsupported/tests/rtos/mbed/semaphore/main.cpp @@ -63,7 +63,7 @@ void test_thread(void const *delay) { if (sem_lock_failed) { sem_defect = true; } - Thread::wait(thread_delay); + ThisThread::sleep_for(thread_delay); print_char('.'); sem_counter--; change_counter++; diff --git a/features/unsupported/tests/rtos/mbed/signals/main.cpp b/features/unsupported/tests/rtos/mbed/signals/main.cpp index 44cda625f8..b9b4e6a9f3 100644 --- a/features/unsupported/tests/rtos/mbed/signals/main.cpp +++ b/features/unsupported/tests/rtos/mbed/signals/main.cpp @@ -35,7 +35,7 @@ volatile int signal_counter = 0; void led_thread(void const *argument) { while (true) { // Signal flags that are reported as event are automatically cleared. - Thread::signal_wait(SIGNAL_SET_VALUE); + ThisThread::flags_wait_all(SIGNAL_SET_VALUE); led = !led; signal_counter++; } @@ -51,7 +51,7 @@ int main (void) { bool result = true; while (true) { - Thread::wait(2 * SIGNAL_HANDLE_DELEY); + ThisThread::sleep_for(2 * SIGNAL_HANDLE_DELEY); thread.signal_set(SIGNAL_SET_VALUE); if (signal_counter == SIGNALS_TO_EMIT) { printf("Handled %d signals\r\n", signal_counter); diff --git a/features/unsupported/tests/rtos/mbed/timer/main.cpp b/features/unsupported/tests/rtos/mbed/timer/main.cpp index 761bf27fed..e78cdda17f 100644 --- a/features/unsupported/tests/rtos/mbed/timer/main.cpp +++ b/features/unsupported/tests/rtos/mbed/timer/main.cpp @@ -42,5 +42,5 @@ int main(void) { led_3_timer.start(50); led_4_timer.start(25); - Thread::wait(osWaitForever); + ThisThread::sleep_for(osWaitForever); } diff --git a/features/unsupported/tests/usb/host/mass_storage/main.cpp b/features/unsupported/tests/usb/host/mass_storage/main.cpp index 2d0241bac8..fcf2001b51 100644 --- a/features/unsupported/tests/usb/host/mass_storage/main.cpp +++ b/features/unsupported/tests/usb/host/mass_storage/main.cpp @@ -17,7 +17,7 @@ void msd_task(void const *) // try to connect a MSD device while(!msd.connect()) { - Thread::wait(500); + ThisThread::sleep_for(500); } if (fs.mount(&msd) != 0) { continue; @@ -46,14 +46,14 @@ void msd_task(void const *) } else { printf("FILE == NULL\r\n"); } - Thread::wait(500); + ThisThread::sleep_for(500); printf("again\n"); // if device disconnected, try to connect again while (msd.connected()) { - Thread::wait(500); + ThisThread::sleep_for(500); } while (fs.unmount() < 0) { - Thread::wait(500); + ThisThread::sleep_for(500); printf("unmount\n"); } } @@ -65,6 +65,6 @@ int main() while(1) { led=!led; - Thread::wait(500); + ThisThread::sleep_for(500); } } diff --git a/features/unsupported/tests/usb/host/mouse/main.cpp b/features/unsupported/tests/usb/host/mouse/main.cpp index 0954ead3d6..aa0a6c60ab 100644 --- a/features/unsupported/tests/usb/host/mouse/main.cpp +++ b/features/unsupported/tests/usb/host/mouse/main.cpp @@ -14,14 +14,14 @@ void mouse_task(void const *) { while(1) { // try to connect a USB mouse while(!mouse.connect()) - Thread::wait(500); + ThisThread::sleep_for(500); // when connected, attach handler called on mouse event mouse.attachEvent(onMouseEvent); // wait until the mouse is disconnected while(mouse.connected()) - Thread::wait(500); + ThisThread::sleep_for(500); } } @@ -29,6 +29,6 @@ int main() { Thread mouseTask(mouse_task, NULL, osPriorityNormal, 256 * 4); while(1) { led=!led; - Thread::wait(500); + ThisThread::sleep_for(500); } } diff --git a/hal/LowPowerTickerWrapper.cpp b/hal/LowPowerTickerWrapper.cpp index dbeb850435..179895f7ff 100644 --- a/hal/LowPowerTickerWrapper.cpp +++ b/hal/LowPowerTickerWrapper.cpp @@ -32,15 +32,7 @@ void LowPowerTickerWrapper::irq_handler(ticker_irq_handler_type handler) { core_util_critical_section_enter(); - if (_suspended) { - if (handler) { - handler(&data); - } - core_util_critical_section_exit(); - return; - } - - if (_pending_fire_now || _match_check(_intf->read())) { + if (_pending_fire_now || _match_check(_intf->read()) || _suspended) { _timeout.detach(); _pending_timeout = false; _pending_match = false; @@ -78,6 +70,14 @@ void LowPowerTickerWrapper::resume() { core_util_critical_section_enter(); + // Wait until rescheduling is allowed + while (!_set_interrupt_allowed) { + timestamp_t current = _intf->read(); + if (((current - _last_actual_set_interrupt) & _mask) >= _min_count_between_writes) { + _set_interrupt_allowed = true; + } + } + _suspended = false; core_util_critical_section_exit(); @@ -118,7 +118,7 @@ uint32_t LowPowerTickerWrapper::read() core_util_critical_section_enter(); timestamp_t current = _intf->read(); - if (_match_check(current)) { + if (!_suspended && _match_check(current)) { _intf->fire_interrupt(); } @@ -133,7 +133,13 @@ void LowPowerTickerWrapper::set_interrupt(timestamp_t timestamp) _last_set_interrupt = _intf->read(); _cur_match_time = timestamp; _pending_match = true; - _schedule_match(_last_set_interrupt); + if (!_suspended) { + _schedule_match(_last_set_interrupt); + } else { + _intf->set_interrupt(timestamp); + _last_actual_set_interrupt = _last_set_interrupt; + _set_interrupt_allowed = false; + } core_util_critical_section_exit(); } @@ -208,13 +214,13 @@ void LowPowerTickerWrapper::_timeout_handler() timestamp_t current = _intf->read(); /* Add extra check for '_last_set_interrupt == _cur_match_time' - * + * * When '_last_set_interrupt == _cur_match_time', _ticker_match_interval_passed sees it as * one-round interval rather than just-pass, so add extra check for it. In rare cases, we * may trap in _timeout_handler/_schedule_match loop. This check can break it. */ if ((_last_set_interrupt == _cur_match_time) || - _ticker_match_interval_passed(_last_set_interrupt, current, _cur_match_time)) { + _ticker_match_interval_passed(_last_set_interrupt, current, _cur_match_time)) { _intf->fire_interrupt(); } else { _schedule_match(current); @@ -232,7 +238,7 @@ bool LowPowerTickerWrapper::_match_check(timestamp_t current) } /* Add extra check for '_last_set_interrupt == _cur_match_time' as above */ return (_last_set_interrupt == _cur_match_time) || - _ticker_match_interval_passed(_last_set_interrupt, current, _cur_match_time); + _ticker_match_interval_passed(_last_set_interrupt, current, _cur_match_time); } uint32_t LowPowerTickerWrapper::_lp_ticks_to_us(uint32_t ticks) @@ -277,7 +283,7 @@ void LowPowerTickerWrapper::_schedule_match(timestamp_t current) _intf->set_interrupt(_cur_match_time); current = _intf->read(); _last_actual_set_interrupt = current; - _set_interrupt_allowed = false; + _set_interrupt_allowed = false; // Check for overflow uint32_t new_cycles_until_match = (_cur_match_time - current) & _mask; diff --git a/hal/LowPowerTickerWrapper.h b/hal/LowPowerTickerWrapper.h index aac8d70d17..8a6a05aca0 100644 --- a/hal/LowPowerTickerWrapper.h +++ b/hal/LowPowerTickerWrapper.h @@ -74,6 +74,9 @@ public: * * This stops to wrapper layer from using the microsecond ticker. * This should be called before using the low power ticker APIs directly. + * + * @warning: Make sure to suspend the LP ticker first (call ticker_suspend()), + * otherwise the behavior is undefined. */ void suspend(); diff --git a/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c b/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c index 8fdc6443c6..b91191d9eb 100644 --- a/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c +++ b/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c @@ -260,4 +260,11 @@ MBED_NONSECURE_ENTRY uint32_t flash_get_size(const flash_t *obj) return obj->target_config->flash_size; } +MBED_NONSECURE_ENTRY uint8_t flash_get_erase_value(const flash_t *obj) +{ + (void)obj; + + return 0xFF; +} + #endif // #ifndef DOMAIN_NS diff --git a/hal/flash_api.h b/hal/flash_api.h index 4231c083ba..4b59193e45 100644 --- a/hal/flash_api.h +++ b/hal/flash_api.h @@ -117,6 +117,13 @@ uint32_t flash_get_start_address(const flash_t *obj); */ uint32_t flash_get_size(const flash_t *obj); +/** Get the flash erase value + * + * @param obj The flash object + * @return The flash erase value + */ +uint8_t flash_get_erase_value(const flash_t *obj); + /**@}*/ #ifdef __cplusplus diff --git a/hal/mbed_lp_ticker_wrapper.h b/hal/mbed_lp_ticker_wrapper.h index 4b317e36c2..e1c1fe4a26 100644 --- a/hal/mbed_lp_ticker_wrapper.h +++ b/hal/mbed_lp_ticker_wrapper.h @@ -53,6 +53,9 @@ const ticker_data_t *get_lp_ticker_wrapper_data(const ticker_data_t *data); * * Pass through all interrupts to the low power ticker and stop using * the microsecond ticker. + * + * @warning: Make sure to suspend the LP ticker first (call ticker_suspend()), + * otherwise the behavior is undefined. */ void lp_ticker_wrapper_suspend(void); diff --git a/mbed.h b/mbed.h index a1553b7d84..662f07599e 100644 --- a/mbed.h +++ b/mbed.h @@ -73,6 +73,7 @@ #include "drivers/UARTSerial.h" #include "drivers/FlashIAP.h" #include "drivers/MbedCRC.h" +#include "drivers/QSPI.h" // mbed Internal components #include "drivers/Timer.h" diff --git a/platform/ATCmdParser.cpp b/platform/ATCmdParser.cpp index 9c422b3438..0108e8bb18 100644 --- a/platform/ATCmdParser.cpp +++ b/platform/ATCmdParser.cpp @@ -21,6 +21,9 @@ #include "ATCmdParser.h" #include "mbed_poll.h" #include "mbed_debug.h" +#include +#include +#include #ifdef LF #undef LF @@ -36,6 +39,8 @@ #define CR 13 #endif +namespace mbed { + // getc/putc handling with timeouts int ATCmdParser::putc(char c) { @@ -102,7 +107,7 @@ int ATCmdParser::read(char *data, int size) // printf/scanf handling -int ATCmdParser::vprintf(const char *format, va_list args) +int ATCmdParser::vprintf(const char *format, std::va_list args) { if (vsprintf(_buffer, format, args) < 0) { @@ -118,7 +123,7 @@ int ATCmdParser::vprintf(const char *format, va_list args) return i; } -int ATCmdParser::vscanf(const char *format, va_list args) +int ATCmdParser::vscanf(const char *format, std::va_list args) { // Since format is const, we need to copy it into our buffer to // add the line's null terminator and clobber value-matches with asterisks. @@ -181,7 +186,7 @@ int ATCmdParser::vscanf(const char *format, va_list args) // Command parsing with line handling -bool ATCmdParser::vsend(const char *command, va_list args) +bool ATCmdParser::vsend(const char *command, std::va_list args) { // Create and send command if (vsprintf(_buffer, command, args) < 0) { @@ -205,12 +210,13 @@ bool ATCmdParser::vsend(const char *command, va_list args) return true; } -bool ATCmdParser::vrecv(const char *response, va_list args) +bool ATCmdParser::vrecv(const char *response, std::va_list args) { restart: _aborted = false; // Iterate through each line in the expected response - while (response[0]) { + // response being NULL means we just want to check for OOBs + while (!response || response[0]) { // Since response is const, we need to copy it into our buffer to // add the line's null terminator and clobber value-matches with asterisks. // @@ -219,7 +225,7 @@ restart: int offset = 0; bool whole_line_wanted = false; - while (response[i]) { + while (response && response[i]) { if (response[i] == '%' && response[i + 1] != '%' && response[i + 1] != '*') { _buffer[offset++] = '%'; _buffer[offset++] = '*'; @@ -252,6 +258,11 @@ restart: int j = 0; while (true) { + // If just peeking for OOBs, and at start of line, check + // readability + if (!response && j == 0 && !_fh->readable()) { + return false; + } // Receive next character int c = getc(); if (c < 0) { @@ -279,6 +290,7 @@ restart: if ((unsigned)j == oob->len && memcmp( oob->prefix, _buffer + offset, oob->len) == 0) { debug_if(_dbg_on, "AT! %s\n", oob->prefix); + _oob_cb_count++; oob->cb(); if (_aborted) { @@ -297,7 +309,7 @@ restart: // Don't attempt scanning until we get delimiter if they included it in format // This allows recv("Foo: %s\n") to work, and not match with just the first character of a string // (scanf does not itself match whitespace in its format string, so \n is not significant to it) - } else { + } else if (response) { sscanf(_buffer + offset, _buffer, &count); } @@ -331,7 +343,7 @@ restart: // Mapping to vararg functions int ATCmdParser::printf(const char *format, ...) { - va_list args; + std::va_list args; va_start(args, format); int res = vprintf(format, args); va_end(args); @@ -340,7 +352,7 @@ int ATCmdParser::printf(const char *format, ...) int ATCmdParser::scanf(const char *format, ...) { - va_list args; + std::va_list args; va_start(args, format); int res = vscanf(format, args); va_end(args); @@ -349,7 +361,7 @@ int ATCmdParser::scanf(const char *format, ...) bool ATCmdParser::send(const char *command, ...) { - va_list args; + std::va_list args; va_start(args, command); bool res = vsend(command, args); va_end(args); @@ -358,7 +370,7 @@ bool ATCmdParser::send(const char *command, ...) bool ATCmdParser::recv(const char *response, ...) { - va_list args; + std::va_list args; va_start(args, response); bool res = vrecv(response, args); va_end(args); @@ -383,52 +395,10 @@ void ATCmdParser::abort() bool ATCmdParser::process_oob() { - if (!_fh->readable()) { - return false; - } - - int i = 0; - while (true) { - // Receive next character - int c = getc(); - if (c < 0) { - return false; - } - // Simplify newlines (borrowed from retarget.cpp) - if ((c == CR && _in_prev != LF) || - (c == LF && _in_prev != CR)) { - _in_prev = c; - c = '\n'; - } else if ((c == CR && _in_prev == LF) || - (c == LF && _in_prev == CR)) { - _in_prev = c; - // onto next character - continue; - } else { - _in_prev = c; - } - _buffer[i++] = c; - _buffer[i] = 0; - - // Check for oob data - struct oob *oob = _oobs; - while (oob) { - if (i == (int)oob->len && memcmp( - oob->prefix, _buffer, oob->len) == 0) { - debug_if(_dbg_on, "AT! %s\r\n", oob->prefix); - oob->cb(); - return true; - } - oob = oob->next; - } - - // Clear the buffer when we hit a newline or ran out of space - // running out of space usually means we ran into binary data - if (((i + 1) >= _buffer_size) || (c == '\n')) { - debug_if(_dbg_on, "AT< %s", _buffer); - i = 0; - } - } + int pre_count = _oob_cb_count; + recv(NULL); + return _oob_cb_count != pre_count; } +} diff --git a/platform/ATCmdParser.h b/platform/ATCmdParser.h index 40adea9c84..0ff4fbd1c5 100644 --- a/platform/ATCmdParser.h +++ b/platform/ATCmdParser.h @@ -20,9 +20,10 @@ #ifndef MBED_ATCMDPARSER_H #define MBED_ATCMDPARSER_H -#include "mbed.h" #include #include "Callback.h" +#include "NonCopyable.h" +#include "FileHandle.h" namespace mbed { @@ -65,6 +66,7 @@ private: // Parsing information const char *_output_delimiter; int _output_delim_size; + int _oob_cb_count; char _in_prev; bool _dbg_on; bool _aborted; @@ -82,15 +84,15 @@ public: /** * Constructor * - * @param fh A FileHandle to a digital interface to use for AT commands - * @param output_delimiter end of command line termination - * @param buffer_size size of internal buffer for transaction - * @param timeout timeout of the connection - * @param debug turns on/off debug output for AT commands + * @param fh A FileHandle to the digital interface, used for AT commands + * @param output_delimiter End of command-line termination + * @param buffer_size Size of internal buffer for transaction + * @param timeout Timeout of the connection + * @param debug Turns on/off debug output for AT commands */ ATCmdParser(FileHandle *fh, const char *output_delimiter = "\r", int buffer_size = 256, int timeout = 8000, bool debug = false) - : _fh(fh), _buffer_size(buffer_size), _in_prev(0), _oobs(NULL) + : _fh(fh), _buffer_size(buffer_size), _oob_cb_count(0), _in_prev(0), _oobs(NULL) { _buffer = new char[buffer_size]; set_timeout(timeout); @@ -114,7 +116,8 @@ public: /** * Allows timeout to be changed between commands * - * @param timeout timeout of the connection + * @param timeout ATCmdParser APIs (read/write/send/recv ..etc) throw an + * error if no response is received in `timeout` duration */ void set_timeout(int timeout) { @@ -122,13 +125,15 @@ public: } /** - * For backwards compatibility. + * For backward compatibility. * @deprecated Do not use this function. This function has been replaced with set_timeout for consistency. * * Please use set_timeout(int) API only from now on. * Allows timeout to be changed between commands * - * @param timeout timeout of the connection + * @param timeout ATCmdParser APIs (read/write/send/recv ..etc) throw an + * error if no response is received in `timeout` duration + * */ MBED_DEPRECATED_SINCE("mbed-os-5.5.0", "Replaced with set_timeout for consistency") void setTimeout(int timeout) @@ -139,7 +144,7 @@ public: /** * Sets string of characters to use as line delimiters * - * @param output_delimiter string of characters to use as line delimiters + * @param output_delimiter String of characters to use as line delimiters */ void set_delimiter(const char *output_delimiter) { @@ -165,7 +170,7 @@ public: /** * Allows traces from modem to be turned on or off * - * @param on set as 1 to turn on traces and vice versa. + * @param on Set as 1 to turn on traces and vice versa. */ void debug_on(uint8_t on) { @@ -173,12 +178,12 @@ public: } /** - * For backwards compatibility. + * For backward compatibility. * @deprecated Do not use this function. This function has been replaced with debug_on for consistency. * * Allows traces from modem to be turned on or off * - * @param on set as 1 to turn on traces and vice versa. + * @param on Set as 1 to turn on traces and vice versa. */ MBED_DEPRECATED_SINCE("mbed-os-5.5.0", "Replaced with debug_on for consistency") void debugOn(uint8_t on) @@ -199,7 +204,7 @@ public: */ bool send(const char *command, ...) MBED_PRINTF_METHOD(1, 2); - bool vsend(const char *command, va_list args); + bool vsend(const char *command, std::va_list args); /** * Receive an AT response @@ -217,7 +222,7 @@ public: */ bool recv(const char *response, ...) MBED_SCANF_METHOD(1, 2); - bool vrecv(const char *response, va_list args); + bool vrecv(const char *response, std::va_list args); /** * Write a single byte to the underlying stream @@ -237,8 +242,8 @@ public: /** * Write an array of bytes to the underlying stream * - * @param data the array of bytes to write - * @param size number of bytes to write + * @param data The array of bytes to write + * @param size Number of bytes to write * @return number of bytes written or -1 on failure */ int write(const char *data, int size); @@ -246,8 +251,8 @@ public: /** * Read an array of bytes from the underlying stream * - * @param data the destination for the read bytes - * @param size number of bytes to read + * @param data The buffer for filling the read bytes + * @param size Number of bytes to read * @return number of bytes read or -1 on failure */ int read(char *data, int size); @@ -256,31 +261,31 @@ public: * Direct printf to underlying stream * @see printf * - * @param format format string to pass to printf - * @param ... arguments to printf + * @param format Format string to pass to printf + * @param ... Variable arguments to printf * @return number of bytes written or -1 on failure */ int printf(const char *format, ...) MBED_PRINTF_METHOD(1, 2); - int vprintf(const char *format, va_list args); + int vprintf(const char *format, std::va_list args); /** * Direct scanf on underlying stream * @see scanf * - * @param format format string to pass to scanf - * @param ... arguments to scanf + * @param format Format string to pass to scanf + * @param ... Variable arguments to scanf * @return number of bytes read or -1 on failure */ int scanf(const char *format, ...) MBED_SCANF_METHOD(1, 2); - int vscanf(const char *format, va_list args); + int vscanf(const char *format, std::va_list args); /** * Attach a callback for out-of-band data * - * @param prefix string on when to initiate callback - * @param func callback to call when string is read + * @param prefix String on when to initiate callback + * @param func Callback to call when string is read * @note out-of-band data is only processed during a scanf call */ void oob(const char *prefix, mbed::Callback func); @@ -293,7 +298,7 @@ public: /** * Abort current recv * - * Can be called from oob handler to interrupt the current + * Can be called from out-of-band handler to interrupt the current * recv operation. */ void abort(); @@ -304,7 +309,7 @@ public: * Process out-of-band data in the receive buffer. This function * returns immediately if there is no data to process. * - * @return true if oob data processed, false otherwise + * @return true if out-of-band data processed, false otherwise */ bool process_oob(void); }; diff --git a/platform/CThunk.h b/platform/CThunk.h index 0b4e685eaf..c3e1b3aa57 100644 --- a/platform/CThunk.h +++ b/platform/CThunk.h @@ -38,45 +38,7 @@ #ifndef __CTHUNK_H__ #define __CTHUNK_H__ -#define CTHUNK_ADDRESS 1 -#define CTHUNK_VARIABLES volatile uint32_t code[2] - -#if (defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__CORTEX_M7) || defined(__CORTEX_A9) \ - || defined(__CORTEX_M33)) -/** -* CTHUNK disassembly for Cortex-M3/M4/M7/A9 (thumb2): -* * adr r0, #4 -* * ldm r0, {r0, r1, r2, pc} -* -* This instruction loads the arguments for the static thunking function to r0-r2, and -* branches to that function by loading its address into PC. -* -* This is safe for both regular calling and interrupt calling, since it only touches scratch registers -* which should be saved by the caller, and are automatically saved as part of the IRQ context switch. -*/ -#define CTHUNK_ASSIGMENT do { \ - m_thunk.code[0] = 0xE890A001; \ - m_thunk.code[1] = 0x00008007; \ - } while (0) - -#elif (defined(__CORTEX_M0PLUS) || defined(__CORTEX_M0) || defined(__CORTEX_M23)) -/* -* CTHUNK disassembly for Cortex M0/M0+ (thumb): -* * adr r0, #4 -* * ldm r0, {r0, r1, r2, r3} -* * bx r3 -*/ -#define CTHUNK_ASSIGMENT do { \ - m_thunk.code[0] = 0xC80FA001; \ - m_thunk.code[1] = 0x00004718; \ - } while (0) - -#else -#error "Target is not currently suported." -#endif - -/* IRQ/Exception compatible thunk entry function */ -typedef void (*CThunkEntry)(void); +#include "CThunkBase.h" /** * Class for created a pointer with data bound to it @@ -84,7 +46,7 @@ typedef void (*CThunkEntry)(void); * @note Synchronization level: Not protected */ template -class CThunk { +class CThunk: public CThunkBase { public: typedef void (T::*CCallbackSimple)(void); typedef void (T::*CCallback)(void *context); @@ -101,7 +63,8 @@ public: ~CThunk() { - + cthunk_free(_entry); + _entry = NULL; } inline CThunk(T *instance, CCallbackSimple callback) @@ -126,27 +89,30 @@ public: inline void callback(CCallback callback) { - m_callback = callback; + _callback = callback; } inline void callback(CCallbackSimple callback) { - m_callback = (CCallback)callback; + _callback_simple = callback; } inline void context(void *context) { - m_thunk.context = (uint32_t)context; + _context = context; } inline void context(uint32_t context) { - m_thunk.context = context; + _context = (void*)context; } inline uint32_t entry(void) { - return (((uint32_t)&m_thunk) | CTHUNK_ADDRESS); + if (_entry == NULL) { + _entry = cthunk_alloc(this); + } + return (uint32_t)_entry; } /* get thunk entry point for connecting rhunk to an IRQ table */ @@ -168,78 +134,34 @@ public: } private: - T *m_instance; - volatile CCallback m_callback; + T *_instance; + void *_context; + union { + CCallbackSimple _callback_simple; + CCallback _callback; + }; -// TODO: this needs proper fix, to refactor toolchain header file and all its use -// PACKED there is not defined properly for IAR -#if defined (__ICCARM__) - typedef __packed struct { - CTHUNK_VARIABLES; - volatile uint32_t instance; - volatile uint32_t context; - volatile uint32_t callback; - volatile uint32_t trampoline; - } CThunkTrampoline; -#else - typedef struct { - CTHUNK_VARIABLES; - volatile uint32_t instance; - volatile uint32_t context; - volatile uint32_t callback; - volatile uint32_t trampoline; - } __attribute__((__packed__)) CThunkTrampoline; -#endif + CThunkEntry _entry; - static void trampoline(T *instance, void *context, CCallback *callback) + static void trampoline(CThunkBase *base) { - if (instance && *callback) { - (static_cast(instance)->**callback)(context); + CThunk *self = static_cast*>(base); + T *instance = self->_instance; + void *context = self->_context; + CCallback callback = self->_callback; + + if (instance && callback) { + (instance->*callback)(context); } } - volatile CThunkTrampoline m_thunk; - inline void init(T *instance, CCallback callback, void *context) { - /* remember callback - need to add this level of redirection - as pointer size for member functions differs between platforms */ - m_callback = callback; - - /* populate thunking trampoline */ - CTHUNK_ASSIGMENT; - m_thunk.context = (uint32_t)context; - m_thunk.instance = (uint32_t)instance; - m_thunk.callback = (uint32_t)&m_callback; - m_thunk.trampoline = (uint32_t)&trampoline; - -#if defined(__CORTEX_A9) - /* Data cache clean */ - /* Cache control */ - { - uint32_t start_addr = (uint32_t)&m_thunk & 0xFFFFFFE0; - uint32_t end_addr = (uint32_t)&m_thunk + sizeof(m_thunk); - uint32_t addr; - - /* Data cache clean and invalid */ - for (addr = start_addr; addr < end_addr; addr += 0x20) { - L1C_CleanInvalidateDCacheMVA((void *)addr); - } - /* Instruction cache invalid */ - L1C_InvalidateICacheAll(); - MMU_InvalidateTLB(); - L1C_InvalidateBTAC(); - } -#endif -#if defined(__CORTEX_M7) - /* Data cache clean and invalid */ - SCB_CleanInvalidateDCache(); - - /* Instruction cache invalid */ - SCB_InvalidateICache(); -#endif - __ISB(); - __DSB(); + _instance = instance; + _context = context; + _callback = callback; + _trampoline = &trampoline; + _entry = 0; } }; diff --git a/platform/CThunkBase.cpp b/platform/CThunkBase.cpp new file mode 100644 index 0000000000..c2306a922e --- /dev/null +++ b/platform/CThunkBase.cpp @@ -0,0 +1,144 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * 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. + */ + +#include "platform/platform.h" +#include "platform/mbed_critical.h" +#include "platform/mbed_assert.h" +#include "platform/mbed_error.h" + + +#include "CThunkBase.h" + +MBED_STATIC_ASSERT(MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX < 256, "MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX must be less than 256"); +MBED_STATIC_ASSERT(MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX > 0, "MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX must be greater than 0"); + +#define ENABLE_N(N) ((MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX & N) ? 1 : 0) + +#define START_128 0 +#define START_64 (START_128 + ENABLE_N(128) * 128) +#define START_32 (START_64 + ENABLE_N(64) * 64) +#define START_16 (START_32 + ENABLE_N(32) * 32) +#define START_8 (START_16 + ENABLE_N(16) * 16) +#define START_4 (START_8 + ENABLE_N(8) * 8) +#define START_2 (START_4 + ENABLE_N(4) * 4) +#define START_1 (START_2 + ENABLE_N(2) * 2) + +#define DECLARE_THUNK128(start) \ + DECLARE_THUNK64(start), \ + DECLARE_THUNK64(start + 64) +#define DECLARE_THUNK64(start) \ + DECLARE_THUNK32(start), \ + DECLARE_THUNK32(start + 32) +#define DECLARE_THUNK32(start) \ + DECLARE_THUNK16(start), \ + DECLARE_THUNK16(start + 16) +#define DECLARE_THUNK16(start) \ + DECLARE_THUNK8(start), \ + DECLARE_THUNK8(start + 8) +#define DECLARE_THUNK8(start) \ + DECLARE_THUNK4(start), \ + DECLARE_THUNK4(start + 4) +#define DECLARE_THUNK4(start) \ + DECLARE_THUNK2(start), \ + DECLARE_THUNK2(start + 2) +#define DECLARE_THUNK2(start) \ + DECLARE_THUNK1(start), \ + DECLARE_THUNK1(start + 1) +#define DECLARE_THUNK1(index) &CThunkBase::thunk_entry + +const CThunkEntry CThunkBase::_thunk_table[MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX] = { +#if ENABLE_N(128) + DECLARE_THUNK128(START_128), +#endif +#if ENABLE_N(64) + DECLARE_THUNK64(START_64), +#endif +#if ENABLE_N(32) + DECLARE_THUNK32(START_32), +#endif +#if ENABLE_N(16) + DECLARE_THUNK16(START_16), +#endif +#if ENABLE_N(8) + DECLARE_THUNK8(START_8), +#endif +#if ENABLE_N(4) + DECLARE_THUNK4(START_4), +#endif +#if ENABLE_N(2) + DECLARE_THUNK2(START_2), +#endif +#if ENABLE_N(1) + DECLARE_THUNK1(START_1) +#endif +}; + +CThunkBase *CThunkBase::_thunk_storage[MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX]; + +CThunkBase::CthunkFree CThunkBase::_cthunk_free_real = NULL; + +CThunkEntry CThunkBase::cthunk_alloc(CThunkBase *cthunk) +{ + // Atomically allocate one entry + core_util_critical_section_enter(); + CThunkEntry entry = NULL; + for (int i = 0; i < MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX; i++) { + if (_thunk_storage[i] == NULL) { + _thunk_storage[i] = cthunk; + entry = _thunk_table[i]; + break; + } + } + core_util_critical_section_exit(); + + if (entry == NULL) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_RESOURCES), "Ran out of CThunk entries. Increase MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX to fix this error"); + } + + // Set function pointer on first use. This allows _thunk_table + // and _thunk_storage to get removed by the linker if + // cthunk_alloc is never used. + _cthunk_free_real = &cthunk_free_real; + + return entry; +} + +void CThunkBase::cthunk_free(CThunkEntry item) +{ + if (_cthunk_free_real) { + _cthunk_free_real(item); + } +} + +void CThunkBase::cthunk_free_real(CThunkEntry item) +{ + bool found = false; + + core_util_critical_section_enter(); + for (int i = 0; i < MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX; i++) { + if (_thunk_table[i] == item) { + _thunk_storage[i] = NULL; + found = true; + break; + } + } + core_util_critical_section_exit(); + + if (!found) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_ARGUMENT), "Tried to free invalid CThunkEntry"); + } + +} diff --git a/platform/CThunkBase.h b/platform/CThunkBase.h new file mode 100644 index 0000000000..4504dea092 --- /dev/null +++ b/platform/CThunkBase.h @@ -0,0 +1,77 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * 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. + */ + +#ifndef __CTHUNK_BASE_H__ +#define __CTHUNK_BASE_H__ + +/* IRQ/Exception compatible thunk entry function */ +typedef void (*CThunkEntry)(void); + +class CThunkBase { +protected: + typedef void (*Trampoline)(CThunkBase*); + + Trampoline _trampoline; + + /* + * Allocate a CThunkEntry which can be called without arguments + * + * Calling the CThunkEntry invokes the _trampoline of the + * given cthunk. This function traps if there are no more + * free thunks. + */ + static CThunkEntry cthunk_alloc(CThunkBase *cthunk); + + /* + * Free a cthunk_entry so it can be reused + */ + static void cthunk_free(CThunkEntry cthunk_entry); + +private: + typedef void (*CthunkFree)(CThunkEntry cthunk_entry); + + /* + * Table of thunk functions + */ + static const CThunkEntry _thunk_table[MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX]; + + /* + * Table of active CThunk classes + */ + static CThunkBase *_thunk_storage[MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX]; + + /* + * Lazily initialized free function pointer + */ + static CthunkFree _cthunk_free_real; + + /* + * Actual free function + */ + static void cthunk_free_real(CThunkEntry cthunk_entry); + + /* + * Template function which stored in the _thunk_table + */ + template + static void thunk_entry() + { + _thunk_storage[N]->_trampoline(_thunk_storage[N]); + } +}; + +#endif/*__CTHUNK_BASE_H__*/ + diff --git a/platform/CallChain.h b/platform/CallChain.h index 85682102d3..3fe17231b0 100644 --- a/platform/CallChain.h +++ b/platform/CallChain.h @@ -147,7 +147,7 @@ public: * @param method pointer to the member function to be called * * @returns - * The function object created for 'tptr' and 'mptr' + * The function object created for the object and method pointers * * @deprecated * The add_front function does not support cv-qualifiers. Replaced by diff --git a/platform/Callback.h b/platform/Callback.h index bf3d66114b..1a6b6751bc 100644 --- a/platform/Callback.h +++ b/platform/Callback.h @@ -601,7 +601,7 @@ public: /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer * @return the value as determined by func which is of - * type and determined by the signiture of func + * type and determined by the signature of func */ static R thunk(void *func) { @@ -1226,7 +1226,7 @@ public: * @param func Callback to call passed as void pointer * @param a0 An argument to be called with function func * @return the value as determined by func which is of - * type and determined by the signiture of func + * type and determined by the signature of func */ static R thunk(void *func, A0 a0) { @@ -1852,7 +1852,7 @@ public: * @param a0 An argument to be called with function func * @param a1 An argument to be called with function func * @return the value as determined by func which is of - * type and determined by the signiture of func + * type and determined by the signature of func */ static R thunk(void *func, A0 a0, A1 a1) { @@ -2479,7 +2479,7 @@ public: * @param a1 An argument to be called with function func * @param a2 An argument to be called with function func * @return the value as determined by func which is of - * type and determined by the signiture of func + * type and determined by the signature of func */ static R thunk(void *func, A0 a0, A1 a1, A2 a2) { @@ -3107,7 +3107,7 @@ public: * @param a2 An argument to be called with function func * @param a3 An argument to be called with function func * @return the value as determined by func which is of - * type and determined by the signiture of func + * type and determined by the signature of func */ static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) { @@ -3736,7 +3736,7 @@ public: * @param a3 An argument to be called with function func * @param a4 An argument to be called with function func * @return the value as determined by func which is of - * type and determined by the signiture of func + * type and determined by the signature of func */ static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { @@ -3832,10 +3832,10 @@ private: typedef Callback event_callback_t; -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)() = 0) @@ -3843,10 +3843,10 @@ Callback callback(R(*func)() = 0) return Callback(func); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const Callback &func) @@ -3854,11 +3854,11 @@ Callback callback(const Callback &func) return Callback(func); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(U *obj, R(T::*method)()) @@ -3866,11 +3866,11 @@ Callback callback(U *obj, R(T::*method)()) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const U *obj, R(T::*method)() const) @@ -3878,11 +3878,11 @@ Callback callback(const U *obj, R(T::*method)() const) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(volatile U *obj, R(T::*method)() volatile) @@ -3890,11 +3890,11 @@ Callback callback(volatile U *obj, R(T::*method)() volatile) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const volatile U *obj, R(T::*method)() const volatile) @@ -3902,11 +3902,11 @@ Callback callback(const volatile U *obj, R(T::*method)() const volatile) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(T *), U *arg) @@ -3914,11 +3914,11 @@ Callback callback(R(*func)(T *), U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(const T *), const U *arg) @@ -3926,11 +3926,11 @@ Callback callback(R(*func)(const T *), const U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(volatile T *), volatile U *arg) @@ -3938,11 +3938,11 @@ Callback callback(R(*func)(volatile T *), volatile U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(const volatile T *), const volatile U *arg) @@ -3950,11 +3950,11 @@ Callback callback(R(*func)(const volatile T *), const volatile U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -3966,11 +3966,11 @@ Callback callback(U *obj, R(*func)(T *)) return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -3982,11 +3982,11 @@ Callback callback(const U *obj, R(*func)(const T *)) return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -3998,11 +3998,11 @@ Callback callback(volatile U *obj, R(*func)(volatile T *)) return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4015,10 +4015,10 @@ Callback callback(const volatile U *obj, R(*func)(const volatile T *)) } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(A0) = 0) @@ -4026,10 +4026,10 @@ Callback callback(R(*func)(A0) = 0) return Callback(func); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const Callback &func) @@ -4037,11 +4037,11 @@ Callback callback(const Callback &func) return Callback(func); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(U *obj, R(T::*method)(A0)) @@ -4049,11 +4049,11 @@ Callback callback(U *obj, R(T::*method)(A0)) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const U *obj, R(T::*method)(A0) const) @@ -4061,11 +4061,11 @@ Callback callback(const U *obj, R(T::*method)(A0) const) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(volatile U *obj, R(T::*method)(A0) volatile) @@ -4073,11 +4073,11 @@ Callback callback(volatile U *obj, R(T::*method)(A0) volatile) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const volatile U *obj, R(T::*method)(A0) const volatile) @@ -4085,11 +4085,11 @@ Callback callback(const volatile U *obj, R(T::*method)(A0) const volatile return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(T *, A0), U *arg) @@ -4097,11 +4097,11 @@ Callback callback(R(*func)(T *, A0), U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(const T *, A0), const U *arg) @@ -4109,11 +4109,11 @@ Callback callback(R(*func)(const T *, A0), const U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(volatile T *, A0), volatile U *arg) @@ -4121,11 +4121,11 @@ Callback callback(R(*func)(volatile T *, A0), volatile U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(const volatile T *, A0), const volatile U *arg) @@ -4133,11 +4133,11 @@ Callback callback(R(*func)(const volatile T *, A0), const volatile U *arg return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4149,11 +4149,11 @@ Callback callback(U *obj, R(*func)(T *, A0)) return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4165,11 +4165,11 @@ Callback callback(const U *obj, R(*func)(const T *, A0)) return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4181,11 +4181,11 @@ Callback callback(volatile U *obj, R(*func)(volatile T *, A0)) return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4198,10 +4198,10 @@ Callback callback(const volatile U *obj, R(*func)(const volatile T *, A0) } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(A0, A1) = 0) @@ -4209,10 +4209,10 @@ Callback callback(R(*func)(A0, A1) = 0) return Callback(func); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const Callback &func) @@ -4220,11 +4220,11 @@ Callback callback(const Callback &func) return Callback(func); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(U *obj, R(T::*method)(A0, A1)) @@ -4232,11 +4232,11 @@ Callback callback(U *obj, R(T::*method)(A0, A1)) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const U *obj, R(T::*method)(A0, A1) const) @@ -4244,11 +4244,11 @@ Callback callback(const U *obj, R(T::*method)(A0, A1) const) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(volatile U *obj, R(T::*method)(A0, A1) volatile) @@ -4256,11 +4256,11 @@ Callback callback(volatile U *obj, R(T::*method)(A0, A1) volatile) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const volatile U *obj, R(T::*method)(A0, A1) const volatile) @@ -4268,11 +4268,11 @@ Callback callback(const volatile U *obj, R(T::*method)(A0, A1) const return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(T *, A0, A1), U *arg) @@ -4280,11 +4280,11 @@ Callback callback(R(*func)(T *, A0, A1), U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(const T *, A0, A1), const U *arg) @@ -4292,11 +4292,11 @@ Callback callback(R(*func)(const T *, A0, A1), const U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(volatile T *, A0, A1), volatile U *arg) @@ -4304,11 +4304,11 @@ Callback callback(R(*func)(volatile T *, A0, A1), volatile U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(const volatile T *, A0, A1), const volatile U *arg) @@ -4316,11 +4316,11 @@ Callback callback(R(*func)(const volatile T *, A0, A1), const volatil return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4332,11 +4332,11 @@ Callback callback(U *obj, R(*func)(T *, A0, A1)) return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4348,11 +4348,11 @@ Callback callback(const U *obj, R(*func)(const T *, A0, A1)) return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4364,11 +4364,11 @@ Callback callback(volatile U *obj, R(*func)(volatile T *, A0, A1)) return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4381,10 +4381,10 @@ Callback callback(const volatile U *obj, R(*func)(const volatile T *, } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(A0, A1, A2) = 0) @@ -4392,10 +4392,10 @@ Callback callback(R(*func)(A0, A1, A2) = 0) return Callback(func); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const Callback &func) @@ -4403,11 +4403,11 @@ Callback callback(const Callback &func) return Callback(func); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(U *obj, R(T::*method)(A0, A1, A2)) @@ -4415,11 +4415,11 @@ Callback callback(U *obj, R(T::*method)(A0, A1, A2)) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const U *obj, R(T::*method)(A0, A1, A2) const) @@ -4427,11 +4427,11 @@ Callback callback(const U *obj, R(T::*method)(A0, A1, A2) const) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(volatile U *obj, R(T::*method)(A0, A1, A2) volatile) @@ -4439,11 +4439,11 @@ Callback callback(volatile U *obj, R(T::*method)(A0, A1, A2) vola return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const volatile U *obj, R(T::*method)(A0, A1, A2) const volatile) @@ -4451,11 +4451,11 @@ Callback callback(const volatile U *obj, R(T::*method)(A0, A1, A2 return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(T *, A0, A1, A2), U *arg) @@ -4463,11 +4463,11 @@ Callback callback(R(*func)(T *, A0, A1, A2), U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(const T *, A0, A1, A2), const U *arg) @@ -4475,11 +4475,11 @@ Callback callback(R(*func)(const T *, A0, A1, A2), const U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(volatile T *, A0, A1, A2), volatile U *arg) @@ -4487,11 +4487,11 @@ Callback callback(R(*func)(volatile T *, A0, A1, A2), volatile U return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(const volatile T *, A0, A1, A2), const volatile U *arg) @@ -4499,11 +4499,11 @@ Callback callback(R(*func)(const volatile T *, A0, A1, A2), const return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4515,11 +4515,11 @@ Callback callback(U *obj, R(*func)(T *, A0, A1, A2)) return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4531,11 +4531,11 @@ Callback callback(const U *obj, R(*func)(const T *, A0, A1, A2)) return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4547,11 +4547,11 @@ Callback callback(volatile U *obj, R(*func)(volatile T *, A0, A1, return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4564,10 +4564,10 @@ Callback callback(const volatile U *obj, R(*func)(const volatile } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(A0, A1, A2, A3) = 0) @@ -4575,10 +4575,10 @@ Callback callback(R(*func)(A0, A1, A2, A3) = 0) return Callback(func); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const Callback &func) @@ -4586,11 +4586,11 @@ Callback callback(const Callback &func) return Callback(func); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(U *obj, R(T::*method)(A0, A1, A2, A3)) @@ -4598,11 +4598,11 @@ Callback callback(U *obj, R(T::*method)(A0, A1, A2, A3)) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const U *obj, R(T::*method)(A0, A1, A2, A3) const) @@ -4610,11 +4610,11 @@ Callback callback(const U *obj, R(T::*method)(A0, A1, A2, A3) return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(volatile U *obj, R(T::*method)(A0, A1, A2, A3) volatile) @@ -4622,11 +4622,11 @@ Callback callback(volatile U *obj, R(T::*method)(A0, A1, A2, return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const volatile U *obj, R(T::*method)(A0, A1, A2, A3) const volatile) @@ -4634,11 +4634,11 @@ Callback callback(const volatile U *obj, R(T::*method)(A0, A1 return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(T *, A0, A1, A2, A3), U *arg) @@ -4646,11 +4646,11 @@ Callback callback(R(*func)(T *, A0, A1, A2, A3), U *arg) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(const T *, A0, A1, A2, A3), const U *arg) @@ -4658,11 +4658,11 @@ Callback callback(R(*func)(const T *, A0, A1, A2, A3), const return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(volatile T *, A0, A1, A2, A3), volatile U *arg) @@ -4670,11 +4670,11 @@ Callback callback(R(*func)(volatile T *, A0, A1, A2, A3), vol return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(const volatile T *, A0, A1, A2, A3), const volatile U *arg) @@ -4682,11 +4682,11 @@ Callback callback(R(*func)(const volatile T *, A0, A1, A2, A3 return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4698,11 +4698,11 @@ Callback callback(U *obj, R(*func)(T *, A0, A1, A2, A3)) return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4714,11 +4714,11 @@ Callback callback(const U *obj, R(*func)(const T *, A0, A1, A return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4730,11 +4730,11 @@ Callback callback(volatile U *obj, R(*func)(volatile T *, A0, return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4747,10 +4747,10 @@ Callback callback(const volatile U *obj, R(*func)(const volat } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(A0, A1, A2, A3, A4) = 0) @@ -4758,10 +4758,10 @@ Callback callback(R(*func)(A0, A1, A2, A3, A4) = 0) return Callback(func); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const Callback &func) @@ -4769,11 +4769,11 @@ Callback callback(const Callback & return Callback(func); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(U *obj, R(T::*method)(A0, A1, A2, A3, A4)) @@ -4781,11 +4781,11 @@ Callback callback(U *obj, R(T::*method)(A0, A1, A2, A3, A return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const U *obj, R(T::*method)(A0, A1, A2, A3, A4) const) @@ -4793,11 +4793,11 @@ Callback callback(const U *obj, R(T::*method)(A0, A1, A2, return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) volatile) @@ -4805,11 +4805,11 @@ Callback callback(volatile U *obj, R(T::*method)(A0, A1, return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(const volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) const volatile) @@ -4817,11 +4817,11 @@ Callback callback(const volatile U *obj, R(T::*method)(A0 return Callback(obj, method); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(T *, A0, A1, A2, A3, A4), U *arg) @@ -4829,11 +4829,11 @@ Callback callback(R(*func)(T *, A0, A1, A2, A3, A4), U *a return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(const T *, A0, A1, A2, A3, A4), const U *arg) @@ -4841,11 +4841,11 @@ Callback callback(R(*func)(const T *, A0, A1, A2, A3, A4) return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(volatile T *, A0, A1, A2, A3, A4), volatile U *arg) @@ -4853,11 +4853,11 @@ Callback callback(R(*func)(volatile T *, A0, A1, A2, A3, return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param func Static function to attach * @param arg Pointer argument to function - * @return Callback with infered type + * @return Callback with inferred type */ template Callback callback(R(*func)(const volatile T *, A0, A1, A2, A3, A4), const volatile U *arg) @@ -4865,11 +4865,11 @@ Callback callback(R(*func)(const volatile T *, A0, A1, A2 return Callback(func, arg); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4881,11 +4881,11 @@ Callback callback(U *obj, R(*func)(T *, A0, A1, A2, A3, A return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4897,11 +4897,11 @@ Callback callback(const U *obj, R(*func)(const T *, A0, A return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ @@ -4913,11 +4913,11 @@ Callback callback(volatile U *obj, R(*func)(volatile T *, return Callback(func, obj); } -/** Create a callback class with type infered from the arguments +/** Create a callback class with type inferred from the arguments * * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with infered type + * @return Callback with inferred type * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ diff --git a/platform/CircularBuffer.h b/platform/CircularBuffer.h index d6db5e6eb9..2eb5fd5a04 100644 --- a/platform/CircularBuffer.h +++ b/platform/CircularBuffer.h @@ -98,7 +98,7 @@ public: } _pool[_head++] = data; if (_head == BufferSize) { - _head = 0; + _head = 0; } if (_head == _tail) { _full = true; diff --git a/platform/DirHandle.h b/platform/DirHandle.h index d0b04d04f2..d40300e360 100644 --- a/platform/DirHandle.h +++ b/platform/DirHandle.h @@ -30,18 +30,24 @@ namespace mbed { */ -/** Represents a directory stream. Objects of this type are returned - * by an opendir function. The core functions are read and seek, +/** Represents a directory stream. An opendir function returns + * objects of this type. The core functions are read and seek, * but only a subset needs to be provided. * - * If a FileSystemLike class defines the opendir method, then the - * directories of an object of that type can be accessed by - * DIR *d = opendir("/example/directory") (or opendir("/example") - * to open the root of the filesystem), and then using readdir(d) etc. + * If a FileSystemLike class defines the opendir method, then you + * can access the directories of an object of that type by either: + * @code + * DIR *d = opendir("/example/directory"); + * @endcode + * or + * @code + * DIR *d = opendir("/example"); + * @endcode + * to open the root of the file system. * * The root directory is considered to contain all FileHandle and - * FileSystem objects, so the DIR* returned by opendir("/") will - * reflect this. + * FileSystem objects, so the DIR pointer returned by opendir("/") + * reflects this. * * @note to create a directory, @see Dir * @note Synchronization level: Set by subclass @@ -113,7 +119,7 @@ public: return close(); }; - /** Return the directory entry at the current position, and + /** Returns the directory entry at the current position, and * advances the position to the next entry. * * @returns diff --git a/platform/FileBase.cpp b/platform/FileBase.cpp index 1c8c35a3fb..5ee1a98c0d 100644 --- a/platform/FileBase.cpp +++ b/platform/FileBase.cpp @@ -63,7 +63,7 @@ FileBase::~FileBase() _mutex->unlock(); if (getPathType() == FilePathType) { - extern void remove_filehandle(FileHandle *file); + extern void remove_filehandle(FileHandle * file); remove_filehandle(static_cast(this)); } } @@ -88,6 +88,7 @@ FileBase *FileBase::lookup(const char *name, unsigned int len) p = p->_next; } if (len == (sizeof "default") - 1 && std::memcmp("default", name, len) == 0) { + _mutex->unlock(); return _default; } _mutex->unlock(); diff --git a/platform/FileHandle.h b/platform/FileHandle.h index 03b6399a66..c9aea35833 100644 --- a/platform/FileHandle.h +++ b/platform/FileHandle.h @@ -36,7 +36,7 @@ namespace mbed { /** Class FileHandle * * An abstract interface that represents operations on a file-like - * object. The core functions are read, write, and seek, but only + * object. The core functions are read, write and seek, but only * a subset of these operations can be provided. * * @note to create a file, @see File @@ -50,7 +50,7 @@ public: * * Devices acting as FileHandles should follow POSIX semantics: * - * * if no data is available, and non-blocking set return -EAGAIN + * * if no data is available, and nonblocking set, return -EAGAIN * * if no data is available, and blocking set, wait until some data is available * * If any data is available, call returns immediately * @@ -65,8 +65,8 @@ public: * Devices acting as FileHandles should follow POSIX semantics: * * * if blocking, block until all data is written - * * if no data can be written, and non-blocking set, return -EAGAIN - * * if some data can be written, and non-blocking set, write partial + * * if no data can be written, and nonblocking set, return -EAGAIN + * * if some data can be written, and nonblocking set, write partial * * @param buffer The buffer to write from * @param size The number of bytes to write @@ -181,11 +181,11 @@ public: return size(); } - /** Set blocking or non-blocking mode of the file operation like read/write. - * Definition depends upon the subclass implementing FileHandle. + /** Set blocking or nonblocking mode of the file operation like read/write. + * Definition depends on the subclass implementing FileHandle. * The default is blocking. * - * @param blocking true for blocking mode, false for non-blocking mode. + * @param blocking true for blocking mode, false for nonblocking mode. * * @return 0 on success * @return Negative error code on failure @@ -195,9 +195,9 @@ public: return blocking ? 0 : -ENOTTY; } - /** Check current blocking or non-blocking mode for file operations. + /** Check current blocking or nonblocking mode for file operations. * - * @return true for blocking mode, false for non-blocking mode. + * @return true for blocking mode, false for nonblocking mode. */ virtual bool is_blocking() const { @@ -205,9 +205,9 @@ public: } /** Check for poll event flags - * The input parameter can be used or ignored - the could always return all events, - * or could check just the events listed in events. - * Call is non-blocking - returns instantaneous state of events. + * You can use or ignore the input parameter. You can return all events + * or check just the events listed in events. + * Call is nonblocking - returns instantaneous state of events. * Whenever an event occurs, the derived class should call the sigio() callback). * * @param events bitmask of poll events we're interested in - POLLIN/POLLOUT etc. @@ -220,7 +220,7 @@ public: return POLLIN | POLLOUT; } - /** Definition depends upon the subclass implementing FileHandle. + /** Definition depends on the subclass implementing FileHandle. * For example, if the FileHandle is of type Stream, writable() could return * true when there is ample buffer space available for write() calls. * @@ -231,7 +231,7 @@ public: return poll(POLLOUT) & POLLOUT; } - /** Definition depends upon the subclass implementing FileHandle. + /** Definition depends on the subclass implementing FileHandle. * For example, if the FileHandle is of type Stream, readable() could return * true when there is something available to read. * @@ -250,11 +250,11 @@ public: * The callback may be called in an interrupt context and should not * perform expensive operations. * - * Note! This is not intended as an attach-like asynchronous api, but rather - * as a building block for constructing such functionality. + * Note! This is not intended as an attach-like asynchronous API, but rather + * as a building block for constructing such functionality. * * The exact timing of when the registered function - * is called is not guaranteed and susceptible to change. It should be used + * is called is not guaranteed and is susceptible to change. It should be used * as a cue to make read/write/poll calls to find the current state. * * @param func Function to call on state change diff --git a/platform/FileSystemHandle.cpp b/platform/FileSystemHandle.cpp index 1823f8a43b..e0702bdb39 100644 --- a/platform/FileSystemHandle.cpp +++ b/platform/FileSystemHandle.cpp @@ -14,10 +14,10 @@ * limitations under the License. */ -#include "mbed.h" #include "FileSystemHandle.h" #include +namespace mbed { int FileSystemHandle::open(DirHandle **dir, const char *path) { return -ENOSYS; @@ -47,3 +47,4 @@ int FileSystemHandle::statvfs(const char *path, struct statvfs *buf) { return -ENOSYS; } +} diff --git a/platform/NonCopyable.h b/platform/NonCopyable.h index 90fce492fb..d368ae23ae 100644 --- a/platform/NonCopyable.h +++ b/platform/NonCopyable.h @@ -23,91 +23,106 @@ namespace mbed { +/** \addtogroup platform */ +/** @{*/ /** - * Inheriting from this class autogeneration of copy construction and copy - * assignment operations. - * - * Classes which are not value type should inherit privately from this class - * to avoid generation of invalid copy constructor or copy assignment operator - * which can lead to unnoticeable programming errors. - * - * As an example consider the following signature: - * + * \defgroup platform_NonCopyable NonCopyable class + * @{ + */ + +/** + * Prevents generation of copy constructor and copy assignment operator in + * derived classes. + * + * @par Usage + * + * To prevent generation of copy constructor and copy assignment operator, + * inherit privately from the NonCopyable class. + * + * @code + * class Resource : NonCopyable { }; + * + * Resource r; + * // generates compile time error: + * Resource r2 = r; + * @endcode + * + * @par Background information + * + * Instances of polymorphic classes are not meant to be copied. The + * C++ standards generate a default copy constructor and copy assignment + * function if these functions have not been defined in the class. + * + * Consider the following example: + * * @code - * class Resource; - * - * class Foo { + * // base class representing a connection + * struct Connection { + * Connection(); + * virtual ~Connection(); + * virtual void open() = 0; + * } + * + * class SerialConnection : public Connection { * public: - * Foo() : _resource(new Resource()) { } - * ~Foo() { delete _resource; } + * SerialConnection(Serial*); + * * private: - * Resource* _resource; + * Serial* _serial; + * }; + * + * Connection& get_connection() { + * static SerialConnection serial_connection; + * return serial_connection; * } * - * Foo get_foo(); - * - * Foo foo = get_foo(); + * Connection connection = get_connection(); * @endcode - * - * There is a bug in this function, it returns a temporary value which will be - * byte copied into foo then destroyed. Unfortunately, internally the Foo class - * manage a pointer to a Resource object. This pointer will be released when the - * temporary is destroyed and foo will manage a pointer to an already released - * Resource. - * - * Two issues has to be fixed in the example above: - * - Function signature has to be changed to reflect the fact that Foo - * instances cannot be copied. In that case accessor should return a - * reference to give access to objects already existing and managed. - * Generator on the other hand should return a pointer to the created object. - * + * + * There is a subtle bug in this code, the function get_connection returns a + * reference to a Connection which is captured by value instead of reference. + * + * When `get_connection` returns a reference to serial_connection it is copied into + * the local variable connection. The vtable and others members defined in Connection + * are copied, but members defined in SerialConnection are left apart. This can cause + * severe crashes or bugs if the virtual functions captured use members not present + * in the base declaration. + * + * To solve that problem, the copy constructor and assignment operator have to + * be declared (but don't need to be defined) in the private section of the + * Connection class: + * * @code - * // return a reference to an already managed Foo instance - * Foo& get_foo(); - * Foo& foo = get_foo(); - * - * // create a new Foo instance - * Foo* make_foo(); - * Foo* m = make_foo(); - * @endcode - * - * - Copy constructor and copy assignment operator has to be made private - * in the Foo class. It prevents unwanted copy of Foo objects. This can be - * done by declaring copy constructor and copy assignment in the private - * section of the Foo class. - * - * @code - * class Foo { - * public: - * Foo() : _resource(new Resource()) { } - * ~Foo() { delete _resource; } + * struct Connection { * private: - * // disallow copy operations - * Foo(const Foo&); - * Foo& operator=(const Foo&); - * // data members - * Resource* _resource; + * Connection(const Connection&); + * Connection& operator=(const Connection&); * } * @endcode - * - * Another solution is to inherit privately from the NonCopyable class. - * It reduces the boiler plate needed to avoid copy operations but more - * importantly it clarifies the programmer intent and the object semantic. - * - * class Foo : private NonCopyable { - * public: - * Foo() : _resource(new Resource()) { } - * ~Foo() { delete _resource; } - * private: - * Resource* _resource; + * + * Although manually declaring private copy constructor and assignment functions + * works, it is not ideal. These declarations are usually easy to forget, + * not immediately visible, and may be obscure to uninformed programmers. + * + * Using the NonCopyable class reduces the boilerplate required and expresses + * the intent because class inheritance appears right after the class name + * declaration. + * + * @code + * struct Connection : private NonCopyable { + * // regular declarations * } - * - * @tparam T The type that should be made non copyable. It prevent cases where - * the empty base optimization cannot be applied and therefore ensure that the - * cost of this semantic sugar is null. - * + * @endcode + * + * + * @par Implementation details + * + * Using a template type prevents cases where the empty base optimization cannot + * be applied and therefore ensures that the cost of the NonCopyable semantic + * sugar is null. + * * As an example, the empty base optimization is prohibited if one of the empty - * base class is also a base type of the first non static data member: + * base classes is also a base type of the first nonstatic data member: * * @code * struct A { }; @@ -121,11 +136,11 @@ namespace mbed { * }; * * // empty base optimization cannot be applied here because A from C and A from - * // B shall have a different address. In that case, with the alignment + * // B have a different address. In that case, with the alignment * // sizeof(C) == 2* sizeof(int) * @endcode * - * The solution to that problem is to templatize the empty class to makes it + * The solution to that problem is to templatize the empty class to make it * unique to the type it is applied to: * * @code @@ -142,12 +157,15 @@ namespace mbed { * // kind of A. sizeof(C) == sizeof(B) == sizeof(int). * @endcode * - * @note Compile time errors are disabled if the develop or the release profile - * is used. To override this behavior and force compile time errors in all profile + * @tparam T The type that should be made noncopyable. + * + * @note Compile time errors are disabled if you use the develop or release profile. + * To override this behavior and force compile time errors in all profiles, * set the configuration parameter "platform.force-non-copyable-error" to true. */ template class NonCopyable { +#ifndef DOXYGEN_ONLY protected: /** * Disallow construction of NonCopyable objects from outside of its hierarchy. @@ -162,11 +180,11 @@ protected: /** * NonCopyable copy constructor. * - * A compile time warning is issued when this function is used and a runtime - * warning is printed when the copy construction of the non copyable happens. + * A compile time warning is issued when this function is used, and a runtime + * warning is printed when the copy construction of the noncopyable happens. * * If you see this warning, your code is probably doing something unspecified. - * Copy of non copyable resources can lead to resource leak and random error. + * Copying of noncopyable resources can lead to resource leak and random error. */ MBED_DEPRECATED("Invalid copy construction of a NonCopyable resource.") NonCopyable(const NonCopyable &) @@ -177,11 +195,11 @@ protected: /** * NonCopyable copy assignment operator. * - * A compile time warning is issued when this function is used and a runtime - * warning is printed when the copy construction of the non copyable happens. + * A compile time warning is issued when this function is used, and a runtime + * warning is printed when the copy construction of the noncopyable happens. * * If you see this warning, your code is probably doing something unspecified. - * Copy of non copyable resources can lead to resource leak and random error. + * Copying of noncopyable resources can lead to resource leak and random error. */ MBED_DEPRECATED("Invalid copy assignment of a NonCopyable resource.") NonCopyable &operator=(const NonCopyable &) @@ -193,19 +211,24 @@ protected: #else private: /** - * Declare copy constructor as private, any attempt to copy construct + * Declare copy constructor as private. Any attempt to copy construct * a NonCopyable will fail at compile time. */ NonCopyable(const NonCopyable &); /** - * Declare copy assignment operator as private, any attempt to copy assign + * Declare copy assignment operator as private. Any attempt to copy assign * a NonCopyable will fail at compile time. */ NonCopyable &operator=(const NonCopyable &); #endif +#endif }; +/**@}*/ + +/**@}*/ + } // namespace mbed #endif /* MBED_NONCOPYABLE_H_ */ diff --git a/platform/PlatformMutex.h b/platform/PlatformMutex.h index 855d098aee..ac06a81855 100644 --- a/platform/PlatformMutex.h +++ b/platform/PlatformMutex.h @@ -1,10 +1,3 @@ - -/** \addtogroup platform */ -/** @{*/ -/** - * \defgroup platform_PlatformMutex PlatformMutex class - * @{ - */ /* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * @@ -25,32 +18,67 @@ #include "platform/NonCopyable.h" +/** \addtogroup platform + * @{ + */ + +/** \defgroup platform_PlatformMutex PlatformMutex class + * @{ + */ + +/** The PlatformMutex class is used to synchronize the execution of threads. + * + * Mbed drivers use the PlatformMutex class instead of rtos::Mutex. + * This enables the use of drivers when the Mbed OS is compiled without the RTOS. + * + * @note + * - When the RTOS is present, the PlatformMutex becomes a typedef for rtos::Mutex. + * - When the RTOS is absent, all methods are defined as noop. + */ + #ifdef MBED_CONF_RTOS_PRESENT + #include "rtos/Mutex.h" typedef rtos::Mutex PlatformMutex; + #else -/** A stub mutex for when an RTOS is not present -*/ -class PlatformMutex : private mbed::NonCopyable { + +class PlatformMutex: private mbed::NonCopyable { public: + /** Create a PlatformMutex object. + * + * @note When the RTOS is present, this is an alias for rtos::Mutex::Mutex(). + */ PlatformMutex() { - // Stub - } + + /** PlatformMutex destructor. + * + * @note When the RTOS is present, this is an alias for rtos::Mutex::~Mutex(). + */ ~PlatformMutex() { - // Stub } + /** Wait until a PlatformMutex becomes available. + * + * @note + * - When the RTOS is present, this is an alias for rtos::Mutex::lock(). + * - When the RTOS is absent, this is a noop. + */ void lock() { - // Do nothing } + /** Unlock a PlatformMutex that the same thread has previously locked. + * + * @note + * - When the RTOS is present, this is an alias for rtos::Mutex::unlock(). + * - When the RTOS is absent, this is a noop. + */ void unlock() { - // Do nothing } }; diff --git a/platform/ScopedLock.h b/platform/ScopedLock.h index 8f79fbf7dd..8e9018c178 100644 --- a/platform/ScopedLock.h +++ b/platform/ScopedLock.h @@ -60,7 +60,7 @@ namespace mbed { template class ScopedLock : private NonCopyable > { public: - /** Locks given locable object + /** Locks given lockable object * * @param lockable reference to the instance of Lockable object * @note lockable object should outlive the ScopedLock object diff --git a/platform/SharedPtr.h b/platform/SharedPtr.h index d6bbac8138..d273507255 100644 --- a/platform/SharedPtr.h +++ b/platform/SharedPtr.h @@ -24,10 +24,12 @@ #include "platform/mbed_critical.h" +namespace mbed { + /** Shared pointer class. * * A shared pointer is a "smart" pointer that retains ownership of an object using - * reference counting accross all smart pointers referencing that object. + * reference counting across all smart pointers referencing that object. * * @code * #include "platform/SharedPtr.h" @@ -285,4 +287,10 @@ bool operator!= (U lhs, const SharedPtr &rhs) return ((T *) lhs != rhs.get()); } +} /* namespace mbed */ + +#ifndef MBED_NO_GLOBAL_USING_DIRECTIVE +using mbed::SharedPtr; +#endif + #endif // __SHAREDPTR_H__ diff --git a/platform/SingletonPtr.h b/platform/SingletonPtr.h index 2581472d0c..595d9807ca 100644 --- a/platform/SingletonPtr.h +++ b/platform/SingletonPtr.h @@ -88,7 +88,7 @@ struct SingletonPtr { * @returns * A pointer to the singleton */ - T *get() + T *get() const { if (NULL == _ptr) { singleton_lock(); @@ -108,15 +108,30 @@ struct SingletonPtr { * @returns * A pointer to the singleton */ - T *operator->() + T *operator->() const { return get(); } + /** Get a reference to the underlying singleton + * + * @returns + * A reference to the singleton + */ + T &operator*() const + { + return *get(); + } + // This is zero initialized when in global scope - T *_ptr; - // Force data to be 4 byte aligned - uint32_t _data[(sizeof(T) + sizeof(uint32_t) - 1) / sizeof(uint32_t)]; + mutable T *_ptr; +#if __cplusplus >= 201103L + // Align data appropriately + alignas(T) mutable char _data[sizeof(T)]; +#else + // Force data to be 8 byte aligned + mutable uint64_t _data[(sizeof(T) + sizeof(uint64_t) - 1) / sizeof(uint64_t)]; +#endif }; #endif diff --git a/platform/Span.h b/platform/Span.h index 05c4ec0bcf..f63a74309e 100644 --- a/platform/Span.h +++ b/platform/Span.h @@ -25,6 +25,13 @@ namespace mbed { +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_Span Span class + * @{ + */ + // Internal details of Span // It is used construct Span from Span of convertible types (non const -> const) namespace span_detail { @@ -47,12 +54,18 @@ public: } +#if defined(DOXYGEN_ONLY) /** * Special value for the Extent parameter of Span. * If the type uses this value, then the size of the array is stored in the object * at runtime. + * + * @relates Span */ +const ptrdiff_t SPAN_DYNAMIC_EXTENT = -1; +#else #define SPAN_DYNAMIC_EXTENT -1 +#endif /** * Nonowning view to a sequence of contiguous elements. @@ -691,7 +704,7 @@ struct Span { * @return A subspan of this starting at Offset and Count long. */ template - Span + Span subspan() const { MBED_ASSERT(0 <= Offset && Offset <= _size); @@ -699,7 +712,7 @@ struct Span { (Count == SPAN_DYNAMIC_EXTENT) || (0 <= Count && (Count + Offset) <= _size) ); - return Span( + return Span( _data + Offset, Count == SPAN_DYNAMIC_EXTENT ? _size - Offset : Count ); @@ -774,6 +787,8 @@ private: * * @return True if Spans in input have the same size and the same content and * false otherwise. + * + * @relates Span */ template bool operator==(const Span &lhs, const Span &rhs) @@ -827,6 +842,8 @@ bool operator==(T (&lhs)[LhsExtent], const Span &rhs) * * @return True if arrays in input do not have the same size or the same content * and false otherwise. + * + * @relates Span */ template bool operator!=(const Span &lhs, const Span &rhs) @@ -876,6 +893,8 @@ bool operator!=(T (&lhs)[LhsExtent], const Span &rhs) * * @note This helper avoids the typing of template parameter when Span is * created 'inline'. + * + * @relates Span */ template Span make_Span(T (&elements)[Size]) @@ -914,6 +933,8 @@ Span make_Span(T *elements) * * @note This helper avoids the typing of template parameter when Span is * created 'inline'. + * + * @relates Span */ template Span make_Span(T *array_ptr, ptrdiff_t array_size) @@ -951,6 +972,8 @@ Span make_const_Span(const T (&elements)[Extent]) * * @note This helper avoids the typing of template parameter when Span is * created 'inline'. + * + * @relates Span */ template Span make_const_Span(const T *elements) @@ -971,6 +994,8 @@ Span make_const_Span(const T *elements) * * @note This helper avoids the typing of template parameter when Span is * created 'inline'. + * + * @relates Span */ template Span make_const_Span(T *array_ptr, size_t array_size) @@ -978,6 +1003,10 @@ Span make_const_Span(T *array_ptr, size_t array_size) return Span(array_ptr, array_size); } +/**@}*/ + +/**@}*/ + } // namespace mbed #endif /* MBED_PLATFORM_SPAN_H_ */ diff --git a/platform/Stream.cpp b/platform/Stream.cpp index 3c14bb19c0..e395425ae7 100644 --- a/platform/Stream.cpp +++ b/platform/Stream.cpp @@ -43,7 +43,7 @@ Stream::~Stream() int Stream::putc(int c) { lock(); - fflush(_file); + std::fseek(_file, 0, SEEK_CUR); int ret = std::fputc(c, _file); unlock(); return ret; @@ -51,7 +51,7 @@ int Stream::putc(int c) int Stream::puts(const char *s) { lock(); - fflush(_file); + std::fseek(_file, 0, SEEK_CUR); int ret = std::fputs(s, _file); unlock(); return ret; @@ -60,7 +60,7 @@ int Stream::getc() { lock(); fflush(_file); - int ret = mbed_getc(_file); + int ret = std::fgetc(_file); unlock(); return ret; } @@ -68,7 +68,7 @@ char *Stream::gets(char *s, int size) { lock(); fflush(_file); - char *ret = mbed_gets(s, size, _file); + char *ret = std::fgets(s, size, _file); unlock(); return ret; } diff --git a/platform/Stream.h b/platform/Stream.h index bb761a5979..bd705c4966 100644 --- a/platform/Stream.h +++ b/platform/Stream.h @@ -20,6 +20,7 @@ #include "platform/FileLike.h" #include "platform/FileHandle.h" #include "platform/NonCopyable.h" +#include "mbed_toolchain.h" #include #include @@ -32,8 +33,6 @@ namespace mbed { */ extern void mbed_set_unbuffered_stream(std::FILE *_file); -extern int mbed_getc(std::FILE *_file); -extern char *mbed_gets(char *s, int size, std::FILE *_file); /** File stream * @@ -49,10 +48,10 @@ public: int puts(const char *s); int getc(); char *gets(char *s, int size); - int printf(const char *format, ...); - int scanf(const char *format, ...); - int vprintf(const char *format, std::va_list args); - int vscanf(const char *format, std::va_list args); + int printf(const char *format, ...) MBED_PRINTF_METHOD(1, 2); + int scanf(const char *format, ...) MBED_SCANF_METHOD(1, 2); + int vprintf(const char *format, std::va_list args) MBED_PRINTF_METHOD(1, 0); + int vscanf(const char *format, std::va_list args) MBED_SCANF_METHOD(1, 0); operator std::FILE *() { diff --git a/platform/mbed_alloc_wrappers.cpp b/platform/mbed_alloc_wrappers.cpp index 00e2dd2e75..44521573f7 100644 --- a/platform/mbed_alloc_wrappers.cpp +++ b/platform/mbed_alloc_wrappers.cpp @@ -27,7 +27,7 @@ /* There are two memory tracers in mbed OS: - the first can be used to detect the maximum heap usage at runtime. It is - activated by defining the MBED_HEAP_STATS_ENABLED macro. + activated by setting the configuration option MBED_HEAP_STATS_ENABLED to true. - the second can be used to trace each memory call by automatically invoking a callback on each memory operation (see hal/api/mbed_mem_trace.h). It is activated by setting the configuration option MBED_MEM_TRACING_ENABLED to true. @@ -40,15 +40,24 @@ are active, the second one (MBED_MEM_TRACING_ENABLED) will trace the first one's /* Implementation of the runtime max heap usage checker */ /******************************************************************************/ -/* Size must be a multiple of 8 to keep alignment */ typedef struct { uint32_t size; - uint32_t pad; + uint32_t signature; } alloc_info_t; #ifdef MBED_HEAP_STATS_ENABLED +#define MBED_HEAP_STATS_SIGNATURE (0xdeadbeef) + static SingletonPtr malloc_stats_mutex; -static mbed_stats_heap_t heap_stats = {0, 0, 0, 0, 0}; +static mbed_stats_heap_t heap_stats = {0, 0, 0, 0, 0, 0, 0}; + +typedef struct { + size_t size; +} mbed_heap_overhead_t; + +#define MALLOC_HEADER_SIZE (sizeof(mbed_heap_overhead_t)) +#define MALLOC_HEADER_PTR(p) (mbed_heap_overhead_t *)((char *)(p) - MALLOC_HEADER_SIZE) +#define MALLOC_HEAP_TOTAL_SIZE(p) (((p)->size) & (~0x1)) #endif void mbed_stats_heap_get(mbed_stats_heap_t *stats) @@ -71,7 +80,6 @@ void mbed_stats_heap_get(mbed_stats_heap_t *stats) #if defined(TOOLCHAIN_GCC) - extern "C" { void *__real__malloc_r(struct _reent *r, size_t size); void *__real__memalign_r(struct _reent *r, size_t alignment, size_t bytes); @@ -91,7 +99,7 @@ extern "C" void *__wrap__malloc_r(struct _reent *r, size_t size) extern "C" void *malloc_wrapper(struct _reent *r, size_t size, void *caller) { void *ptr = NULL; -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_lock(); #endif #ifdef MBED_HEAP_STATS_ENABLED @@ -99,6 +107,7 @@ extern "C" void *malloc_wrapper(struct _reent *r, size_t size, void *caller) alloc_info_t *alloc_info = (alloc_info_t *)__real__malloc_r(r, size + sizeof(alloc_info_t)); if (alloc_info != NULL) { alloc_info->size = size; + alloc_info->signature = MBED_HEAP_STATS_SIGNATURE; ptr = (void *)(alloc_info + 1); heap_stats.current_size += size; heap_stats.total_size += size; @@ -106,6 +115,7 @@ extern "C" void *malloc_wrapper(struct _reent *r, size_t size, void *caller) if (heap_stats.current_size > heap_stats.max_size) { heap_stats.max_size = heap_stats.current_size; } + heap_stats.overhead_size += MALLOC_HEAP_TOTAL_SIZE(MALLOC_HEADER_PTR(alloc_info)) - size; } else { heap_stats.alloc_fail_cnt += 1; } @@ -113,17 +123,17 @@ extern "C" void *malloc_wrapper(struct _reent *r, size_t size, void *caller) #else // #ifdef MBED_HEAP_STATS_ENABLED ptr = __real__malloc_r(r, size); #endif // #ifdef MBED_HEAP_STATS_ENABLED -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_malloc(ptr, size, caller); mbed_mem_trace_unlock(); -#endif // #if MBED_MEM_TRACING_ENABLED +#endif // #ifdef MBED_MEM_TRACING_ENABLED return ptr; } extern "C" void *__wrap__realloc_r(struct _reent *r, void *ptr, size_t size) { void *new_ptr = NULL; -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_lock(); #endif #ifdef MBED_HEAP_STATS_ENABLED @@ -156,10 +166,10 @@ extern "C" void *__wrap__realloc_r(struct _reent *r, void *ptr, size_t size) #else // #ifdef MBED_HEAP_STATS_ENABLED new_ptr = __real__realloc_r(r, ptr, size); #endif // #ifdef MBED_HEAP_STATS_ENABLED -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_realloc(new_ptr, ptr, size, MBED_CALLER_ADDR()); mbed_mem_trace_unlock(); -#endif // #if MBED_MEM_TRACING_ENABLED +#endif // #ifdef MBED_MEM_TRACING_ENABLED return new_ptr; } @@ -170,7 +180,7 @@ extern "C" void __wrap__free_r(struct _reent *r, void *ptr) extern "C" void free_wrapper(struct _reent *r, void *ptr, void *caller) { -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_lock(); #endif #ifdef MBED_HEAP_STATS_ENABLED @@ -178,24 +188,33 @@ extern "C" void free_wrapper(struct _reent *r, void *ptr, void *caller) alloc_info_t *alloc_info = NULL; if (ptr != NULL) { alloc_info = ((alloc_info_t *)ptr) - 1; - heap_stats.current_size -= alloc_info->size; - heap_stats.alloc_cnt -= 1; + if (MBED_HEAP_STATS_SIGNATURE == alloc_info->signature) { + size_t user_size = alloc_info->size; + size_t alloc_size = MALLOC_HEAP_TOTAL_SIZE(MALLOC_HEADER_PTR(alloc_info)); + alloc_info->signature = 0x0; + heap_stats.current_size -= user_size; + heap_stats.alloc_cnt -= 1; + heap_stats.overhead_size -= (alloc_size - user_size); + __real__free_r(r, (void *)alloc_info); + } else { + __real__free_r(r, ptr); + } } - __real__free_r(r, (void *)alloc_info); + malloc_stats_mutex->unlock(); #else // #ifdef MBED_HEAP_STATS_ENABLED __real__free_r(r, ptr); #endif // #ifdef MBED_HEAP_STATS_ENABLED -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_free(ptr, caller); mbed_mem_trace_unlock(); -#endif // #if MBED_MEM_TRACING_ENABLED +#endif // #ifdef MBED_MEM_TRACING_ENABLED } extern "C" void *__wrap__calloc_r(struct _reent *r, size_t nmemb, size_t size) { void *ptr = NULL; -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_lock(); #endif #ifdef MBED_HEAP_STATS_ENABLED @@ -208,10 +227,10 @@ extern "C" void *__wrap__calloc_r(struct _reent *r, size_t nmemb, size_t size) #else // #ifdef MBED_HEAP_STATS_ENABLED ptr = __real__calloc_r(r, nmemb, size); #endif // #ifdef MBED_HEAP_STATS_ENABLED -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_calloc(ptr, nmemb, size, MBED_CALLER_ADDR()); mbed_mem_trace_unlock(); -#endif // #if MBED_MEM_TRACING_ENABLED +#endif // #ifdef MBED_MEM_TRACING_ENABLED return ptr; } @@ -221,7 +240,6 @@ extern "C" void *__wrap__memalign_r(struct _reent *r, size_t alignment, size_t b } - /******************************************************************************/ /* ARMCC / IAR memory allocation wrappers */ /******************************************************************************/ @@ -260,7 +278,6 @@ extern "C" { void free_wrapper(void *ptr, void *caller); } - extern "C" void *SUB_MALLOC(size_t size) { return malloc_wrapper(size, MBED_CALLER_ADDR()); @@ -269,7 +286,7 @@ extern "C" void *SUB_MALLOC(size_t size) extern "C" void *malloc_wrapper(size_t size, void *caller) { void *ptr = NULL; -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_lock(); #endif #ifdef MBED_HEAP_STATS_ENABLED @@ -277,6 +294,7 @@ extern "C" void *malloc_wrapper(size_t size, void *caller) alloc_info_t *alloc_info = (alloc_info_t *)SUPER_MALLOC(size + sizeof(alloc_info_t)); if (alloc_info != NULL) { alloc_info->size = size; + alloc_info->signature = MBED_HEAP_STATS_SIGNATURE; ptr = (void *)(alloc_info + 1); heap_stats.current_size += size; heap_stats.total_size += size; @@ -284,6 +302,7 @@ extern "C" void *malloc_wrapper(size_t size, void *caller) if (heap_stats.current_size > heap_stats.max_size) { heap_stats.max_size = heap_stats.current_size; } + heap_stats.overhead_size += MALLOC_HEAP_TOTAL_SIZE(MALLOC_HEADER_PTR(alloc_info)) - size; } else { heap_stats.alloc_fail_cnt += 1; } @@ -291,10 +310,10 @@ extern "C" void *malloc_wrapper(size_t size, void *caller) #else // #ifdef MBED_HEAP_STATS_ENABLED ptr = SUPER_MALLOC(size); #endif // #ifdef MBED_HEAP_STATS_ENABLED -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_malloc(ptr, size, caller); mbed_mem_trace_unlock(); -#endif // #if MBED_MEM_TRACING_ENABLED +#endif // #ifdef MBED_MEM_TRACING_ENABLED return ptr; } @@ -302,7 +321,7 @@ extern "C" void *malloc_wrapper(size_t size, void *caller) extern "C" void *SUB_REALLOC(void *ptr, size_t size) { void *new_ptr = NULL; -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_lock(); #endif #ifdef MBED_HEAP_STATS_ENABLED @@ -322,7 +341,7 @@ extern "C" void *SUB_REALLOC(void *ptr, size_t size) // If the new buffer has been allocated copy the data to it // and free the old buffer - if (new_ptr != NULL) { + if ((new_ptr != NULL) && (ptr != NULL)) { uint32_t copy_size = (old_size < size) ? old_size : size; memcpy(new_ptr, (void *)ptr, copy_size); free(ptr); @@ -330,17 +349,17 @@ extern "C" void *SUB_REALLOC(void *ptr, size_t size) #else // #ifdef MBED_HEAP_STATS_ENABLED new_ptr = SUPER_REALLOC(ptr, size); #endif // #ifdef MBED_HEAP_STATS_ENABLED -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_realloc(new_ptr, ptr, size, MBED_CALLER_ADDR()); mbed_mem_trace_unlock(); -#endif // #if MBED_MEM_TRACING_ENABLED +#endif // #ifdef MBED_MEM_TRACING_ENABLED return new_ptr; } extern "C" void *SUB_CALLOC(size_t nmemb, size_t size) { void *ptr = NULL; -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_lock(); #endif #ifdef MBED_HEAP_STATS_ENABLED @@ -352,10 +371,10 @@ extern "C" void *SUB_CALLOC(size_t nmemb, size_t size) #else // #ifdef MBED_HEAP_STATS_ENABLED ptr = SUPER_CALLOC(nmemb, size); #endif // #ifdef MBED_HEAP_STATS_ENABLED -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_calloc(ptr, nmemb, size, MBED_CALLER_ADDR()); mbed_mem_trace_unlock(); -#endif // #if MBED_MEM_TRACING_ENABLED +#endif // #ifdef MBED_MEM_TRACING_ENABLED return ptr; } @@ -366,7 +385,7 @@ extern "C" void SUB_FREE(void *ptr) extern "C" void free_wrapper(void *ptr, void *caller) { -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_lock(); #endif #ifdef MBED_HEAP_STATS_ENABLED @@ -374,18 +393,27 @@ extern "C" void free_wrapper(void *ptr, void *caller) alloc_info_t *alloc_info = NULL; if (ptr != NULL) { alloc_info = ((alloc_info_t *)ptr) - 1; - heap_stats.current_size -= alloc_info->size; - heap_stats.alloc_cnt -= 1; + if (MBED_HEAP_STATS_SIGNATURE == alloc_info->signature) { + size_t user_size = alloc_info->size; + size_t alloc_size = MALLOC_HEAP_TOTAL_SIZE(MALLOC_HEADER_PTR(alloc_info)); + alloc_info->signature = 0x0; + heap_stats.current_size -= user_size; + heap_stats.alloc_cnt -= 1; + heap_stats.overhead_size -= (alloc_size - user_size); + SUPER_FREE((void *)alloc_info); + } else { + SUPER_FREE(ptr); + } } - SUPER_FREE((void *)alloc_info); + malloc_stats_mutex->unlock(); #else // #ifdef MBED_HEAP_STATS_ENABLED SUPER_FREE(ptr); #endif // #ifdef MBED_HEAP_STATS_ENABLED -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED mbed_mem_trace_free(ptr, caller); mbed_mem_trace_unlock(); -#endif // #if MBED_MEM_TRACING_ENABLED +#endif // #ifdef MBED_MEM_TRACING_ENABLED } #endif // #if defined(MBED_MEM_TRACING_ENABLED) || defined(MBED_HEAP_STATS_ENABLED) @@ -396,7 +424,7 @@ extern "C" void free_wrapper(void *ptr, void *caller) #else -#if MBED_MEM_TRACING_ENABLED +#ifdef MBED_MEM_TRACING_ENABLED #error Memory tracing is not supported with the current toolchain. #endif diff --git a/platform/mbed_application.c b/platform/mbed_application.c index 9953130bfd..bd2388dc14 100644 --- a/platform/mbed_application.c +++ b/platform/mbed_application.c @@ -45,7 +45,7 @@ static void powerdown_gic() GICDistributor->CPENDSGIR[i] = 0xFFFFFFFF; } for (j = 0; j < 8; j++) { - GICDistributor->IPRIORITYR[i*8+j] = 0x00000000; + GICDistributor->IPRIORITYR[i * 8 + j] = 0x00000000; } } } diff --git a/platform/mbed_assert.c b/platform/mbed_assert.c index 8a698abdd9..bc1934461a 100644 --- a/platform/mbed_assert.c +++ b/platform/mbed_assert.c @@ -13,15 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include #include "platform/mbed_assert.h" -#include "device.h" -#include "platform/mbed_interface.h" #include "platform/mbed_critical.h" +#include "platform/mbed_error.h" -void mbed_assert_internal(const char *expr, const char *file, int line) +MBED_NORETURN void mbed_assert_internal(const char *expr, const char *file, int line) { core_util_critical_section_enter(); - mbed_error_printf("mbed assertation failed: %s, file: %s, line %d \n", expr, file, line); - mbed_die(); + mbed_error(MBED_ERROR_ASSERTION_FAILED, expr, 0, file, line); } + diff --git a/platform/mbed_assert.h b/platform/mbed_assert.h index 8aecdcc3fa..4976c11b45 100644 --- a/platform/mbed_assert.h +++ b/platform/mbed_assert.h @@ -24,20 +24,21 @@ #define MBED_ASSERT_H #include "mbed_preprocessor.h" +#include "mbed_toolchain.h" #ifdef __cplusplus extern "C" { #endif -/** Internal mbed assert function which is invoked when MBED_ASSERT macro failes. +/** Internal mbed assert function which is invoked when MBED_ASSERT macro fails. * This function is active only if NDEBUG is not defined prior to including this * assert header file. * In case of MBED_ASSERT failing condition, error() is called with the assertation message. - * @param expr Expresion to be checked. + * @param expr Expression to be checked. * @param file File where assertation failed. * @param line Failing assertation line number. */ -void mbed_assert_internal(const char *expr, const char *file, int line); +MBED_NORETURN void mbed_assert_internal(const char *expr, const char *file, int line); #ifdef __cplusplus } diff --git a/platform/mbed_board.c b/platform/mbed_board.c index 0c837cfb32..59635d1d33 100644 --- a/platform/mbed_board.c +++ b/platform/mbed_board.c @@ -18,15 +18,10 @@ #include "platform/mbed_wait_api.h" #include "platform/mbed_toolchain.h" #include "platform/mbed_interface.h" +#include "platform/mbed_retarget.h" #include "platform/mbed_critical.h" -#include "hal/serial_api.h" -#if DEVICE_SERIAL -extern int stdio_uart_inited; -extern serial_t stdio_uart; -#endif - -WEAK void mbed_die(void) +WEAK MBED_NORETURN void mbed_die(void) { #if !defined (NRF51_H) && !defined(TARGET_EFM32) core_util_critical_section_enter(); @@ -55,36 +50,46 @@ void mbed_error_printf(const char *format, ...) { va_list arg; va_start(arg, format); - mbed_error_vfprintf(format, arg); + mbed_error_vprintf(format, arg); va_end(arg); } +void mbed_error_vprintf(const char *format, va_list arg) +{ + char buffer[132]; + int size = vsnprintf(buffer, sizeof buffer, format, arg); + if (size >= sizeof buffer) { + /* Output was truncated - indicate by overwriting tail of buffer + * with ellipsis, newline and null terminator. + */ + static const char ellipsis[] = "...\n"; + memcpy(&buffer[sizeof buffer - sizeof ellipsis], ellipsis, sizeof ellipsis); + } + if (size > 0) { + mbed_error_puts(buffer); + } +} + +void mbed_error_puts(const char *str) +{ + core_util_critical_section_enter(); +#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES || MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES + char stdio_out_prev = '\0'; + for (; *str != '\0'; str++) { + if (*str == '\n' && stdio_out_prev != '\r') { + const char cr = '\r'; + write(STDERR_FILENO, &cr, 1); + } + write(STDERR_FILENO, str, 1); + stdio_out_prev = *str; + } +#else + write(STDERR_FILENO, str, strlen(str)); +#endif + core_util_critical_section_exit(); +} + void mbed_error_vfprintf(const char *format, va_list arg) { -#if DEVICE_SERIAL -#define ERROR_BUF_SIZE (128) - core_util_critical_section_enter(); - char buffer[ERROR_BUF_SIZE]; - int size = vsnprintf(buffer, ERROR_BUF_SIZE, format, arg); - if (size > 0) { - if (!stdio_uart_inited) { - serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX); - } -#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES - char stdio_out_prev = '\0'; - for (int i = 0; i < size; i++) { - if (buffer[i] == '\n' && stdio_out_prev != '\r') { - serial_putc(&stdio_uart, '\r'); - } - serial_putc(&stdio_uart, buffer[i]); - stdio_out_prev = buffer[i]; - } -#else - for (int i = 0; i < size; i++) { - serial_putc(&stdio_uart, buffer[i]); - } -#endif - } - core_util_critical_section_exit(); -#endif + mbed_error_vprintf(format, arg); } diff --git a/platform/mbed_critical.c b/platform/mbed_critical.c index 59876db431..320319ba63 100644 --- a/platform/mbed_critical.c +++ b/platform/mbed_critical.c @@ -100,6 +100,11 @@ void core_util_critical_section_exit(void) } } +void core_util_atomic_flag_clear(volatile core_util_atomic_flag *flagPtr) +{ + flagPtr->_flag = false; +} + #if MBED_EXCLUSIVE_ACCESS /* Supress __ldrex and __strex deprecated warnings - "#3731-D: intrinsic is deprecated" */ @@ -107,6 +112,15 @@ void core_util_critical_section_exit(void) #pragma diag_suppress 3731 #endif +bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr) +{ + uint8_t currentValue; + do { + currentValue = __LDREXB(&flagPtr->_flag); + } while (__STREXB(true, &flagPtr->_flag)); + return currentValue; +} + bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue) { do { @@ -204,6 +218,15 @@ uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta) #else +bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr) +{ + core_util_critical_section_enter(); + uint8_t currentValue = flagPtr->_flag; + flagPtr->_flag = true; + core_util_critical_section_exit(); + return currentValue; +} + bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue) { bool success; diff --git a/platform/mbed_critical.h b/platform/mbed_critical.h index f5ecc37aab..c4a510ca8e 100644 --- a/platform/mbed_critical.h +++ b/platform/mbed_critical.h @@ -39,7 +39,7 @@ extern "C" { * This function can be called to determine whether or not interrupts are currently enabled. * @note * NOTE: - * This function works for both cortex-A and cortex-M, although the underlyng implementation + * This function works for both cortex-A and cortex-M, although the underlying implementation * differs. * @return true if interrupts are enabled, false otherwise */ @@ -50,7 +50,7 @@ bool core_util_are_interrupts_enabled(void); * This function can be called to determine if the code is running on interrupt context. * @note * NOTE: - * This function works for both cortex-A and cortex-M, although the underlyng implementation + * This function works for both cortex-A and cortex-M, although the underlying implementation * differs. * @return true if in an isr, false otherwise */ @@ -89,6 +89,43 @@ void core_util_critical_section_exit(void); */ bool core_util_in_critical_section(void); +/** + * A lock-free, primitive atomic flag. + * + * Emulate C11's atomic_flag. The flag is initially in an indeterminate state + * unless explicitly initialised with CORE_UTIL_ATOMIC_FLAG_INIT. + */ +typedef struct core_util_atomic_flag { + uint8_t _flag; +} core_util_atomic_flag; + +/** + * Initialiser for a core_util_atomic_flag. + * + * Example: + * ~~~ + * core_util_atomic_flag in_progress = CORE_UTIL_ATOMIC_FLAG_INIT; + * ~~~ + */ +#define CORE_UTIL_ATOMIC_FLAG_INIT { 0 } + +/** + * Atomic test and set. + * + * Atomically tests then sets the flag to true, returning the previous value. + * + * @param flagPtr Target flag being tested and set. + * @return The previous value. + */ +bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr); + +/** + * Atomic clear. + * + * @param flagPtr Target flag being cleared. + */ +void core_util_atomic_flag_clear(volatile core_util_atomic_flag *flagPtr); + /** * Atomic compare and set. It compares the contents of a memory location to a * given value and, only if they are the same, modifies the contents of that diff --git a/platform/mbed_debug.h b/platform/mbed_debug.h index 5ccc123bb0..38da79a821 100644 --- a/platform/mbed_debug.h +++ b/platform/mbed_debug.h @@ -27,11 +27,14 @@ #include #include #endif +#include "mbed_toolchain.h" #ifdef __cplusplus extern "C" { #endif +static inline void debug(const char *format, ...) MBED_PRINTF(1, 2); +static inline void debug_if(int condition, const char *format, ...) MBED_PRINTF(2, 3); /** Output a debug message * diff --git a/platform/mbed_error.c b/platform/mbed_error.c index d093987824..efd5ef5fba 100644 --- a/platform/mbed_error.c +++ b/platform/mbed_error.c @@ -28,71 +28,64 @@ #if DEVICE_STDIO_MESSAGES #include #endif - -//Helper macro to get the current SP -#define GET_CURRENT_SP(sp) \ - { \ - /*If in Handler mode we are always using MSP*/ \ - if ( __get_IPSR() != 0U ) { \ - sp = __get_MSP(); \ - } else { \ - /*Look into CONTROL.SPSEL value*/ \ - if ((__get_CONTROL() & 2U) == 0U) { \ - sp = __get_MSP();/*Read MSP*/ \ - } else { \ - sp = __get_PSP();/*Read PSP*/ \ - } \ - } \ - } +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#include #ifndef NDEBUG -#define ERROR_REPORT(ctx, error_msg) print_error_report(ctx, error_msg) +#define ERROR_REPORT(ctx, error_msg, error_filename, error_line) print_error_report(ctx, error_msg, error_filename, error_line) +static void print_error_report(const mbed_error_ctx *ctx, const char *, const char *error_filename, int error_line); #else -#define ERROR_REPORT(ctx, error_msg) ((void) 0) +#define ERROR_REPORT(ctx, error_msg, error_filename, error_line) ((void) 0) #endif -static uint8_t error_in_progress = 0; +static core_util_atomic_flag error_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT; +static core_util_atomic_flag halt_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT; static int error_count = 0; static mbed_error_ctx first_error_ctx = {0}; static mbed_error_ctx last_error_ctx = {0}; static mbed_error_hook_t error_hook = NULL; -static void print_error_report(mbed_error_ctx *ctx, const char *); static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsigned int error_value, const char *filename, int line_number, void *caller); //Helper function to halt the system -static void mbed_halt_system(void) +static MBED_NORETURN void mbed_halt_system(void) { - //If not in ISR context exit, otherwise spin on WFI - if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) { + // Prevent recursion if halt is called again during halt attempt - try + // something simple instead. + if (core_util_atomic_flag_test_and_set(&halt_in_progress)) { + core_util_critical_section_enter(); + __DSB(); for (;;) { - __WFI(); + __WFE(); // Not WFI, as don't want to wake for pending interrupts } - } else { - //exit eventually calls mbed_die - exit(1); } + + //If in ISR context, call mbed_die directly + if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) { + mbed_die(); + } + + // In normal context, try orderly exit(1), which eventually calls mbed_die + exit(1); } -WEAK void error(const char *format, ...) +WEAK MBED_NORETURN void error(const char *format, ...) { - - // Prevent recursion if error is called again - if (error_in_progress) { - return; - } - - //Call handle_error/print_error_report permanently setting error_in_progress flag - handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR()); - ERROR_REPORT(&last_error_ctx, "Fatal Run-time error"); - error_in_progress = 1; + // Prevent recursion if error is called again during store+print attempt + if (!core_util_atomic_flag_test_and_set(&error_in_progress)) { + handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR()); + ERROR_REPORT(&last_error_ctx, "Fatal Run-time error", NULL, 0); #ifndef NDEBUG - va_list arg; - va_start(arg, format); - mbed_error_vfprintf(format, arg); - va_end(arg); + va_list arg; + va_start(arg, format); + mbed_error_vprintf(format, arg); + va_end(arg); #endif - exit(1); + } + + mbed_halt_system(); } //Set an error status with the error handling system @@ -107,18 +100,6 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign error_status = MBED_ERROR_INVALID_ARGUMENT; } - //Prevent corruption by holding out other callers - //and we also need this until we remove the "error" call completely - while (error_in_progress == 1); - - //Use critsect here, as we don't want inadvertant modification of this global variable - core_util_critical_section_enter(); - error_in_progress = 1; - core_util_critical_section_exit(); - - //Increment error count - error_count++; - //Clear the context capturing buffer memset(¤t_error_ctx, 0, sizeof(mbed_error_ctx)); //Capture error information @@ -132,20 +113,22 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign current_error_ctx.thread_entry_address = (uint32_t)current_thread->thread_addr; current_error_ctx.thread_stack_size = current_thread->stack_size; current_error_ctx.thread_stack_mem = (uint32_t)current_thread->stack_mem; -#ifdef TARGET_CORTEX_M - GET_CURRENT_SP(current_error_ctx.thread_current_sp); -#endif //TARGET_CORTEX_M - + current_error_ctx.thread_current_sp = (uint32_t)¤t_error_ctx; // Address local variable to get a stack pointer #endif //MBED_CONF_RTOS_PRESENT #if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED //Capture filename/linenumber if provided //Index for tracking error_filename - memset(¤t_error_ctx.error_filename, 0, MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN); strncpy(current_error_ctx.error_filename, filename, MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN); current_error_ctx.error_line_number = line_number; #endif + //Prevent corruption by holding out other callers + core_util_critical_section_enter(); + + //Increment error count + error_count++; + //Capture the fist system error and store it if (error_count == 1) { //first error memcpy(&first_error_ctx, ¤t_error_ctx, sizeof(mbed_error_ctx)); @@ -164,7 +147,7 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign error_hook(&last_error_ctx); } - error_in_progress = 0; + core_util_critical_section_exit(); return MBED_SUCCESS; } @@ -190,25 +173,25 @@ int mbed_get_error_count(void) return error_count; } -//Sets a fatal error +//Sets a non-fatal error mbed_error_status_t mbed_warning(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) { return handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR()); } //Sets a fatal error, this function is marked WEAK to be able to override this for some tests -WEAK mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) +WEAK MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) { - //set the error reported and then halt the system - if (MBED_SUCCESS != handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR())) { - return MBED_ERROR_FAILED_OPERATION; + // Prevent recursion if error is called again during store+print attempt + if (!core_util_atomic_flag_test_and_set(&error_in_progress)) { + //set the error reported + (void) handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR()); + + //On fatal errors print the error context/report + ERROR_REPORT(&last_error_ctx, error_msg, filename, line_number); } - //On fatal errors print the error context/report - ERROR_REPORT(&last_error_ctx, error_msg); mbed_halt_system(); - - return MBED_ERROR_FAILED_OPERATION; } //Register an application defined callback with error handling @@ -290,15 +273,20 @@ mbed_error_status_t mbed_clear_all_errors(void) return status; } +static const char *name_or_unnamed(const char *name) +{ + return name ? name : ""; +} + #if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT) /* Prints info of a thread(using osRtxThread_t struct)*/ -static void print_thread(osRtxThread_t *thread) +static void print_thread(const osRtxThread_t *thread) { - mbed_error_printf("\nState: 0x%08X Entry: 0x%08X Stack Size: 0x%08X Mem: 0x%08X SP: 0x%08X", thread->state, thread->thread_addr, thread->stack_size, (uint32_t)thread->stack_mem, thread->sp); + mbed_error_printf("\n%s State: 0x%" PRIX8 " Entry: 0x%08" PRIX32 " Stack Size: 0x%08" PRIX32 " Mem: 0x%08" PRIX32 " SP: 0x%08" PRIX32, name_or_unnamed(thread->name), thread->state, thread->thread_addr, thread->stack_size, (uint32_t)thread->stack_mem, thread->sp); } /* Prints thread info from a list */ -static void print_threads_info(osRtxThread_t *threads) +static void print_threads_info(const osRtxThread_t *threads) { while (threads != NULL) { print_thread(threads); @@ -308,86 +296,90 @@ static void print_threads_info(osRtxThread_t *threads) #endif #ifndef NDEBUG -static void print_error_report(mbed_error_ctx *ctx, const char *error_msg) +static void print_error_report(const mbed_error_ctx *ctx, const char *error_msg, const char *error_filename, int error_line) { - uint32_t error_code = MBED_GET_ERROR_CODE(ctx->error_status); - uint32_t error_module = MBED_GET_ERROR_MODULE(ctx->error_status); + int error_code = MBED_GET_ERROR_CODE(ctx->error_status); + int error_module = MBED_GET_ERROR_MODULE(ctx->error_status); mbed_error_printf("\n\n++ MbedOS Error Info ++\nError Status: 0x%X Code: %d Module: %d\nError Message: ", ctx->error_status, error_code, error_module); switch (error_code) { //These are errors reported by kernel handled from mbed_rtx_handlers case MBED_ERROR_CODE_RTOS_EVENT: - mbed_error_printf("Kernel Error: 0x%X, ", ctx->error_value); + mbed_error_printf("Kernel Error: 0x%" PRIX32 ", ", ctx->error_value); break; case MBED_ERROR_CODE_RTOS_THREAD_EVENT: - mbed_error_printf("Thread: 0x%X, ", ctx->error_value); + mbed_error_printf("Thread: 0x%" PRIX32 ", ", ctx->error_value); break; case MBED_ERROR_CODE_RTOS_MUTEX_EVENT: - mbed_error_printf("Mutex: 0x%X, ", ctx->error_value); + mbed_error_printf("Mutex: 0x%" PRIX32 ", ", ctx->error_value); break; case MBED_ERROR_CODE_RTOS_SEMAPHORE_EVENT: - mbed_error_printf("Semaphore: 0x%X, ", ctx->error_value); + mbed_error_printf("Semaphore: 0x%" PRIX32 ", ", ctx->error_value); break; case MBED_ERROR_CODE_RTOS_MEMORY_POOL_EVENT: - mbed_error_printf("MemoryPool: 0x%X, ", ctx->error_value); + mbed_error_printf("MemoryPool: 0x%" PRIX32 ", ", ctx->error_value); break; case MBED_ERROR_CODE_RTOS_EVENT_FLAGS_EVENT: - mbed_error_printf("EventFlags: 0x%X, ", ctx->error_value); + mbed_error_printf("EventFlags: 0x%" PRIX32 ", ", ctx->error_value); break; case MBED_ERROR_CODE_RTOS_TIMER_EVENT: - mbed_error_printf("Timer: 0x%X, ", ctx->error_value); + mbed_error_printf("Timer: 0x%" PRIX32 ", ", ctx->error_value); break; case MBED_ERROR_CODE_RTOS_MESSAGE_QUEUE_EVENT: - mbed_error_printf("MessageQueue: 0x%X, ", ctx->error_value); + mbed_error_printf("MessageQueue: 0x%" PRIX32 ", ", ctx->error_value); + break; + + case MBED_ERROR_CODE_ASSERTION_FAILED: + mbed_error_printf("Assertion failed: "); break; default: //Nothing to do here, just print the error info down break; } - mbed_error_printf(error_msg); - mbed_error_printf("\nLocation: 0x%X", ctx->error_address); + mbed_error_puts(error_msg); + mbed_error_printf("\nLocation: 0x%" PRIX32, ctx->error_address); -#if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED && !defined(NDEBUG) - if ((NULL != ctx->error_filename[0]) && (ctx->error_line_number != 0)) { - //for string, we must pass address of a ptr which has the address of the string - mbed_error_printf("\nFile:%s+%d", ctx->error_filename, ctx->error_line_number); + /* We print the filename passed in, not any filename in the context. This + * avoids the console print for mbed_error being limited to the presence + * and length of the filename storage. Note that although the MBED_ERROR + * macro compiles out filenames unless platform.error-filename-capture-enabled + * is turned on, MBED_ASSERT always passes filenames, and other direct + * users of mbed_error() may also choose to. + */ + if (error_filename) { + mbed_error_puts("\nFile: "); + mbed_error_puts(error_filename); + mbed_error_printf("+%d", error_line); } -#endif - mbed_error_printf("\nError Value: 0x%X", ctx->error_value); -#ifdef TARGET_CORTEX_M - mbed_error_printf("\nCurrent Thread: Id: 0x%X Entry: 0x%X StackSize: 0x%X StackMem: 0x%X SP: 0x%X ", + mbed_error_printf("\nError Value: 0x%" PRIX32, ctx->error_value); +#ifdef MBED_CONF_RTOS_PRESENT + mbed_error_printf("\nCurrent Thread: %s Id: 0x%" PRIX32 " Entry: 0x%" PRIX32 " StackSize: 0x%" PRIX32 " StackMem: 0x%" PRIX32 " SP: 0x%" PRIX32 " ", + name_or_unnamed(((osRtxThread_t *)ctx->thread_id)->name), ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem, ctx->thread_current_sp); -#else - //For Cortex-A targets we dont have support to capture the current SP - mbed_error_printf("\nCurrent Thread: Id: 0x%X Entry: 0x%X StackSize: 0x%X StackMem: 0x%X ", - ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem); -#endif //TARGET_CORTEX_M +#endif #if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT) mbed_error_printf("\nNext:"); print_thread(osRtxInfo.thread.run.next); + mbed_error_printf("\nReady:"); + print_threads_info(osRtxInfo.thread.ready.thread_list); + mbed_error_printf("\nWait:"); - osRtxThread_t *threads = (osRtxThread_t *)&osRtxInfo.thread.wait_list; - print_threads_info(threads); + print_threads_info(osRtxInfo.thread.wait_list); mbed_error_printf("\nDelay:"); - threads = (osRtxThread_t *)&osRtxInfo.thread.delay_list; - print_threads_info(threads); - - mbed_error_printf("\nIdle:"); - threads = (osRtxThread_t *)&osRtxInfo.thread.idle; - print_threads_info(threads); + print_threads_info(osRtxInfo.thread.delay_list); #endif mbed_error_printf(MBED_CONF_PLATFORM_ERROR_DECODE_HTTP_URL_STR, ctx->error_status); mbed_error_printf("\n-- MbedOS Error Info --\n"); diff --git a/platform/mbed_error.h b/platform/mbed_error.h index 18d02d62e8..c48d05c27c 100644 --- a/platform/mbed_error.h +++ b/platform/mbed_error.h @@ -42,7 +42,7 @@ extern "C" { #else //MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN #if MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN > 64 //We have to limit this to 64 bytes since we use mbed_error_printf for error reporting -//and mbed_error_vfprintf uses 128bytes internal buffer which may not be sufficient for anything +//and mbed_error_vprintf uses 128bytes internal buffer which may not be sufficient for anything //longer that 64 bytes with the current implementation. #error "Unsupported error filename buffer length detected, max supported length is 64 chars. Please change MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN or max-error-filename-len in configuration." #endif @@ -86,24 +86,24 @@ extern "C" { \endverbatim * * The error status value range for each error type is as follows:\n - * Posix Error Status-es - 0xFFFFFFFF to 0xFFFFFF01(-1 -255) - This corresponds to Posix error codes represented as negative.\n + * POSIX Error Status-es - 0xFFFFFFFF to 0xFFFFFF01(-1 -255) - This corresponds to POSIX error codes represented as negative.\n * System Error Status-es - 0x80XX0100 to 0x80XX0FFF - This corresponds to System error codes range(all values are negative). Bits 23-16 will be module type(marked with XX)\n * Custom Error Status-es - 0xA0XX1000 to 0xA0XXFFFF - This corresponds to Custom error codes range(all values are negative). Bits 23-16 will be module type(marked with XX)\n\n * - * The ERROR CODE(values encoded into ERROR CODE bit-field in mbed_error_status_t) value range for each error type is also seperated as below:\n - * Posix Error Codes - 1 to 255.\n + * The ERROR CODE(values encoded into ERROR CODE bit-field in mbed_error_status_t) value range for each error type is also separated as below:\n + * POSIX Error Codes - 1 to 255.\n * System Error Codes - 256 to 4095.\n * Custom Error Codes - 4096 to 65535.\n * - * @note Posix error codes are always encoded as negative of their actual value. For example, EPERM is encoded as -EPERM. - * And, the MODULE TYPE for Posix error codes are always encoded as MBED_MODULE_UNKNOWN.\n - * This is to enable easy injection of Posix error codes into MbedOS error handling system without altering the actual Posix error values.\n - * Accordingly, Posix error codes are represented as -1 to -255 under MbedOS error status representation. + * @note POSIX error codes are always encoded as negative of their actual value. For example, EPERM is encoded as -EPERM. + * And, the MODULE TYPE for POSIX error codes are always encoded as MBED_MODULE_UNKNOWN.\n + * This is to enable easy injection of POSIX error codes into MbedOS error handling system without altering the actual POSIX error values.\n + * Accordingly, POSIX error codes are represented as -1 to -255 under MbedOS error status representation. */ typedef int mbed_error_status_t; /** - * Macro for defining a Posix error status. This macro is mainly used to define Posix error values in mbed_error_code_t enumeration. + * Macro for defining a POSIX error status. This macro is mainly used to define POSIX error values in mbed_error_code_t enumeration. * @param error_name Name of the error without the ERROR_ prefix * @param error_code Error code value to be used, must be between 1 and 255(inclusive). * @@ -169,8 +169,7 @@ typedef int mbed_error_status_t; * @param error_status mbed_error_status_t status to be set(See mbed_error_status_t enum above for available error status values). * @param error_msg The error message to be printed out to STDIO/Serial. * @param error_value Value associated with the error status. This would depend on error code/error scenario. Only available with MBED_ERROR1 - * @return 0 or MBED_SUCCESS. - * MBED_ERROR_INVALID_ARGUMENT if called with invalid error status/codes + * @return Does not return * * @code * @@ -202,7 +201,7 @@ typedef int mbed_error_status_t; * See mbed_error_status_t description for more info.\n * MBED_ERROR_TYPE_SYSTEM - Used to indicate that the error status is of System defined Error type.\n * MBED_ERROR_TYPE_CUSTOM - Used to indicate that the error status is of Custom defined Error type.\n - * MBED_ERROR_TYPE_POSIX - Used to indicate that the error status is of Posix error type.\n + * MBED_ERROR_TYPE_POSIX - Used to indicate that the error status is of POSIX error type.\n * */ typedef enum _mbed_error_type_t { @@ -231,31 +230,32 @@ typedef enum _mbed_error_type_t { * @note * \n Below are the module code mappings:\n \verbatim - MBED_MODULE_APPLICATION 0 Application - MBED_MODULE_PLATFORM 1 Platform - MODULE_KERNEL 2 RTX Kernel - MBED_MODULE_NETWORK_STACK 3 Network stack - MBED_MODULE_HAL 4 HAL - Hardware Abstraction Layer - MBED_MODULE_NETWORK_STACKMODULE_MEMORY_SUBSYSTEM 5 Memory Subsystem - MBED_MODULE_FILESYSTEM 6 Filesystem - MBED_MODULE_BLOCK_DEVICE 7 Block device - MBED_MODULE_DRIVER 8 Driver - MBED_MODULE_DRIVER_SERIAL 9 Serial Driver - MBED_MODULE_DRIVER_RTC 10 RTC Driver - MBED_MODULE_DRIVER_I2C 11 I2C Driver - MODULE_DRIVER_SPI 12 SPI Driver - MODULE_DRIVER_GPIO 13 GPIO Driver - MODULE_DRIVER_ANALOG 14 Analog Driver - MODULE_DRIVER_DIGITAL 15 DigitalIO Driver - MODULE_DRIVER_CAN 16 CAN Driver - MODULE_DRIVER_ETHERNET 17 Ethernet Driver - MODULE_DRIVER_CRC 18 CRC Module - MODULE_DRIVER_PWM 19 PWM Driver - MODULE_DRIVER_QSPI 20 QSPI Driver - MODULE_DRIVER_USB 21 USB Driver - MODULE_TARGET_SDK 22 SDK + MBED_MODULE_APPLICATION 0 Application + MBED_MODULE_PLATFORM 1 Platform + MBED_MODULE_KERNEL 2 RTX Kernel + MBED_MODULE_NETWORK_STACK 3 Network stack + MBED_MODULE_HAL 4 HAL - Hardware Abstraction Layer + MBED_MODULE_MEMORY_SUBSYSTEM 5 Memory Subsystem + MBED_MODULE_FILESYSTEM 6 Filesystem + MBED_MODULE_BLOCK_DEVICE 7 Block device + MBED_MODULE_DRIVER 8 Driver + MBED_MODULE_DRIVER_SERIAL 9 Serial Driver + MBED_MODULE_DRIVER_RTC 10 RTC Driver + MBED_MODULE_DRIVER_I2C 11 I2C Driver + MBED_MODULE_DRIVER_SPI 12 SPI Driver + MBED_MODULE_DRIVER_GPIO 13 GPIO Driver + MBED_MODULE_DRIVER_ANALOG 14 Analog Driver + MBED_MODULE_DRIVER_DIGITAL 15 DigitalIO Driver + MBED_MODULE_DRIVER_CAN 16 CAN Driver + MBED_MODULE_DRIVER_ETHERNET 17 Ethernet Driver + MBED_MODULE_DRIVER_CRC 18 CRC Module + MBED_MODULE_DRIVER_PWM 19 PWM Driver + MBED_MODULE_DRIVER_QSPI 20 QSPI Driver + MBED_MODULE_DRIVER_USB 21 USB Driver + MBED_MODULE_TARGET_SDK 22 SDK + MBED_MODULE_BLE 23 BLE - MBED_MODULE_UNKNOWN 255 Unknown module + MBED_MODULE_UNKNOWN 255 Unknown module \endverbatim * */ @@ -265,7 +265,7 @@ typedef enum _mbed_module_type { MBED_MODULE_KERNEL, MBED_MODULE_NETWORK_STACK, MBED_MODULE_HAL, - MBED_MODULE_NETWORK_STACKMODULE_MEMORY_SUBSYSTEM, + MBED_MODULE_MEMORY_SUBSYSTEM, MBED_MODULE_FILESYSTEM, MBED_MODULE_BLOCK_DEVICE, MBED_MODULE_DRIVER, @@ -290,7 +290,7 @@ typedef enum _mbed_module_type { MBED_MODULE_MAX = MBED_MODULE_UNKNOWN } mbed_module_type_t; -//Use MBED_SUCCESS(=0) or any postive number for successful returns +//Use MBED_SUCCESS(=0) or any positive number for successful returns #define MBED_SUCCESS 0 #define MBED_POSIX_ERROR_BASE 0 @@ -301,23 +301,23 @@ typedef enum _mbed_module_type { /** mbed_error_code_t definition * * mbed_error_code_t enumeration defines the Error codes and Error status values for MBED_MODULE_UNKNOWN.\n - * It defines all of Posix Error Codes/Statuses and Mbed System Error Codes/Statuses.\n\n + * It defines all of POSIX Error Codes/Statuses and Mbed System Error Codes/Statuses.\n\n * * @note - * Posix Error codes are defined using the macro MBED_DEFINE_POSIX_ERROR\n + * POSIX Error codes are defined using the macro MBED_DEFINE_POSIX_ERROR\n * For example MBED_DEFINE_POSIX_ERROR( EPERM, EPERM ). This effectively defines the following values:\n * ERROR_CODE_EPERM = EPERM\n * ERROR_EPERM = -EPERM\n * - * Posix Error codes are defined using the macro MBED_DEFINE_POSIX_ERROR\n + * POSIX Error codes are defined using the macro MBED_DEFINE_POSIX_ERROR\n * For example MBED_DEFINE_POSIX_ERROR( EPERM, EPERM ). This macro defines the following values:\n * ERROR_CODE_EPERM = MBED_POSIX_ERROR_BASE+EPERM\n * ERROR_EPERM = -(MBED_POSIX_ERROR_BASE+EPERM)\n * Its effectively equivalent to:\n * ERROR_CODE_EPERM = 1\n * ERROR_EPERM = -1\n - * All Posix error codes currently supported by MbedOS(defined in mbed_retarget.h) are defined using the MBED_DEFINE_POSIX_ERROR macro.\n\n - * Below are the Posic error codes and the description:\n + * All POSIX error codes currently supported by MbedOS(defined in mbed_retarget.h) are defined using the MBED_DEFINE_POSIX_ERROR macro.\n\n + * Below are the POSIX error codes and the description:\n * \verbatim EPERM 1 Operation not permitted ENOENT 2 No such file or directory @@ -469,7 +469,7 @@ typedef enum _mbed_module_type { INVALID_DATA 258 Invalid data INVALID_FORMAT 259 Invalid format INVALID_INDEX 260 Invalid Index - INVALID_SIZE 261 Inavlid Size + INVALID_SIZE 261 Invalid Size INVALID_OPERATION 262 Invalid Operation NOT_FOUND 263 Not Found ACCESS_DENIED 264 Access Denied @@ -484,9 +484,9 @@ typedef enum _mbed_module_type { OPERATION_ABORTED 273 Operation failed WRITE_PROTECTED 274 Attempt to write to write-protected resource NO_RESPONSE 275 No response - SEMAPHORE_LOCK_FAILED 276 Sempahore lock failed + SEMAPHORE_LOCK_FAILED 276 Semaphore lock failed MUTEX_LOCK_FAILED 277 Mutex lock failed - SEMAPHORE_UNLOCK_FAILED 278 Sempahore unlock failed + SEMAPHORE_UNLOCK_FAILED 278 Semaphore unlock failed MUTEX_UNLOCK_FAILED 279 Mutex unlock failed CRC_ERROR 280 CRC error or mismatch OPEN_FAILED 281 Open failed @@ -524,11 +524,14 @@ typedef enum _mbed_module_type { DEVICE_BUSY 313 Device Busy CONFIG_UNSUPPORTED 314 Configuration not supported CONFIG_MISMATCH 315 Configuration mismatch - ALREADY_INITIALIZED 316 Already initialzied + ALREADY_INITIALIZED 316 Already initialized HARDFAULT_EXCEPTION 317 HardFault exception MEMMANAGE_EXCEPTION 318 MemManage exception BUSFAULT_EXCEPTION 319 BusFault exception USAGEFAULT_EXCEPTION 320 UsageFault exception + BLE_NO_FRAME_INITIALIZED, 321 BLE No frame initialized + BLE_BACKEND_CREATION_FAILED 322 BLE Backend creation failed + BLE_BACKEND_NOT_INITIALIZED 323 BLE Backend not initialized \endverbatim * * @note @@ -543,9 +546,9 @@ typedef enum _mbed_module_type { * * @note * **Using error codes:** \n - * Posix error codes may be used in modules/functions currently using Posix error codes and switching them to Mbed-OS error codes + * POSIX error codes may be used in modules/functions currently using POSIX error codes and switching them to Mbed-OS error codes * may cause interoperability issues. For example, some of the filesystem, network stack implementations may need to use - * Posix error codes in order to keep them compatible with other modules interfacing with them, and may continue to use Posix error codes. + * POSIX error codes in order to keep them compatible with other modules interfacing with them, and may continue to use POSIX error codes. * * In all other cases, like for any native development of Mbed-OS modules Mbed-OS error codes should be used. * This makes it easy to use Mbed-OS error reporting/logging infrastructure and makes debugging error scenarios @@ -561,20 +564,19 @@ typedef enum _mbed_module_type { * * \verbatim ++ MbedOS Error Info ++ - Error Status: 0x80040103 - Error Code: 259 - Error Module: 04 - Error Message: HAL Module error - Error Location: 0x000067C7 - Error Value: 0x00005566 - Current Thread: Id: 0x200024A8 EntryFn: 0x0000FB0D StackSize: 0x00001000 StackMem: 0x200014A8 SP: 0x2002FFD8 + Error Status: 0x80FF013D Code: 317 Module: 255 + Error Message: Fault exception + Location: 0x5CD1 + Error Value: 0x4A2A + Current Thread: Id: 0x20001E80 Entry: 0x5EB1 StackSize: 0x1000 StackMem: 0x20000E80 SP: 0x2002FF90 + For more info, visit: https://mbed.com/s/error?error=0x80FF013D&mbedos=999999&core=0x410FC241&compile=1&ver=5060528 -- MbedOS Error Info -- \endverbatim */ typedef enum _mbed_error_code { //Below are POSIX ERROR CODE definitions, which starts at MBED_POSIX_ERROR_BASE(=0) - //POSIX ERROR CODE definitions starts at offset 0(MBED_POSIX_ERROR_BASE) to align them with actual Posix Error Code + //POSIX ERROR CODE definitions starts at offset 0(MBED_POSIX_ERROR_BASE) to align them with actual POSIX Error Code //defintions in mbed_retarget.h // Error Name Error Code MBED_DEFINE_POSIX_ERROR(EPERM, EPERM), /* 1 Operation not permitted */ @@ -717,7 +719,7 @@ typedef enum _mbed_error_code { MBED_DEFINE_SYSTEM_ERROR(INVALID_DATA_DETECTED, 2), /* 258 Invalid data detected */ MBED_DEFINE_SYSTEM_ERROR(INVALID_FORMAT, 3), /* 259 Invalid format */ MBED_DEFINE_SYSTEM_ERROR(INVALID_INDEX, 4), /* 260 Invalid Index */ - MBED_DEFINE_SYSTEM_ERROR(INVALID_SIZE, 5), /* 261 Inavlid Size */ + MBED_DEFINE_SYSTEM_ERROR(INVALID_SIZE, 5), /* 261 Invalid Size */ MBED_DEFINE_SYSTEM_ERROR(INVALID_OPERATION, 6), /* 262 Invalid Operation */ MBED_DEFINE_SYSTEM_ERROR(ITEM_NOT_FOUND, 7), /* 263 Item Not Found */ MBED_DEFINE_SYSTEM_ERROR(ACCESS_DENIED, 8), /* 264 Access Denied */ @@ -732,9 +734,9 @@ typedef enum _mbed_error_code { MBED_DEFINE_SYSTEM_ERROR(OPERATION_ABORTED, 17), /* 273 Operation failed */ MBED_DEFINE_SYSTEM_ERROR(WRITE_PROTECTED, 18), /* 274 Attempt to write to write-protected resource */ MBED_DEFINE_SYSTEM_ERROR(NO_RESPONSE, 19), /* 275 No response */ - MBED_DEFINE_SYSTEM_ERROR(SEMAPHORE_LOCK_FAILED, 20), /* 276 Sempahore lock failed */ + MBED_DEFINE_SYSTEM_ERROR(SEMAPHORE_LOCK_FAILED, 20), /* 276 Semaphore lock failed */ MBED_DEFINE_SYSTEM_ERROR(MUTEX_LOCK_FAILED, 21), /* 277 Mutex lock failed */ - MBED_DEFINE_SYSTEM_ERROR(SEMAPHORE_UNLOCK_FAILED, 22), /* 278 Sempahore unlock failed */ + MBED_DEFINE_SYSTEM_ERROR(SEMAPHORE_UNLOCK_FAILED, 22), /* 278 Semaphore unlock failed */ MBED_DEFINE_SYSTEM_ERROR(MUTEX_UNLOCK_FAILED, 23), /* 279 Mutex unlock failed */ MBED_DEFINE_SYSTEM_ERROR(CRC_ERROR, 24), /* 280 CRC error or mismatch */ MBED_DEFINE_SYSTEM_ERROR(OPEN_FAILED, 25), /* 281 Open failed */ @@ -772,7 +774,7 @@ typedef enum _mbed_error_code { MBED_DEFINE_SYSTEM_ERROR(DEVICE_BUSY, 57), /* 313 Device Busy */ MBED_DEFINE_SYSTEM_ERROR(CONFIG_UNSUPPORTED, 58), /* 314 Configuration not supported */ MBED_DEFINE_SYSTEM_ERROR(CONFIG_MISMATCH, 59), /* 315 Configuration mismatch */ - MBED_DEFINE_SYSTEM_ERROR(ALREADY_INITIALIZED, 60), /* 316 Already initialzied */ + MBED_DEFINE_SYSTEM_ERROR(ALREADY_INITIALIZED, 60), /* 316 Already initialized */ MBED_DEFINE_SYSTEM_ERROR(HARDFAULT_EXCEPTION, 61), /* 317 HardFault exception */ MBED_DEFINE_SYSTEM_ERROR(MEMMANAGE_EXCEPTION, 62), /* 318 MemManage exception */ MBED_DEFINE_SYSTEM_ERROR(BUSFAULT_EXCEPTION, 63), /* 319 BusFault exception */ @@ -780,7 +782,8 @@ typedef enum _mbed_error_code { MBED_DEFINE_SYSTEM_ERROR(BLE_NO_FRAME_INITIALIZED, 65), /* 321 BLE No frame initialized */ MBED_DEFINE_SYSTEM_ERROR(BLE_BACKEND_CREATION_FAILED, 66), /* 322 BLE Backend creation failed */ MBED_DEFINE_SYSTEM_ERROR(BLE_BACKEND_NOT_INITIALIZED, 67), /* 323 BLE Backend not initialized */ - + MBED_DEFINE_SYSTEM_ERROR(ASSERTION_FAILED, 68), /* 324 Assertion Failed */ + //Everytime you add a new system error code, you must update //Error documentation under Handbook to capture the info on //the new error status/codes @@ -868,7 +871,7 @@ typedef struct _mbed_error_ctx { * */ -void error(const char *format, ...); +MBED_NORETURN void error(const char *format, ...) MBED_PRINTF(1, 2); /** * Call this Macro to generate a mbed_error_status_t value for a System error @@ -919,7 +922,6 @@ void error(const char *format, ...); * Callback/Error hook function prototype. Applications needing a callback when an error is reported can use mbed_set_error_hook function * to register a callback/error hook function using the following prototype. When an error happens in the system error handling * implementation will invoke this callback with the mbed_error_status_t reported and the error context at the time of error. - * @param error_status mbed_error_status_t status being reported. * @param error_ctx Error context structure associated with this error. * @return void * @@ -976,8 +978,7 @@ int mbed_get_error_count(void); * @param error_value Value associated with the error status. This would depend on error code/error scenario. * @param filename Name of the source file originating the error( Most callers can pass __FILE__ here ). * @param line_number The line number of the source file originating the error( Most callers can pass __LINE__ here ) . - * @return 0 or MBED_SUCCESS. - * MBED_ERROR_INVALID_ARGUMENT if called with invalid error status/codes + * @return Does not return. * * @code * @@ -987,7 +988,7 @@ int mbed_get_error_count(void); * * @note See MBED_WARNING/MBED_ERROR macros which provides a wrapper on this API */ -mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number); +MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number); /** * Registers an application defined error callback with the error handling system. diff --git a/platform/mbed_interface.h b/platform/mbed_interface.h index 48594916e8..cdfe71746e 100644 --- a/platform/mbed_interface.h +++ b/platform/mbed_interface.h @@ -26,6 +26,7 @@ #include +#include "mbed_toolchain.h" #include "device.h" /* Mbed interface mac address @@ -120,12 +121,15 @@ void mbed_mac_address(char *mac); /** Cause the mbed to flash the BLOD (Blue LEDs Of Death) sequence */ -void mbed_die(void); +MBED_NORETURN void mbed_die(void); /** Print out an error message. This is typically called when * handling a crash. * * @note Synchronization level: Interrupt safe + * @note This uses an internal 128-byte buffer to format the string, + * so the output may be truncated. If you need to write a potentially + * long string, use mbed_error_puts. * * @param format C string that contains data stream to be printed. * Code snippets below show valid format. @@ -135,7 +139,7 @@ void mbed_die(void); * @endcode * */ -void mbed_error_printf(const char *format, ...); +void mbed_error_printf(const char *format, ...) MBED_PRINTF(1, 2); /** Print out an error message. Similar to mbed_error_printf * but uses a va_list. @@ -146,9 +150,29 @@ void mbed_error_printf(const char *format, ...); * @param arg Variable arguments list * */ -void mbed_error_vfprintf(const char *format, va_list arg); +void mbed_error_vprintf(const char *format, va_list arg) MBED_PRINTF(1, 0); + +/** Print out an error message. This is typically called when + * handling a crash. + * + * Unlike mbed_error_printf, there is no limit to the maximum output + * length. Unlike standard puts, but like standard fputs, this does not + * append a '\n' character. + * + * @note Synchronization level: Interrupt safe + * + * @param str C string that contains data stream to be printed. + * + */ +void mbed_error_puts(const char *str); + +/** @deprecated Renamed to mbed_error_vprintf to match functionality */ +MBED_DEPRECATED_SINCE("mbed-os-5.11", + "Renamed to mbed_error_vprintf to match functionality.") +void mbed_error_vfprintf(const char *format, va_list arg) MBED_PRINTF(1, 0); /** @}*/ + #ifdef __cplusplus } #endif diff --git a/platform/mbed_lib.json b/platform/mbed_lib.json index 6c9a03988c..5a3c0ef979 100644 --- a/platform/mbed_lib.json +++ b/platform/mbed_lib.json @@ -68,7 +68,7 @@ "memory-tracing-enabled": { "macro_name": "MBED_MEM_TRACING_ENABLED", "help": "Enable tracing of each memory call by invoking a callback on each memory operation. See mbed_mem_trace.h in the HAL API for more information", - "value": false + "value": null }, "sys-stats-enabled": { "macro_name": "MBED_SYS_STATS_ENABLED", @@ -98,6 +98,10 @@ "error-decode-http-url-str": { "help": "HTTP URL string for ARM Mbed-OS Error Decode microsite", "value": "\"\\nFor more info, visit: https://armmbed.github.io/mbedos-error/?error=0x%08X\"" + }, + "cthunk_count_max": { + "help": "The maximum CThunk objects used at the same time. This must be greater than 0 and less 256", + "value": 8 } }, "target_overrides": { diff --git a/platform/mbed_mem_trace.cpp b/platform/mbed_mem_trace.cpp index 7b7b3aa323..f34453cfd3 100644 --- a/platform/mbed_mem_trace.cpp +++ b/platform/mbed_mem_trace.cpp @@ -28,6 +28,7 @@ /* The callback function that will be called after a traced memory operations finishes. */ static mbed_mem_trace_cb_t mem_trace_cb; +static mbed_mem_trace_cb_t mem_trace_cb_reserve; /* 'trace_lock_count' guards "trace inside trace" situations (for example, the implementation * of realloc() might call malloc() internally, and since malloc() is also traced, this could * result in two calls to the callback function instead of one. */ @@ -46,6 +47,24 @@ void mbed_mem_trace_set_callback(mbed_mem_trace_cb_t cb) mem_trace_cb = cb; } +void mbed_mem_trace_disable() +{ + mbed_mem_trace_lock(); + if (mem_trace_cb) { + mem_trace_cb_reserve = mem_trace_cb; + mem_trace_cb = 0; + } + mbed_mem_trace_unlock(); +} +void mbed_mem_trace_enable() +{ + mbed_mem_trace_lock(); + if (!mem_trace_cb && mem_trace_cb_reserve) { + mem_trace_cb = mem_trace_cb_reserve; + } + mbed_mem_trace_unlock(); +} + void mbed_mem_trace_lock() { mem_trace_mutex->lock(); diff --git a/platform/mbed_mem_trace.h b/platform/mbed_mem_trace.h index 1fe2e99a90..965bf83c80 100644 --- a/platform/mbed_mem_trace.h +++ b/platform/mbed_mem_trace.h @@ -28,12 +28,14 @@ extern "C" { #include #include -/* Operation types for tracer */ +/** + * enum Memory operation types for tracer + */ enum { - MBED_MEM_TRACE_MALLOC, - MBED_MEM_TRACE_REALLOC, - MBED_MEM_TRACE_CALLOC, - MBED_MEM_TRACE_FREE + MBED_MEM_TRACE_MALLOC, /**< Identifier for malloc operation */ + MBED_MEM_TRACE_REALLOC, /**< Identifier for realloc operation */ + MBED_MEM_TRACE_CALLOC, /**< Identifier for calloc operation */ + MBED_MEM_TRACE_FREE /**< Identifier for free operation */ }; /** @@ -72,9 +74,19 @@ typedef void (*mbed_mem_trace_cb_t)(uint8_t op, void *res, void *caller, ...); */ void mbed_mem_trace_set_callback(mbed_mem_trace_cb_t cb); +/** + * Disable the memory trace output by disabling the callback function + */ +void mbed_mem_trace_disable(); + +/** + * Re-enable the memory trace output with the cb in use when disable was called + */ +void mbed_mem_trace_enable(); + /** * Trace lock. - * @note Locking prevent recursive tracing of malloc/free inside relloc/calloc + * @note Locking prevent recursive tracing of malloc/free inside realloc/calloc */ void mbed_mem_trace_lock(); @@ -129,7 +141,7 @@ void mbed_mem_trace_free(void *ptr, void *caller); * * @param op identifies the memory operation ('m' for 'malloc', 'r' for 'realloc', * 'c' for 'calloc' and 'f' for 'free'). - * @param res (base 16) is the result of the memor operation. This is always NULL + * @param res (base 16) is the result of the memory operation. This is always NULL * for 'free', since 'free' doesn't return anything. * @param caller (base 16) is the caller of the memory operation. Note that the value * of 'caller' might be unreliable. diff --git a/platform/mbed_poll.cpp b/platform/mbed_poll.cpp index 868a1b8d06..da9e825d8a 100644 --- a/platform/mbed_poll.cpp +++ b/platform/mbed_poll.cpp @@ -17,7 +17,7 @@ #include "FileHandle.h" #if MBED_CONF_RTOS_PRESENT #include "rtos/Kernel.h" -#include "rtos/Thread.h" +#include "rtos/ThisThread.h" using namespace rtos; #else #include "drivers/Timer.h" @@ -29,7 +29,7 @@ namespace mbed { // timeout -1 forever, or milliseconds int poll(pollfh fhs[], unsigned nfhs, int timeout) { - /** + /* * TODO Proper wake-up mechanism. * In order to correctly detect availability of read/write a FileHandle, we needed * a select or poll mechanisms. We opted for poll as POSIX defines in @@ -83,7 +83,7 @@ int poll(pollfh fhs[], unsigned nfhs, int timeout) #ifdef MBED_CONF_RTOS_PRESENT // TODO - proper blocking // wait for condition variable, wait queue whatever here - rtos::Thread::wait(1); + rtos::ThisThread::sleep_for(1); #endif } return count; diff --git a/platform/mbed_power_mgmt.h b/platform/mbed_power_mgmt.h index 05a54e4e7f..ba0d1bda39 100644 --- a/platform/mbed_power_mgmt.h +++ b/platform/mbed_power_mgmt.h @@ -32,7 +32,8 @@ extern "C" { #endif -/** Sleep manager API +/** + * @defgroup hal_sleep_manager Sleep manager API * The sleep manager provides API to automatically select sleep mode. * * There are two sleep modes: @@ -43,6 +44,17 @@ extern "C" { * are not allowed (=disabled) during the deepsleep. For instance, high frequency * clocks. * + * # Defined behavior + * * The lock is a counter + * * The lock can be locked up to USHRT_MAX - Verified by ::test_lock_eq_ushrt_max + * * The lock has to be equally unlocked as locked - Verified by ::test_lock_eq_ushrt_max + * * The function sleep_manager_lock_deep_sleep_internal() locks the automatic deep mode selection - Verified by ::test_lock_unlock + * * The function sleep_manager_unlock_deep_sleep_internal() unlocks the automatic deep mode selection - Verified by ::test_lock_unlock + * * The function sleep_manager_sleep_auto() chooses the sleep or deep sleep modes based on the lock - Verified by ::test_sleep_auto + * * The function sleep_manager_lock_deep_sleep_internal() is IRQ and thread safe - Verified by ::sleep_manager_multithread_test and ::sleep_manager_irq_test + * * The function sleep_manager_unlock_deep_sleep_internal() is IRQ and thread safe - Verified by ::sleep_manager_multithread_test and ::sleep_manager_irq_test + * * The function sleep_manager_sleep_auto() is IRQ and thread safe + * * Example: * @code * @@ -63,7 +75,19 @@ extern "C" { * return _sensor.start(event, callback); * } * @endcode + * @{ */ + +/** + * @defgroup hal_sleep_manager_tests Sleep manager API tests + * Tests to validate the proper implementation of the sleep manager + * + * To run the sleep manager hal tests use the command: + * + * mbed test -t -m -n tests-mbed_hal-sleep_manager* + * + */ + #ifdef MBED_SLEEP_TRACING_ENABLED void sleep_tracker_lock(const char *const filename, int line); @@ -133,7 +157,7 @@ bool sleep_manager_can_deep_sleep(void); */ bool sleep_manager_can_deep_sleep_test_check(void); -/** Enter auto selected sleep mode. It chooses the sleep or deeepsleep modes based +/** Enter auto selected sleep mode. It chooses the sleep or deepsleep modes based * on the deepsleep locking counter * * This function is IRQ and thread safe @@ -169,9 +193,9 @@ void sleep_manager_sleep_auto(void); static inline void sleep(void) { #if DEVICE_SLEEP -#if (MBED_CONF_RTOS_PRESENT == 0) || (DEVICE_STCLK_OFF_DURING_SLEEP == 0) || defined(MBED_TICKLESS) +#if (MBED_CONF_RTOS_PRESENT == 0) || (DEVICE_SYSTICK_CLK_OFF_DURING_SLEEP == 0) || defined(MBED_TICKLESS) sleep_manager_sleep_auto(); -#endif /* (MBED_CONF_RTOS_PRESENT == 0) || (DEVICE_STCLK_OFF_DURING_SLEEP == 0) || defined(MBED_TICKLESS) */ +#endif /* (MBED_CONF_RTOS_PRESENT == 0) || (DEVICE_SYSTICK_CLK_OFF_DURING_SLEEP == 0) || defined(MBED_TICKLESS) */ #endif /* DEVICE_SLEEP */ } @@ -203,15 +227,6 @@ static inline void deepsleep(void) #endif /* DEVICE_SLEEP */ } -/** Resets the processor and most of the sub-system - * - * @note Does not affect the debug sub-system - */ -static inline void system_reset(void) -{ - NVIC_SystemReset(); -} - /** Provides the time spent in sleep mode since boot. * * @return Time spent in sleep @@ -240,6 +255,17 @@ us_timestamp_t mbed_time_idle(void); */ us_timestamp_t mbed_uptime(void); +/** @}*/ + +/** Resets the processor and most of the sub-system + * + * @note Does not affect the debug sub-system + */ +MBED_NORETURN static inline void system_reset(void) +{ + NVIC_SystemReset(); +} + #ifdef __cplusplus } #endif diff --git a/platform/mbed_retarget.cpp b/platform/mbed_retarget.cpp index ae17a65a5c..7e8ed8725d 100644 --- a/platform/mbed_retarget.cpp +++ b/platform/mbed_retarget.cpp @@ -1250,6 +1250,8 @@ extern "C" void exit(int return_code) #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT fflush(stdout); fflush(stderr); + fsync(STDOUT_FILENO); + fsync(STDERR_FILENO); #endif #endif @@ -1345,38 +1347,6 @@ void mbed_set_unbuffered_stream(std::FILE *_file) #endif } -int mbed_getc(std::FILE *_file) -{ -#if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000) - /*This is only valid for unbuffered streams*/ - int res = std::fgetc(_file); - if (res >= 0) { - _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ - _file->_Rend = _file->_Wend; - _file->_Next = _file->_Wend; - } - return res; -#else - return std::fgetc(_file); -#endif -} - -char *mbed_gets(char *s, int size, std::FILE *_file) -{ -#if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000) - /*This is only valid for unbuffered streams*/ - char *str = fgets(s, size, _file); - if (str != NULL) { - _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ - _file->_Rend = _file->_Wend; - _file->_Next = _file->_Wend; - } - return str; -#else - return std::fgets(s, size, _file); -#endif -} - } // namespace mbed #if defined (__ICCARM__) @@ -1469,7 +1439,7 @@ extern "C" void __cxa_guard_abort(int *guard_object_p) #endif -#if MBED_MEM_TRACING_ENABLED && (defined(__CC_ARM) || defined(__ICCARM__) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))) +#if defined(MBED_MEM_TRACING_ENABLED) && (defined(__CC_ARM) || defined(__ICCARM__) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))) // If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp // provide the implementation for these. Note: this needs to use the wrappers @@ -1515,7 +1485,7 @@ void operator delete[](void *ptr) free_wrapper(ptr, MBED_CALLER_ADDR()); } -#elif MBED_MEM_TRACING_ENABLED && defined(__GNUC__) +#elif defined(MBED_MEM_TRACING_ENABLED) && defined(__GNUC__) #include diff --git a/platform/mbed_rtc_time.cpp b/platform/mbed_rtc_time.cpp index fbc8db2b1b..7ec6171b4d 100644 --- a/platform/mbed_rtc_time.cpp +++ b/platform/mbed_rtc_time.cpp @@ -57,6 +57,7 @@ static time_t _rtc_lpticker_read(void) static void _rtc_lpticker_write(time_t t) { + _rtc_lp_timer->reset(); _rtc_lp_base = t; } diff --git a/platform/mbed_rtc_time.h b/platform/mbed_rtc_time.h index ee3e7ec7a1..f1b04c3d68 100644 --- a/platform/mbed_rtc_time.h +++ b/platform/mbed_rtc_time.h @@ -31,7 +31,7 @@ extern "C" { * * Provides mechanisms to set and read the current time, based * on the microcontroller Real-Time Clock (RTC), plus some - * standard C manipulation and formating functions. + * standard C manipulation and formatting functions. * * Example: * @code @@ -40,10 +40,10 @@ extern "C" { * int main() { * set_time(1256729737); // Set RTC time to Wed, 28 Oct 2009 11:35:37 * - * while(1) { + * while (true) { * time_t seconds = time(NULL); * - * printf("Time as seconds since January 1, 1970 = %d\n", seconds); + * printf("Time as seconds since January 1, 1970 = %u\n", (unsigned int)seconds); * * printf("Time as a basic string = %s", ctime(&seconds)); * @@ -59,7 +59,7 @@ extern "C" { /** Set the current time * - * Initialises and sets the time of the microcontroller Real-Time Clock (RTC) + * Initializes and sets the time of the microcontroller Real-Time Clock (RTC) * to the time represented by the number of seconds since January 1, 1970 * (the UNIX timestamp). * @@ -84,8 +84,8 @@ void set_time(time_t t); * * @param read_rtc pointer to function which returns current UNIX timestamp * @param write_rtc pointer to function which sets current UNIX timestamp, can be NULL - * @param init_rtc pointer to funtion which initializes RTC, can be NULL - * @param isenabled_rtc pointer to function wich returns if the rtc is enabled, can be NULL + * @param init_rtc pointer to function which initializes RTC, can be NULL + * @param isenabled_rtc pointer to function which returns if the RTC is enabled, can be NULL */ void attach_rtc(time_t (*read_rtc)(void), void (*write_rtc)(time_t), void (*init_rtc)(void), int (*isenabled_rtc)(void)); diff --git a/platform/mbed_stats.h b/platform/mbed_stats.h index 4532041379..fb975f5f29 100644 --- a/platform/mbed_stats.h +++ b/platform/mbed_stats.h @@ -42,16 +42,17 @@ extern "C" { * struct mbed_stats_heap_t definition */ typedef struct { - uint32_t current_size; /**< Bytes allocated currently. */ - uint32_t max_size; /**< Max bytes allocated at a given time. */ - uint32_t total_size; /**< Cumulative sum of bytes ever allocated. */ - uint32_t reserved_size; /**< Current number of bytes allocated for the heap. */ - uint32_t alloc_cnt; /**< Current number of allocations. */ - uint32_t alloc_fail_cnt; /**< Number of failed allocations. */ + uint32_t current_size; /**< Bytes currently allocated on the heap */ + uint32_t max_size; /**< Maximum bytes allocated on the heap at one time since reset */ + uint32_t total_size; /**< Cumulative sum of bytes allocated on the heap that have not been freed */ + uint32_t reserved_size; /**< Current number of bytes reserved for the heap */ + uint32_t alloc_cnt; /**< Current number of allocations that have not been freed since reset */ + uint32_t alloc_fail_cnt; /**< Number of failed allocations since reset */ + uint32_t overhead_size; /**< Number of bytes used to store heap statistics. This overhead takes up space on the heap, reducing the available heap space */ } mbed_stats_heap_t; /** - * Fill the passed in heap stat structure with heap stats. + * Fill the passed in heap stat structure with the heap statistics. * * @param stats A pointer to the mbed_stats_heap_t structure to fill */ @@ -61,14 +62,14 @@ void mbed_stats_heap_get(mbed_stats_heap_t *stats); * struct mbed_stats_stack_t definition */ typedef struct { - uint32_t thread_id; /**< Identifier for thread that owns the stack or 0 if multiple threads. */ - uint32_t max_size; /**< Maximum number of bytes used on the stack. */ - uint32_t reserved_size; /**< Current number of bytes allocated for the stack. */ - uint32_t stack_cnt; /**< Number of stacks stats accumulated in the structure. */ + uint32_t thread_id; /**< Identifier for the thread that owns the stack or 0 if representing accumulated statistics */ + uint32_t max_size; /**< Maximum number of bytes used on the stack since the thread was started */ + uint32_t reserved_size; /**< Current number of bytes reserved for the stack */ + uint32_t stack_cnt; /**< The number of stacks represented in the accumulated statistics or 1 if representing a single stack */ } mbed_stats_stack_t; /** - * Fill the passed in structure with stack stats accumulated for all threads. The thread_id will be 0 + * Fill the passed in structure with stack statistics accumulated for all threads. The thread_id will be 0 * and stack_cnt will represent number of threads. * * @param stats A pointer to the mbed_stats_stack_t structure to fill @@ -76,12 +77,13 @@ typedef struct { void mbed_stats_stack_get(mbed_stats_stack_t *stats); /** - * Fill the passed array of stat structures with the stack stats for each available thread. + * Fill the passed array of structures with the stack statistics for each available thread. * * @param stats A pointer to an array of mbed_stats_stack_t structures to fill * @param count The number of mbed_stats_stack_t structures in the provided array - * @return The number of mbed_stats_stack_t structures that have been filled, - * this is equal to the number of stacks on the system. + * @return The number of mbed_stats_stack_t structures that have been filled. + * If the number of stacks on the system is less than or equal to count, it will equal the number of stacks on the system. + * If the number of stacks on the system is greater than count, it will equal count. */ size_t mbed_stats_stack_get_each(mbed_stats_stack_t *stats, size_t count); @@ -89,10 +91,10 @@ size_t mbed_stats_stack_get_each(mbed_stats_stack_t *stats, size_t count); * struct mbed_stats_cpu_t definition */ typedef struct { - us_timestamp_t uptime; /**< Time since system is up and running */ - us_timestamp_t idle_time; /**< Time spent in idle thread since system is up and running */ - us_timestamp_t sleep_time; /**< Time spent in sleep since system is up and running */ - us_timestamp_t deep_sleep_time; /**< Time spent in deep sleep since system is up and running */ + us_timestamp_t uptime; /**< Time since the system has started */ + us_timestamp_t idle_time; /**< Time spent in the idle thread since the system has started */ + us_timestamp_t sleep_time; /**< Time spent in sleep since the system has started */ + us_timestamp_t deep_sleep_time; /**< Time spent in deep sleep since the system has started */ } mbed_stats_cpu_t; /** @@ -106,21 +108,22 @@ void mbed_stats_cpu_get(mbed_stats_cpu_t *stats); * struct mbed_stats_thread_t definition */ typedef struct { - uint32_t id; /**< Thread Object Identifier */ - uint32_t state; /**< Thread Object State */ - uint32_t priority; /**< Thread Priority */ - uint32_t stack_size; /**< Thread Stack Size */ - uint32_t stack_space; /**< Thread remaining stack size */ - const char *name; /**< Thread Object name */ + uint32_t id; /**< ID of the thread */ + uint32_t state; /**< State of the thread */ + uint32_t priority; /**< Priority of the thread (higher number indicates higher priority) */ + uint32_t stack_size; /**< Current number of bytes reserved for the stack */ + uint32_t stack_space; /**< Current number of free bytes remaining on the stack */ + const char *name; /**< Name of the thread */ } mbed_stats_thread_t; /** - * Fill the passed array of stat structures with the thread stats for each available thread. + * Fill the passed array of stat structures with the thread statistics for each available thread. * * @param stats A pointer to an array of mbed_stats_thread_t structures to fill * @param count The number of mbed_stats_thread_t structures in the provided array - * @return The number of mbed_stats_thread_t structures that have been filled, - * this is equal to the number of threads on the system. + * @return The number of mbed_stats_thread_t structures that have been filled. + * If the number of threads on the system is less than or equal to count, it will equal the number of threads on the system. + * If the number of threads on the system is greater than count, it will equal count. */ size_t mbed_stats_thread_get_each(mbed_stats_thread_t *stats, size_t count); @@ -137,14 +140,14 @@ typedef enum { * struct mbed_stats_sys_t definition */ typedef struct { - uint32_t os_version; /**< Mbed OS Version (Release only) */ - uint32_t cpu_id; /**< CPUID Register data (Cortex-M only supported) */ + uint32_t os_version; /**< Mbed OS version (populated only for tagged releases) */ + uint32_t cpu_id; /**< CPUID register data (Cortex-M only supported) */ mbed_compiler_id_t compiler_id; /**< Compiler ID \ref mbed_compiler_id_t */ uint32_t compiler_version; /**< Compiler version */ } mbed_stats_sys_t; /** - * Fill the passed in sys stat structure with system stats. + * Fill the passed in system stat structure with system statistics. * * @param stats A pointer to the mbed_stats_sys_t structure to fill */ diff --git a/platform/mbed_toolchain.h b/platform/mbed_toolchain.h index d5864295da..fba7d32bed 100644 --- a/platform/mbed_toolchain.h +++ b/platform/mbed_toolchain.h @@ -144,6 +144,8 @@ #ifndef MBED_WEAK #if defined(__ICCARM__) #define MBED_WEAK __weak +#elif defined(__MINGW32__) +#define MBED_WEAK #else #define MBED_WEAK __attribute__((weak)) #endif @@ -235,8 +237,8 @@ /** MBED_UNREACHABLE * An unreachable statement. If the statement is reached, - * behaviour is undefined. Useful in situations where the compiler - * cannot deduce the unreachability of code. + * behavior is undefined. Useful in situations where the compiler + * cannot deduce if the code is unreachable. * * @code * #include "mbed_toolchain.h" @@ -354,7 +356,7 @@ #ifndef MBED_PRINTF_METHOD #if defined(__GNUC__) || defined(__CC_ARM) -#define MBED_PRINTF_METHOD(format_idx, first_param_idx) __attribute__ ((__format__(__printf__, format_idx+1, first_param_idx+1))) +#define MBED_PRINTF_METHOD(format_idx, first_param_idx) __attribute__ ((__format__(__printf__, format_idx+1, first_param_idx == 0 ? 0 : first_param_idx+1))) #else #define MBED_PRINTF_METHOD(format_idx, first_param_idx) #endif @@ -370,7 +372,7 @@ #ifndef MBED_SCANF_METHOD #if defined(__GNUC__) || defined(__CC_ARM) -#define MBED_SCANF_METHOD(format_idx, first_param_idx) __attribute__ ((__format__(__scanf__, format_idx+1, first_param_idx+1))) +#define MBED_SCANF_METHOD(format_idx, first_param_idx) __attribute__ ((__format__(__scanf__, format_idx+1, first_param_idx == 0 ? 0 : first_param_idx+1))) #else #define MBED_SCANF_METHOD(format_idx, first_param_idx) #endif diff --git a/platform/mbed_wait_api.h b/platform/mbed_wait_api.h index 3a458ac155..e97400f46a 100644 --- a/platform/mbed_wait_api.h +++ b/platform/mbed_wait_api.h @@ -57,7 +57,7 @@ extern "C" { * @note * If the RTOS is present, this function always spins to get the exact number of microseconds, * which potentially affects power (such as preventing deep sleep) and multithread performance. - * You can avoid it by using Thread::wait(). + * You can avoid it by using ThisThread::sleep_for(). */ void wait(float s); @@ -68,7 +68,7 @@ void wait(float s); * @note * If the RTOS is present, this function always spins to get the exact number of microseconds, * which potentially affects power (such as preventing deep sleep) and multithread performance. - * You can avoid it by using Thread::wait(). + * You can avoid it by using ThisThread::sleep_for(). */ void wait_ms(int ms); diff --git a/platform/mbed_wait_api_rtos.cpp b/platform/mbed_wait_api_rtos.cpp index f24f58cbdd..c44cdb0acd 100644 --- a/platform/mbed_wait_api_rtos.cpp +++ b/platform/mbed_wait_api_rtos.cpp @@ -20,7 +20,7 @@ #include "platform/mbed_wait_api.h" #include "hal/us_ticker_api.h" -#include "rtos/rtos.h" +#include "rtos/ThisThread.h" #include "platform/mbed_critical.h" #include "platform/mbed_power_mgmt.h" @@ -42,7 +42,7 @@ void wait_us(int us) if ((us >= 1000) && core_util_are_interrupts_enabled()) { // Use the RTOS to wait for millisecond delays if possible sleep_manager_lock_deep_sleep(); - Thread::wait((uint32_t)us / 1000); + rtos::ThisThread::sleep_for((uint32_t)us / 1000); sleep_manager_unlock_deep_sleep(); } // Use busy waiting for sub-millisecond delays, or for the whole diff --git a/requirements.txt b/requirements.txt index 3f6d5662d8..49d67828bf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,20 +1,21 @@ -colorama>=0.3.3 -PySerial>=2.7 -PrettyTable>=0.7.2 -Jinja2>=2.7.3 -IntelHex>=1.3 -junit-xml -pyYAML -requests -mbed-ls>=1.5.1,==1.* -mbed-host-tests>=1.1.2 -mbed-greentea>=0.2.24 -beautifulsoup4>=4 -fuzzywuzzy>=0.11 -pyelftools>=0.24 -jsonschema>=2.6 -future>=0.16.0 -six>=1.11.0 +colorama==0.3.9 +pyserial>=3,<=3.4 +prettytable==0.7.2 +Jinja2>=2.7.3,<=2.10 +intelhex>=1.3,<=2.2.1 +junit-xml==1.8 +pyYAML==3.13 +urllib3[secure]==1.23 +requests>=2.20,<2.21 +mbed-ls>=1.5.1,<1.7 +mbed-host-tests>=1.1.2,<=1.5 +mbed-greentea>=0.2.24,<=1.5 +beautifulsoup4>=4,<=4.6.3 +fuzzywuzzy>=0.11,<=0.17 +pyelftools>=0.24,<=0.25 +jsonschema==2.6.0 +future==0.16.0 +six==1.11.0 git+https://github.com/armmbed/manifest-tool.git@v1.4.6 mbed-cloud-sdk==2.0.1 -icetea>=1.0.2,<2 +icetea>=1.0.2,<1.1 diff --git a/rtos/ConditionVariable.cpp b/rtos/ConditionVariable.cpp index b54fe3a126..edc6b19248 100644 --- a/rtos/ConditionVariable.cpp +++ b/rtos/ConditionVariable.cpp @@ -21,7 +21,7 @@ */ #include "rtos/ConditionVariable.h" #include "rtos/Kernel.h" -#include "rtos/Thread.h" +#include "rtos/ThisThread.h" #include "mbed_error.h" #include "mbed_assert.h" @@ -46,7 +46,7 @@ void ConditionVariable::wait() bool ConditionVariable::wait_for(uint32_t millisec) { Waiter current_thread; - MBED_ASSERT(_mutex.get_owner() == Thread::gettid()); + MBED_ASSERT(_mutex.get_owner() == ThisThread::get_id()); MBED_ASSERT(_mutex._count == 1); _add_wait_list(&_wait_list, ¤t_thread); @@ -84,7 +84,7 @@ bool ConditionVariable::wait_until(uint64_t millisec) void ConditionVariable::notify_one() { - MBED_ASSERT(_mutex.get_owner() == Thread::gettid()); + MBED_ASSERT(_mutex.get_owner() == ThisThread::get_id()); if (_wait_list != NULL) { _wait_list->sem.release(); _remove_wait_list(&_wait_list, _wait_list); @@ -93,7 +93,7 @@ void ConditionVariable::notify_one() void ConditionVariable::notify_all() { - MBED_ASSERT(_mutex.get_owner() == Thread::gettid()); + MBED_ASSERT(_mutex.get_owner() == ThisThread::get_id()); while (_wait_list != NULL) { _wait_list->sem.release(); _remove_wait_list(&_wait_list, _wait_list); diff --git a/rtos/ConditionVariable.h b/rtos/ConditionVariable.h index 1a1c4576ea..8581b78327 100644 --- a/rtos/ConditionVariable.h +++ b/rtos/ConditionVariable.h @@ -1,5 +1,5 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017-2017 ARM Limited +/* Mbed Microcontroller Library + * Copyright (c) 2017-2018 ARM Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,108 +35,147 @@ namespace rtos { struct Waiter; -/** This class provides a safe way to wait for or send notifications of condition changes +/** The ConditionVariable class is a synchronization primitive that allows + * threads to wait until a particular condition occurs. * - * This class is used in conjunction with a mutex to safely wait for or - * notify waiters of condition changes to a resource accessible by multiple + * Use the condition variable in conjunction with a mutex to safely wait for + * or notify waiters of condition changes to a resource accessible by multiple * threads. * - * # Defined behavior - * - All threads waiting on the condition variable wake when - * ConditionVariable::notify_all is called. - * - If one or more threads are waiting on the condition variable at least - * one of them wakes when ConditionVariable::notify is called. + * The thread that intends to wait on a ConditionVariable must: + * - Acquire a lock on a mutex. + * - Execute `wait`, `wait_for` or `wait_until`. While the thread is waiting, + * the mutex is unlocked. + * - When the condition variable has been notified, or in the case of `wait_for` + * and `wait_until` the timeout expires, the thread is awakened. * - * # Undefined behavior - * - The thread which is unblocked on ConditionVariable::notify_one is - * undefined if there are multiple waiters. - * - The order which in which waiting threads acquire the condition variable's - * mutex after ConditionVariable::notify_all is called is undefined. - * - When ConditionVariable::notify_one or ConditionVariable::notify_all is - * called and there are one or more waiters and one or more threads attempting - * to acquire the condition variable's mutex the order in which the mutex is - * acquired is undefined. - * - The behavior of ConditionVariable::wait and ConditionVariable::wait_for + * The thread that intends to notify a ConditionVariable must: + * - Acquire a lock on the mutex used to construct the condition variable. + * - Execute `notify_one` or `notify_all` on the condition variable. + * + * All threads waiting on the condition variable wake when + * `ConditionVariable::notify_all` is called. + * At least one thread waiting on the condition variable wakes + * when `ConditionVariable::notify_one` is called. + * + * While a thread is waiting for notification of a + * ConditionVariable, it releases the lock held on the mutex. + * The ConditionVariable reacquires the mutex lock before exiting the wait + * function. + * + * #### Unspecified behavior + * - The thread that is unblocked on `ConditionVariable::notify_one` is + * unspecified if there are multiple waiters. + * - When `ConditionVariable::notify_one` or `ConditionVariable::notify_all` is + * called and there are one or more waiters, and one or more threads + * attempting to acquire the condition variable's mutex, the order in which the mutex is + * acquired is unspecified. + * - Spurious notifications (not triggered by the application) can occur. + * + * #### Undefined behavior + * - Calling wait if the mutex is not locked by the current thread is undefined + * behavior. + * - The order in which waiting threads acquire the condition variable's + * mutex after `ConditionVariable::notify_all` is called is undefined. + * - The behavior of `ConditionVariable::wait` and `ConditionVariable::wait_for` * is undefined if the condition variable's mutex is locked more than once by * the calling thread. - * - Spurious notifications (not triggered by the application) can occur - * and it is not defined when these occur. * * @note Synchronization level: Thread safe * * Example: + * * @code * #include "mbed.h" * * Mutex mutex; - * ConditionVariable cond(mutex); + * ConditionVariable cv(mutex); * - * // These variables are protected by locking mutex - * uint32_t count = 0; + * // These variables are protected by locking the mutex. + * uint32_t work_count = 0; * bool done = false; * * void worker_thread() * { - * mutex.lock(); - * do { - * printf("Worker: Count %lu\r\n", count); + * // Acquire lock on mutex before accessing protected variables and waiting. + * mutex.lock(); * - * // Wait for a condition to change - * cond.wait(); + * while (done == false) { + * printf("Worker thread: Count: %lu\r\n", work_count); * - * } while (!done); - * printf("Worker: Exiting\r\n"); - * mutex.unlock(); + * // Wait for main thread to notify the condition variable. + * printf("Worker thread: Waiting\r\n"); + * cv.wait(); + * } + * + * printf("Worker: Exiting\r\n"); + * + * // The condition variable acquires the lock when exiting the `wait` function. + * // Unlock mutex when exiting the thread. + * mutex.unlock(); * } * - * int main() { - * Thread thread; - * thread.start(worker_thread); - * - * for (int i = 0; i < 5; i++) { - * - * mutex.lock(); - * // Change count and notify waiters of this - * count++; - * printf("Main: Set count to %lu\r\n", count); - * cond.notify_all(); - * mutex.unlock(); - * - * wait(1.0); - * } + * int main() + * { + * Thread thread; + * thread.start(worker_thread); * + * for (int i = 0; i < 5; i++) { + * // Acquire lock on mutex before modifying variables and notifying. * mutex.lock(); - * // Change done and notify waiters of this - * done = true; - * printf("Main: Set done\r\n"); - * cond.notify_all(); + * + * // Change count and notify waiters. + * work_count++; + * printf("Main thread: Set count to: %lu\r\n", work_count); + * printf("Main thread: Notifying worker thread\r\n"); + * cv.notify_all(); + * + * // Mutex must be unlocked before the worker thread can acquire it. * mutex.unlock(); * - * thread.join(); + * wait(1.0); + * } + * + * // Change done and notify waiters of this. + * mutex.lock(); + * done = true; + * cv.notify_all(); + * mutex.unlock(); + * + * thread.join(); + * + * printf("Main: Exiting\r\n"); * } * @endcode */ + class ConditionVariable : private mbed::NonCopyable { public: - /** Create and Initialize a ConditionVariable object + /** Create and initialize a ConditionVariable object. * * @note You cannot call this function from ISR context. */ ConditionVariable(Mutex &mutex); - /** Wait for a notification + /** Wait for a notification. * - * Wait until a notification occurs. + * Wait causes the current thread to block until the condition variable + * receives a notification from another thread. * * @note - The thread calling this function must be the owner of the - * ConditionVariable's mutex and it must be locked exactly once - * @note - Spurious notifications can occur so the caller of this API - * should check to make sure the condition they are waiting on has - * been met + * ConditionVariable's mutex, and it must be locked exactly once. + * + * @note - Spurious notifications can occur, so the caller of this API + * should check to make sure the condition the caller is waiting on has + * been met. + * + * @note - The current thread releases the lock while inside the wait + * function and reacquires it upon exiting the function. * * Example: * @code * mutex.lock(); + * * while (!condition_met) { * cond.wait(); * } @@ -150,16 +189,24 @@ public: */ void wait(); - /** Wait for a notification until specified time + /** Wait for a notification until the specified time. * - * @param millisec absolute end time referenced to Kernel::get_ms_count() - * @return true if a timeout occurred, false otherwise. + * Wait until causes the current thread to block until the condition + * variable is notified, or a specific time given by millisec parameter is + * reached. + * + * @param millisec Absolute end time referenced to `Kernel::get_ms_count()` + * @return `true` if a timeout occurred, `false` otherwise. * * @note - The thread calling this function must be the owner of the - * ConditionVariable's mutex and it must be locked exactly once - * @note - Spurious notifications can occur so the caller of this API - * should check to make sure the condition they are waiting on has - * been met + * ConditionVariable's mutex, and it must be locked exactly once. + * + * @note - Spurious notifications can occur, so the caller of this API + * should check to make sure the condition the caller is waiting on has + * been met. + * + * @note - The current thread releases the lock while inside the wait + * function and reacquires it upon exiting the function. * * Example: * @code @@ -183,16 +230,24 @@ public: */ bool wait_until(uint64_t millisec); - /** Wait for a notification or timeout + /** Wait for a notification or timeout. * - * @param millisec timeout value or osWaitForever in case of no time-out. - * @return true if a timeout occurred, false otherwise. + * `Wait for` causes the current thread to block until the condition + * variable receives a notification from another thread, or the timeout + * specified by the millisec parameter is reached. + * + * @param millisec Timeout value or osWaitForever in case of no timeout. + * @return `true` if a timeout occurred, `false` otherwise. * * @note - The thread calling this function must be the owner of the - * ConditionVariable's mutex and it must be locked exactly once - * @note - Spurious notifications can occur so the caller of this API - * should check to make sure the condition they are waiting on has - * been met + * ConditionVariable's mutex, and it must be locked exactly once. + * + * @note - Spurious notifications can occur, so the caller of this API + * should check to make sure the condition the caller is waiting on has + * been met. + * + * @note - The current thread releases the lock while inside the wait + * function and reacquire it upon exiting the function. * * Example: * @code @@ -218,7 +273,14 @@ public: /** Notify one waiter on this condition variable that a condition changed. * - * @note - The thread calling this function must be the owner of the ConditionVariable's mutex + * This function unblocks one of the threads waiting for the condition + * variable. + * + * @note - The thread calling this function must be the owner of the + * ConditionVariable's mutex. + * + * @note - The thread that is unblocked on ConditionVariable::notify_one is + * undefined if there are multiple waiters. * * @note You cannot call this function from ISR context. */ @@ -226,18 +288,27 @@ public: /** Notify all waiters on this condition variable that a condition changed. * - * @note - The thread calling this function must be the owner of the ConditionVariable's mutex + * This function unblocks all of the threads waiting for the condition + * variable. + * + * @note - The thread calling this function must be the owner of the + * ConditionVariable's mutex. + * + * @note - If there are one or more waiters and one or more threads + * attempting to acquire the condition variable's mutex the order in which + * the mutex is acquired is undefined. * * @note You cannot call this function from ISR context. */ void notify_all(); - /** ConditionVariable destructor + /** ConditionVariable destructor. * * @note You cannot call this function from ISR context. */ ~ConditionVariable(); +#if !defined(DOXYGEN_ONLY) protected: struct Waiter { Waiter(); @@ -251,6 +322,7 @@ protected: static void _remove_wait_list(Waiter **wait_list, Waiter *waiter); Mutex &_mutex; Waiter *_wait_list; +#endif // !defined(DOXYGEN_ONLY) }; } diff --git a/rtos/EventFlags.h b/rtos/EventFlags.h index 0571ec7b85..a448807459 100644 --- a/rtos/EventFlags.h +++ b/rtos/EventFlags.h @@ -36,23 +36,25 @@ namespace rtos { * \defgroup rtos_EventFlags EventFlags class * @{ */ - -/** The EventFlags class is used to signal or wait for an arbitrary event or events. - @note - EventFlags support 31 flags so the MSB flag is ignored, it is used to return an error code (@a osFlagsError) + +/** The EventFlags class is used to control event flags or wait for event flags other threads control. + @note - Memory considerations: The EventFlags control structures will be created on current thread's stack, both for the mbed OS + EventFlags support 31 flags. The MSB flag is ignored. It is used to return an error code (@a osFlagsError). + + @note + Memory considerations: The EventFlags control structures will be created on the current thread's stack, both for the Mbed OS and underlying RTOS objects (static or dynamic RTOS memory pools are not being used). */ class EventFlags : private mbed::NonCopyable { public: - /** Create and Initialize an EventFlags object + /** Create and initialize an EventFlags object. * * @note You cannot call this function from ISR context. */ EventFlags(); - /** Create and Initialize a EventFlags object + /** Create and initialize an EventFlags object. @param name name to be used for this EventFlags. It has to stay allocated for the lifetime of the thread. @@ -60,50 +62,50 @@ public: */ EventFlags(const char *name); - /** Set the specified Event Flags. - @param flags specifies the flags that shall be set. - @return event flags after setting or error code if highest bit set (@a osFlagsError). + /** Set the specified event flags. + @param flags the flags that will be set. + @return event flags after setting or error code if highest bit set (see @a osFlagsError for details). @note This function may be called from ISR context. */ uint32_t set(uint32_t flags); - /** Clear the specified Event Flags. - @param flags specifies the flags that shall be cleared. (default: 0x7fffffff - all flags) - @return event flags before clearing or error code if highest bit set (@a osFlagsError). + /** Clear the specified event flags. + @param flags the flags that will be cleared (default: 0x7fffffff -- all flags). + @return event flags before clearing or error code if highest bit set (see @a osFlagsError for details). @note You may call this function from ISR context. */ uint32_t clear(uint32_t flags = 0x7fffffff); - /** Get the currently set Event Flags. - @return set event flags. + /** Get the currently set event flags. + @return current event flags. @note You may call this function from ISR context. */ uint32_t get() const; /** Wait for all of the specified event flags to become signaled. - @param flags specifies the flags to wait for. - @param timeout timeout value or 0 in case of no time-out. (default: osWaitForever) - @param clear specifies wether to clear the flags after waiting for them. (default: true) - @return event flags before clearing or error code if highest bit set (@a osFlagsError). + @param flags the flags to wait for (default: 0 -- no flags). + @param timeout timeout value or 0 in case of no time-out (default: osWaitForever). + @param clear clear specified event flags after waiting for them (default: true). + @return event flags before clearing or error code if highest bit set (see @a osFlagsError for details). @note You may call this function from ISR context if the timeout parameter is set to 0. */ uint32_t wait_all(uint32_t flags = 0, uint32_t timeout = osWaitForever, bool clear = true); /** Wait for any of the specified event flags to become signaled. - @param flags specifies the flags to wait for. (default: 0) - @param timeout timeout value or 0 in case of no time-out. (default: osWaitForever) - @param clear specifies wether to clear the flags after waiting for them. (default: true) - @return event flags before clearing or error code if highest bit set (@a osFlagsError). + @param flags the flags to wait for (default: 0 -- no flags). + @param timeout timeout value or 0 in case of no timeout (default: osWaitForever). + @param clear clear specified event flags after waiting for them (default: true). + @return event flags before clearing or error code if highest bit set (see @a osFlagsError for details). @note This function may be called from ISR context if the timeout parameter is set to 0. */ uint32_t wait_any(uint32_t flags = 0, uint32_t timeout = osWaitForever, bool clear = true); - /** Event flags destructor + /** EventFlags destructor. @note You cannot call this function from ISR context. */ diff --git a/rtos/Kernel.cpp b/rtos/Kernel.cpp index 1e7e8bc794..a620c0cf1f 100644 --- a/rtos/Kernel.cpp +++ b/rtos/Kernel.cpp @@ -20,11 +20,11 @@ * SOFTWARE. */ +#include "cmsis_os2.h" #include "rtos/Kernel.h" - -#include "mbed.h" #include "rtos/rtos_idle.h" #include "rtos/rtos_handlers.h" +#include "platform/mbed_critical.h" namespace rtos { diff --git a/rtos/Kernel.h b/rtos/Kernel.h index bd123def7f..851dfb688e 100644 --- a/rtos/Kernel.h +++ b/rtos/Kernel.h @@ -33,26 +33,26 @@ namespace rtos { namespace Kernel { /** Read the current RTOS kernel millisecond tick count. - The tick count corresponds to the tick count used by the RTOS for timing - purposes. It increments monotonically from 0 at boot, hence effectively + The tick count corresponds to the tick count the RTOS uses for timing + purposes. It increments monotonically from 0 at boot, so it effectively never wraps. If the underlying RTOS only provides a 32-bit tick count, this method expands it to 64 bits. @return RTOS kernel current tick count - @note mbed OS always uses millisecond RTOS ticks, and this could only wrap - after half a billion years + @note Mbed OS always uses millisecond RTOS ticks, and this could only wrap + after half a billion years. @note You cannot call this function from ISR context. */ uint64_t get_ms_count(); -/** Attach a function to be called by the RTOS idle task - @param fptr pointer to the function to be called +/** Attach a function to be called by the RTOS idle task. + @param fptr pointer to the function to be called @note You may call this function from ISR context. */ void attach_idle_hook(void (*fptr)(void)); -/** Attach a function to be called when a task is killed - @param fptr pointer to the function to be called +/** Attach a function to be called when a thread terminates. + @param fptr pointer to the function to be called @note You may call this function from ISR context. */ diff --git a/rtos/Mail.h b/rtos/Mail.h index c0fdc76fc4..6899d41f4c 100644 --- a/rtos/Mail.h +++ b/rtos/Mail.h @@ -43,80 +43,99 @@ namespace rtos { * @{ */ -/** The Mail class allow to control, send, receive, or wait for mail. - A mail is a memory block that is send to a thread or interrupt service routine. - @tparam T data type of a single message element. - @tparam queue_sz maximum number of messages in queue. - - @note - Memory considerations: The mail data store and control structures will be created on current thread's stack, - both for the mbed OS and underlying RTOS objects (static or dynamic RTOS memory pools are not being used). -*/ +/** The Mail class allows you to control, send, receive or wait for mail. + * A mail is a memory block that is sent to a thread or interrupt service routine (ISR). + * @tparam T Data type of a single mail message element. + * @tparam queue_sz Maximum number of mail messages in queue. + * + * @note + * Memory considerations: The mail data store and control structures are part of this class - they do not (themselves) + * allocate memory on the heap, both for the Mbed OS and underlying RTOS objects (static or dynamic RTOS memory + * pools are not being used). + */ template class Mail : private mbed::NonCopyable > { public: - /** Create and Initialize Mail queue. + /** Create and initialize Mail queue. * * @note You cannot call this function from ISR context. - */ + */ Mail() { }; - /** Check if the mail queue is empty + /** Check if the mail queue is empty. * - * @return True if the mail queue is empty, false if not + * @return State of queue. + * @retval true Mail queue is empty. + * @retval false Mail queue contains mail. * * @note You may call this function from ISR context. */ - bool empty() const { + bool empty() const + { return _queue.empty(); } - /** Check if the mail queue is full + /** Check if the mail queue is full. * - * @return True if the mail queue is full, false if not + * @return State of queue. + * @retval true Mail queue is full. + * @retval false Mail queue is not full. * * @note You may call this function from ISR context. */ - bool full() const { + bool full() const + { return _queue.full(); } - /** Allocate a memory block of type T - @param millisec timeout value or 0 in case of no time-out. (default: 0). - @return pointer to memory block that can be filled with mail or NULL in case error. - - @note You may call this function from ISR context if the millisec parameter is set to 0. - */ + /** Allocate a memory block of type T. + * + * @param millisec Not used. + * + * @return Pointer to memory block that you can fill with mail or NULL in case error. + * + * @note You may call this function from ISR context. + */ T* alloc(uint32_t millisec=0) { return _pool.alloc(); } - /** Allocate a memory block of type T and set memory block to zero. - @param millisec timeout value or 0 in case of no time-out. (default: 0). - @return pointer to memory block that can be filled with mail or NULL in case error. - - @note You may call this function from ISR context if the millisec parameter is set to 0. - */ + /** Allocate a memory block of type T, and set memory block to zero. + * + * @param millisec Not used. + * + * @return Pointer to memory block that you can fill with mail or NULL in case error. + * + * @note You may call this function from ISR context. + */ T* calloc(uint32_t millisec=0) { return _pool.calloc(); } /** Put a mail in the queue. - @param mptr memory block previously allocated with Mail::alloc or Mail::calloc. - @return status code that indicates the execution status of the function. - - @note You may call this function from ISR context. - */ + * + * @param mptr Memory block previously allocated with Mail::alloc or Mail::calloc. + * + * @return Status code that indicates the execution status of the function (osOK on success). + * + * @note You may call this function from ISR context. + */ osStatus put(T *mptr) { return _queue.put(mptr); } - /** Get a mail from a queue. - @param millisec timeout value or 0 in case of no time-out. (default: osWaitForever). - @return event that contains mail information or error code. - - @note You may call this function from ISR context if the millisec parameter is set to 0. - */ + /** Get a mail from the queue. + * + * @param millisec Timeout value or 0 in case of no timeout (default: osWaitForever). + * + * @return Event that contains mail information or error code. + * @retval osEventMessage Message received. + * @retval osOK No mail is available (and no timeout was specified). + * @retval osEventTimeout No mail has arrived during the given timeout period. + * @retval osErrorParameter A parameter is invalid or outside of a permitted range. + * + * @note You may call this function from ISR context if the millisec parameter is set to 0. + */ osEvent get(uint32_t millisec=osWaitForever) { osEvent evt = _queue.get(millisec); if (evt.status == osEventMessage) { @@ -126,11 +145,13 @@ public: } /** Free a memory block from a mail. - @param mptr pointer to the memory block that was obtained with Mail::get. - @return status code that indicates the execution status of the function. - - @note You may call this function from ISR context. - */ + * + * @param mptr Pointer to the memory block that was obtained with Mail::get. + * + * @return Status code that indicates the execution status of the function (osOK on success). + * + * @note You may call this function from ISR context. + */ osStatus free(T *mptr) { return _pool.free(mptr); } diff --git a/rtos/MemoryPool.h b/rtos/MemoryPool.h index bfcd392ecc..37374d5ca9 100644 --- a/rtos/MemoryPool.h +++ b/rtos/MemoryPool.h @@ -37,7 +37,7 @@ namespace rtos { * \defgroup rtos_MemoryPool MemoryPool class * @{ */ - + /** Define and manage fixed-size memory pools of objects of a given type. @tparam T data type of a single object (element). @tparam queue_sz maximum number of objects (elements) in the memory pool. @@ -48,13 +48,14 @@ namespace rtos { */ template class MemoryPool : private mbed::NonCopyable > { - MBED_STATIC_ASSERT(pool_sz > 0, "Invalid memory pool size. Must be greater than 0."); + MBED_STATIC_ASSERT(pool_sz > 0, "Invalid memory pool size. Must be greater than 0."); public: /** Create and Initialize a memory pool. * * @note You cannot call this function from ISR context. */ - MemoryPool() { + MemoryPool() + { memset(_pool_mem, 0, sizeof(_pool_mem)); memset(&_obj_mem, 0, sizeof(_obj_mem)); osMemoryPoolAttr_t attr = { 0 }; @@ -70,7 +71,8 @@ public: * * @note You cannot call this function from ISR context. */ - ~MemoryPool() { + ~MemoryPool() + { osMemoryPoolDelete(_id); } @@ -79,8 +81,9 @@ public: @note You may call this function from ISR context. */ - T* alloc(void) { - return (T*)osMemoryPoolAlloc(_id, 0); + T *alloc(void) + { + return (T *)osMemoryPoolAlloc(_id, 0); } /** Allocate a memory block of type T from a memory pool and set memory block to zero. @@ -88,8 +91,9 @@ public: @note You may call this function from ISR context. */ - T* calloc(void) { - T *item = (T*)osMemoryPoolAlloc(_id, 0); + T *calloc(void) + { + T *item = (T *)osMemoryPoolAlloc(_id, 0); if (item != NULL) { memset(item, 0, sizeof(T)); } @@ -104,8 +108,9 @@ public: @note You may call this function from ISR context. */ - osStatus free(T *block) { - return osMemoryPoolFree(_id, (void*)block); + osStatus free(T *block) + { + return osMemoryPoolFree(_id, (void *)block); } private: diff --git a/rtos/Mutex.h b/rtos/Mutex.h index ea6c8288be..21688bbab5 100644 --- a/rtos/Mutex.h +++ b/rtos/Mutex.h @@ -52,15 +52,15 @@ typedef mbed::ScopedLock ScopedMutexLock; * \defgroup rtos_Mutex Mutex class * @{ */ - + /** The Mutex class is used to synchronize the execution of threads. - This is for example used to protect access to a shared resource. + This is, for example, used to protect access to a shared resource. @note You cannot use member functions of this class in ISR context. If you require Mutex functionality within ISR handler, consider using @a Semaphore. @note - Memory considerations: The mutex control structures will be created on current thread's stack, both for the Mbed OS + Memory considerations: The mutex control structures are created on the current thread's stack, both for the Mbed OS and underlying RTOS objects (static or dynamic RTOS memory pools are not being used). */ class Mutex : private mbed::NonCopyable { @@ -85,16 +85,16 @@ public: @a osOK the mutex has been obtained. @note You cannot call this function from ISR context. - @note This function treats RTOS errors as fatal system errors, so can only return osOK. + @note This function treats RTOS errors as fatal system errors, so it can only return osOK. Use of the return value is deprecated, as the return is expected to become void in the future. */ osStatus lock(void); /** - For backwards compatibility. + Wait until a Mutex becomes available. + @deprecated Do not use this function. This function has been replaced with lock(), trylock() and trylock_for() functions. - Wait until a Mutex becomes available. @param millisec timeout value or 0 in case of no time-out. @return status code that indicates the execution status of the function: @a osOK the mutex has been obtained. @@ -102,7 +102,7 @@ public: @a osErrorResource the mutex could not be obtained when no timeout was specified. @note You cannot call this function from ISR context. - @note This function treats RTOS errors as fatal system errors, so can only return osOK or + @note This function treats RTOS errors as fatal system errors, so it can only return osOK or osErrorResource in case when millisec is 0 or osErrorTimeout if millisec is not osWaitForever. */ MBED_DEPRECATED_SINCE("mbed-os-5.10.0", "Replaced with lock(), trylock() and trylock_for() functions") @@ -147,7 +147,7 @@ public: @a osOK the mutex has been released. @note You cannot call this function from ISR context. - @note This function treats RTOS errors as fatal system errors, so can only return osOK. + @note This function treats RTOS errors as fatal system errors, so it can only return osOK. Use of the return value is deprecated, as the return is expected to become void in the future. */ osStatus unlock(); diff --git a/rtos/Queue.h b/rtos/Queue.h index ef49330c33..5785c9fcd7 100644 --- a/rtos/Queue.h +++ b/rtos/Queue.h @@ -22,14 +22,11 @@ #ifndef QUEUE_H #define QUEUE_H -#include -#include - #include "cmsis_os2.h" +#include "mbed_rtos1_types.h" #include "mbed_rtos_storage.h" #include "platform/mbed_error.h" #include "platform/NonCopyable.h" -#include "mbed_rtos1_types.h" namespace rtos { /** \addtogroup rtos */ @@ -38,89 +35,153 @@ namespace rtos { * \defgroup rtos_Queue Queue class * @{ */ - -/** The Queue class allow to control, send, receive, or wait for messages. - A message can be a integer or pointer value to a certain type T that is send - to a thread or interrupt service routine. - @tparam T data type of a single message element. - @tparam queue_sz maximum number of messages in queue. - @note - Memory considerations: The queue control structures will be created on current thread's stack, both for the mbed OS - and underlying RTOS objects (static or dynamic RTOS memory pools are not being used). -*/ +/** The Queue class represents a collection of objects that are stored first by + * order of priority, and then in first-in, first-out (FIFO) order. + * + * You can use a queue when you need to store data and then access it in the same + * order that it has been stored. The order in which you retrieve the data is in + * order of descending priority. If multiple elements have the same priority, + * they are retrieved in FIFO order. + * + * The object type stored in the queue can be an integer, pointer or a generic + * type given by the template parameter T. + * + * @tparam T Specifies the type of elements stored in the queue. + * @tparam queue_sz Maximum number of messages that you can store in the queue. + * + * @note Memory considerations: The queue control structures are created on the + * current thread's stack, both for the Mbed OS and underlying RTOS + * objects (static or dynamic RTOS memory pools are not being used). + * + */ template class Queue : private mbed::NonCopyable > { public: - /** Create and initialize a message Queue. + /** Create and initialize a message Queue of objects of the parameterized + * type `T` and maximum capacity specified by `queue_sz`. * * @note You cannot call this function from ISR context. */ - Queue() { + Queue() + { memset(&_obj_mem, 0, sizeof(_obj_mem)); osMessageQueueAttr_t attr = { 0 }; attr.mq_mem = _queue_mem; attr.mq_size = sizeof(_queue_mem); attr.cb_mem = &_obj_mem; attr.cb_size = sizeof(_obj_mem); - _id = osMessageQueueNew(queue_sz, sizeof(T*), &attr); + _id = osMessageQueueNew(queue_sz, sizeof(T *), &attr); MBED_ASSERT(_id); } + /** Queue destructor * * @note You cannot call this function from ISR context. */ - ~Queue() { + ~Queue() + { osMessageQueueDelete(_id); } - /** Check if the queue is empty + /** Check if the queue is empty. * * @return True if the queue is empty, false if not * * @note You may call this function from ISR context. */ - bool empty() const { + bool empty() const + { return osMessageQueueGetCount(_id) == 0; } - /** Check if the queue is full + /** Check if the queue is full. * * @return True if the queue is full, false if not * * @note You may call this function from ISR context. */ - bool full() const { + bool full() const + { return osMessageQueueGetSpace(_id) == 0; } - /** Put a message in a Queue. - @param data message pointer. - @param millisec timeout value or 0 in case of no time-out. (default: 0) - @param prio priority value or 0 in case of default. (default: 0) - @return status code that indicates the execution status of the function: - @a osOK the message has been put into the queue. - @a osErrorTimeout the message could not be put into the queue in the given time. - @a osErrorResource not enough space in the queue. - @a osErrorParameter internal error or non-zero timeout specified in an ISR. - - @note You may call this function from ISR context if the millisec parameter is set to 0. - */ + /** Inserts the given element to the end of the queue. + * + * This function puts the message pointed to by `data` into the queue. The + * parameter `prio` is used to sort the message according to their priority + * (higher numbers indicate higher priority) on insertion. + * + * The timeout indicated by the parameter `millisec` specifies how long the + * function blocks waiting for the message to be inserted into the + * queue. + * + * The parameter `millisec` can have the following values: + * - When the timeout is 0 (the default), the function returns instantly. + * - When the timeout is osWaitForever, the function waits for an + * infinite time. + * - For all other values, the function waits for the given number of + * milliseconds. + * + * @param data Pointer to the element to insert into the queue. + * @param millisec Timeout for the operation to be executed, or 0 in case + * of no timeout. (default: 0) + * @param prio Priority of the operation or 0 in case of default. + * (default: 0) + * + * @return Status code that indicates the execution status of the function: + * @a osOK The message has been successfully inserted + * into the queue. + * @a osErrorTimeout The message could not be inserted into the + * queue in the given time. + * @a osErrorResource The message could not be inserted because + * the queue is full. + * @a osErrorParameter Internal error or nonzero timeout specified + * in an ISR. + * + * @note You may call this function from ISR context if the millisec + * parameter is set to 0. + * + */ osStatus put(T* data, uint32_t millisec=0, uint8_t prio=0) { return osMessageQueuePut(_id, &data, prio, millisec); } - /** Get a message or Wait for a message from a Queue. Messages are retrieved in a descending priority order or - first in first out when the priorities are the same. - @param millisec timeout value or 0 in case of no time-out. (default: osWaitForever). - @return event information that includes the message in event.value and the status code in event.status: - @a osEventMessage message received. - @a osOK no message is available in the queue and no timeout was specified. - @a osEventTimeout no message has arrived during the given timeout period. - @a osErrorParameter a parameter is invalid or outside of a permitted range. - - @note You may call this function from ISR context if the millisec parameter is set to 0. - */ + /** Get a message or wait for a message from the queue. + * + * This function retrieves a message from the queue. The message is stored + * in the value field of the returned `osEvent` object. + * + * The timeout specified by the parameter `millisec` specifies how long the + * function waits to retrieve the message from the queue. + * + * The timeout parameter can have the following values: + * - When the timeout is 0, the function returns instantly. + * - When the timeout is osWaitForever (default), the function waits + * infinite time until the message is retrieved. + * - When the timeout is any other value, the function waits for the + * specified time before returning a timeout error. + * + * Messages are retrieved in descending priority order. If two messages + * share the same priority level, they are retrieved in first-in, first-out + * (FIFO) order. + * + * @param millisec Timeout value or 0 in case of no time-out. + * (default: osWaitForever). + * + * @return Event information that includes the message in event. Message + * value and the status code in event.status: + * @a osEventMessage Message successfully received. + * @a osOK No message is available in the queue, and no + * timeout was specified. + * @a osEventTimeout No message was received before a timeout + * event occurred. + * @a osErrorParameter A parameter is invalid or outside of a + * permitted range. + * + * @note You may call this function from ISR context if the millisec + * parameter is set to 0. + */ osEvent get(uint32_t millisec=osWaitForever) { osEvent event; T *data = NULL; @@ -149,12 +210,12 @@ public: private: osMessageQueueId_t _id; - char _queue_mem[queue_sz * (sizeof(T*) + sizeof(mbed_rtos_storage_message_t))]; + char _queue_mem[queue_sz * (sizeof(T *) + sizeof(mbed_rtos_storage_message_t))]; mbed_rtos_storage_msg_queue_t _obj_mem; }; /** @}*/ /** @}*/ -} -#endif +} // namespace rtos +#endif // QUEUE_H diff --git a/rtos/RtosTimer.cpp b/rtos/RtosTimer.cpp index 3e6c19718b..0e3674f627 100644 --- a/rtos/RtosTimer.cpp +++ b/rtos/RtosTimer.cpp @@ -20,33 +20,37 @@ * SOFTWARE. */ #include "rtos/RtosTimer.h" +#include "platform/Callback.h" +#include "platform/mbed_error.h" +#include "platform/mbed_assert.h" #include -#include "mbed.h" -#include "platform/mbed_error.h" - namespace rtos { -void RtosTimer::constructor(mbed::Callback func, os_timer_type type) { +void RtosTimer::constructor(mbed::Callback func, os_timer_type type) +{ _function = func; memset(&_obj_mem, 0, sizeof(_obj_mem)); osTimerAttr_t attr = { 0 }; attr.cb_mem = &_obj_mem; attr.cb_size = sizeof(_obj_mem); - _id = osTimerNew((void (*)(void *))Callback::thunk, type, &_function, &attr); + _id = osTimerNew((void (*)(void *))mbed::Callback::thunk, type, &_function, &attr); MBED_ASSERT(_id); } -osStatus RtosTimer::start(uint32_t millisec) { +osStatus RtosTimer::start(uint32_t millisec) +{ return osTimerStart(_id, millisec); } -osStatus RtosTimer::stop(void) { +osStatus RtosTimer::stop(void) +{ return osTimerStop(_id); } -RtosTimer::~RtosTimer() { +RtosTimer::~RtosTimer() +{ osTimerDelete(_id); } diff --git a/rtos/RtosTimer.h b/rtos/RtosTimer.h index 27e0c5aeee..eb976cd0bd 100644 --- a/rtos/RtosTimer.h +++ b/rtos/RtosTimer.h @@ -37,7 +37,7 @@ namespace rtos { * \defgroup rtos_RtosTimer RtosTimer class * @{ */ - + /** The RtosTimer class allow creating and and controlling of timer functions in the system. A timer function is called when a time period expires whereby both on-shot and periodic timers are possible. A timer can be started, restarted, or stopped. @@ -88,7 +88,7 @@ class RtosTimer : private mbed::NonCopyable { public: /** Create timer. @param func function to be executed by this timer. - @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behaviour. (default: osTimerPeriodic) + @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior. (default: osTimerPeriodic) @param argument argument to the timer call back function. (default: NULL) @deprecated Replaced with RtosTimer(Callback, os_timer_type) @deprecated @@ -97,31 +97,33 @@ public: @note You cannot call this function from ISR context. */ MBED_DEPRECATED_SINCE("mbed-os-5.1", - "Replaced with RtosTimer(Callback, os_timer_type)") + "Replaced with RtosTimer(Callback, os_timer_type)") MBED_DEPRECATED_SINCE("mbed-os-5.2", - "The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details") - RtosTimer(void (*func)(void const *argument), os_timer_type type=osTimerPeriodic, void *argument=NULL) { + "The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details") + RtosTimer(void (*func)(void const *argument), os_timer_type type = osTimerPeriodic, void *argument = NULL) + { constructor(mbed::callback((void (*)(void *))func, argument), type); } - + /** Create timer. @param func function to be executed by this timer. - @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behaviour. (default: osTimerPeriodic) + @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior. (default: osTimerPeriodic) @deprecated The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details @note You cannot call this function from ISR context. */ MBED_DEPRECATED_SINCE("mbed-os-5.2", - "The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details") - RtosTimer(mbed::Callback func, os_timer_type type=osTimerPeriodic) { + "The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details") + RtosTimer(mbed::Callback func, os_timer_type type = osTimerPeriodic) + { constructor(func, type); } - + /** Create timer. @param obj pointer to the object to call the member function on. @param method member function to be executed by this timer. - @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behaviour. (default: osTimerPeriodic) + @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior. (default: osTimerPeriodic) @deprecated The RtosTimer constructor does not support cv-qualifiers. Replaced by RtosTimer(callback(obj, method), os_timer_type). @@ -132,11 +134,12 @@ public: */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", - "The RtosTimer constructor does not support cv-qualifiers. Replaced by " - "RtosTimer(callback(obj, method), os_timer_type).") + "The RtosTimer constructor does not support cv-qualifiers. Replaced by " + "RtosTimer(callback(obj, method), os_timer_type).") MBED_DEPRECATED_SINCE("mbed-os-5.2", - "The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details") - RtosTimer(T *obj, M method, os_timer_type type=osTimerPeriodic) { + "The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details") + RtosTimer(T *obj, M method, os_timer_type type = osTimerPeriodic) + { constructor(mbed::callback(obj, method), type); } diff --git a/rtos/Semaphore.cpp b/rtos/Semaphore.cpp index 4e7bcb3744..ed1433c30d 100644 --- a/rtos/Semaphore.cpp +++ b/rtos/Semaphore.cpp @@ -27,15 +27,18 @@ namespace rtos { -Semaphore::Semaphore(int32_t count) { +Semaphore::Semaphore(int32_t count) +{ constructor(count, 0xffff); } -Semaphore::Semaphore(int32_t count, uint16_t max_count) { +Semaphore::Semaphore(int32_t count, uint16_t max_count) +{ constructor(count, max_count); } -void Semaphore::constructor(int32_t count, uint16_t max_count) { +void Semaphore::constructor(int32_t count, uint16_t max_count) +{ memset(&_obj_mem, 0, sizeof(_obj_mem)); osSemaphoreAttr_t attr = { 0 }; attr.cb_mem = &_obj_mem; @@ -44,7 +47,8 @@ void Semaphore::constructor(int32_t count, uint16_t max_count) { MBED_ASSERT(_id != NULL); } -int32_t Semaphore::wait(uint32_t millisec) { +int32_t Semaphore::wait(uint32_t millisec) +{ osStatus_t stat = osSemaphoreAcquire(_id, millisec); switch (stat) { case osOK: @@ -58,7 +62,8 @@ int32_t Semaphore::wait(uint32_t millisec) { } } -int32_t Semaphore::wait_until(uint64_t millisec) { +int32_t Semaphore::wait_until(uint64_t millisec) +{ uint64_t now = Kernel::get_ms_count(); if (now >= millisec) { @@ -71,11 +76,13 @@ int32_t Semaphore::wait_until(uint64_t millisec) { } } -osStatus Semaphore::release(void) { +osStatus Semaphore::release(void) +{ return osSemaphoreRelease(_id); } -Semaphore::~Semaphore() { +Semaphore::~Semaphore() +{ osSemaphoreDelete(_id); } diff --git a/rtos/Semaphore.h b/rtos/Semaphore.h index 4584792290..0bcd788de9 100644 --- a/rtos/Semaphore.h +++ b/rtos/Semaphore.h @@ -49,7 +49,7 @@ public: @note You cannot call this function from ISR context. */ - Semaphore(int32_t count=0); + Semaphore(int32_t count = 0); /** Create and Initialize a Semaphore object used for managing resources. @param count number of available resources @@ -65,7 +65,7 @@ public: @note You may call this function from ISR context if the millisec parameter is set to 0. */ - int32_t wait(uint32_t millisec=osWaitForever); + int32_t wait(uint32_t millisec = osWaitForever); /** Wait until a Semaphore resource becomes available. @param millisec absolute timeout time, referenced to Kernel::get_ms_count() diff --git a/rtos/TARGET_CORTEX/SysTimer.cpp b/rtos/TARGET_CORTEX/SysTimer.cpp index 662e6d09df..35efb02620 100644 --- a/rtos/TARGET_CORTEX/SysTimer.cpp +++ b/rtos/TARGET_CORTEX/SysTimer.cpp @@ -54,7 +54,7 @@ namespace rtos { namespace internal { SysTimer::SysTimer() : - TimerEvent(get_lp_ticker_data()), _start_time(0), _tick(0) + TimerEvent(get_lp_ticker_data()), _start_time(0), _tick(0) { _start_time = ticker_read_us(_ticker_data); _suspend_time_passed = true; @@ -62,7 +62,7 @@ SysTimer::SysTimer() : } SysTimer::SysTimer(const ticker_data_t *data) : - TimerEvent(data), _start_time(0), _tick(0) + TimerEvent(data), _start_time(0), _tick(0) { _start_time = ticker_read_us(_ticker_data); } diff --git a/rtos/TARGET_CORTEX/TOOLCHAIN_ARM_MICRO/mbed_boot_arm_micro.c b/rtos/TARGET_CORTEX/TOOLCHAIN_ARM_MICRO/mbed_boot_arm_micro.c index 4684257d11..c968deb755 100644 --- a/rtos/TARGET_CORTEX/TOOLCHAIN_ARM_MICRO/mbed_boot_arm_micro.c +++ b/rtos/TARGET_CORTEX/TOOLCHAIN_ARM_MICRO/mbed_boot_arm_micro.c @@ -37,10 +37,10 @@ void _main_init(void) { /* microlib only supports the two region memory model */ - mbed_heap_start = (unsigned char*)__heap_base; + mbed_heap_start = (unsigned char *)__heap_base; mbed_heap_size = (uint32_t)__heap_base - (uint32_t)__heap_limit; - mbed_stack_isr_start = (unsigned char*)((uint32_t)__initial_sp - ISR_STACK_SIZE); + mbed_stack_isr_start = (unsigned char *)((uint32_t)__initial_sp - ISR_STACK_SIZE); mbed_stack_isr_size = ISR_STACK_SIZE; mbed_init(); diff --git a/rtos/TARGET_CORTEX/TOOLCHAIN_ARM_STD/mbed_boot_arm_std.c b/rtos/TARGET_CORTEX/TOOLCHAIN_ARM_STD/mbed_boot_arm_std.c index 9bcacc271c..1475082d8a 100644 --- a/rtos/TARGET_CORTEX/TOOLCHAIN_ARM_STD/mbed_boot_arm_std.c +++ b/rtos/TARGET_CORTEX/TOOLCHAIN_ARM_STD/mbed_boot_arm_std.c @@ -105,7 +105,7 @@ __asm(".global __use_no_semihosting\n\t"); //lint -esym(9003, os_libspace*) "variables 'os_libspace*' defined at module scope" // Memory for libspace -static uint32_t os_libspace[OS_THREAD_LIBSPACE_NUM+1][LIBSPACE_SIZE/4] \ +static uint32_t os_libspace[OS_THREAD_LIBSPACE_NUM + 1][LIBSPACE_SIZE / 4] \ __attribute__((section(".bss.os.libspace"))); // Thread IDs for libspace @@ -113,7 +113,8 @@ static osThreadId_t os_libspace_id[OS_THREAD_LIBSPACE_NUM] \ __attribute__((section(".bss.os.libspace"))); // Check if Kernel has been started -static uint32_t os_kernel_is_active (void) { +static uint32_t os_kernel_is_active(void) +{ static uint8_t os_kernel_active = 0U; if (os_kernel_active == 0U) { @@ -125,7 +126,8 @@ static uint32_t os_kernel_is_active (void) { } // Provide libspace for current thread -void *__user_perthread_libspace (void) { +void *__user_perthread_libspace(void) +{ osThreadId_t id; uint32_t n; @@ -182,7 +184,7 @@ __USED int _mutex_initialize(mutex *m) core_util_critical_section_enter(); for (int i = 0; i < OS_MUTEX_STATIC_NUM; i++) { if (_static_mutexes[i] == NULL) { - _static_mutexes[i] = (mutex)-1; // dummy value to reserve slot + _static_mutexes[i] = (mutex) - 1; // dummy value to reserve slot slot = &_static_mutexes[i]; //Use the static attrs attr.cb_size = sizeof(mbed_rtos_storage_mutex_t); @@ -202,7 +204,7 @@ __USED int _mutex_initialize(mutex *m) /* Mutex pool exhausted, try using HEAP */ attr.cb_size = sizeof(mbed_rtos_storage_mutex_t); - attr.cb_mem = (void*)malloc(attr.cb_size); + attr.cb_mem = (void *)malloc(attr.cb_size); if (attr.cb_mem == NULL) { osRtxErrorNotify(osRtxErrorClibSpace, m); return 0; @@ -218,21 +220,24 @@ __USED int _mutex_initialize(mutex *m) } /* Acquire mutex */ -__USED void _mutex_acquire(mutex *m) { +__USED void _mutex_acquire(mutex *m) +{ if (os_kernel_is_active() != 0U) { (void)osMutexAcquire(*m, osWaitForever); } } /* Release mutex */ -__USED void _mutex_release(mutex *m) { +__USED void _mutex_release(mutex *m) +{ if (os_kernel_is_active() != 0U) { (void)osMutexRelease(*m); } } /* Free mutex */ -__USED void _mutex_free(mutex *m) { +__USED void _mutex_free(mutex *m) +{ mutex *slot = NULL; core_util_critical_section_enter(); for (int i = 0; i < OS_MUTEX_STATIC_NUM; i++) { diff --git a/rtos/TARGET_CORTEX/TOOLCHAIN_GCC_ARM/mbed_boot_gcc_arm.c b/rtos/TARGET_CORTEX/TOOLCHAIN_GCC_ARM/mbed_boot_gcc_arm.c index c6ff33cda0..105f780860 100644 --- a/rtos/TARGET_CORTEX/TOOLCHAIN_GCC_ARM/mbed_boot_gcc_arm.c +++ b/rtos/TARGET_CORTEX/TOOLCHAIN_GCC_ARM/mbed_boot_gcc_arm.c @@ -35,7 +35,7 @@ extern uint32_t __end__[]; #define HEAP_SIZE ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START)) #endif -extern void __libc_init_array (void); +extern void __libc_init_array(void); /* * mbed entry point for the GCC toolchain @@ -86,7 +86,8 @@ void mbed_toolchain_init() } extern int __real_main(void); -int __wrap_main(void) { +int __wrap_main(void) +{ /* For backwards compatibility */ return __real_main(); } @@ -94,22 +95,22 @@ int __wrap_main(void) { /* Opaque declaration of _reent structure */ struct _reent; -void __rtos_malloc_lock( struct _reent *_r ) +void __rtos_malloc_lock(struct _reent *_r) { osMutexAcquire(malloc_mutex_id, osWaitForever); } -void __rtos_malloc_unlock( struct _reent *_r ) +void __rtos_malloc_unlock(struct _reent *_r) { osMutexRelease(malloc_mutex_id); } -void __rtos_env_lock( struct _reent *_r ) +void __rtos_env_lock(struct _reent *_r) { osMutexAcquire(env_mutex_id, osWaitForever); } -void __rtos_env_unlock( struct _reent *_r ) +void __rtos_env_unlock(struct _reent *_r) { osMutexRelease(env_mutex_id); } diff --git a/rtos/TARGET_CORTEX/TOOLCHAIN_IAR/mbed_boot_iar.c b/rtos/TARGET_CORTEX/TOOLCHAIN_IAR/mbed_boot_iar.c index e5c0af783d..387b7f8dc1 100644 --- a/rtos/TARGET_CORTEX/TOOLCHAIN_IAR/mbed_boot_iar.c +++ b/rtos/TARGET_CORTEX/TOOLCHAIN_IAR/mbed_boot_iar.c @@ -27,7 +27,7 @@ #pragma section="CSTACK" #pragma section="HEAP" -extern void* __vector_table; +extern void *__vector_table; extern int __low_level_init(void); extern void __iar_data_init3(void); extern __weak void __iar_init_core(void); @@ -53,7 +53,7 @@ extern void __iar_dynamic_initialization(void); * \arm\src\lib\thumb\cstartup_M.s */ #pragma required=__vector_table -void __iar_program_start( void ) +void __iar_program_start(void) { /* the calls below are normally made in IAR cstartup */ __iar_init_core(); @@ -74,10 +74,10 @@ void __iar_program_start( void ) __iar_data_init3(); /* mbed specific code */ - mbed_heap_start = (unsigned char*)__section_begin("HEAP"); + mbed_heap_start = (unsigned char *)__section_begin("HEAP"); mbed_heap_size = (uint32_t)__section_size("HEAP"); - mbed_stack_isr_start = (unsigned char*)__section_begin("CSTACK"); + mbed_stack_isr_start = (unsigned char *)__section_begin("CSTACK"); mbed_stack_isr_size = (uint32_t)__section_size("CSTACK"); mbed_init(); @@ -112,7 +112,7 @@ void __iar_system_Mtxinit(__iar_Rmtx *mutex) /* Initialize a system lock */ attr.cb_size = sizeof(std_mutex_sys[index]); attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; std_mutex_id_sys[index] = osMutexNew(&attr); - *mutex = (__iar_Rmtx*)&std_mutex_id_sys[index]; + *mutex = (__iar_Rmtx *)&std_mutex_id_sys[index]; return; } } @@ -123,18 +123,18 @@ void __iar_system_Mtxinit(__iar_Rmtx *mutex) /* Initialize a system lock */ void __iar_system_Mtxdst(__iar_Rmtx *mutex) /* Destroy a system lock */ { - osMutexDelete(*(osMutexId_t*)*mutex); + osMutexDelete(*(osMutexId_t *)*mutex); *mutex = 0; } void __iar_system_Mtxlock(__iar_Rmtx *mutex) /* Lock a system lock */ { - osMutexAcquire(*(osMutexId_t*)*mutex, osWaitForever); + osMutexAcquire(*(osMutexId_t *)*mutex, osWaitForever); } void __iar_system_Mtxunlock(__iar_Rmtx *mutex) /* Unlock a system lock */ { - osMutexRelease(*(osMutexId_t*)*mutex); + osMutexRelease(*(osMutexId_t *)*mutex); } void __iar_file_Mtxinit(__iar_Rmtx *mutex) /* Initialize a file lock */ @@ -148,7 +148,7 @@ void __iar_file_Mtxinit(__iar_Rmtx *mutex) /* Initialize a file lock */ attr.cb_size = sizeof(std_mutex_file[index]); attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; std_mutex_id_file[index] = osMutexNew(&attr); - *mutex = (__iar_Rmtx*)&std_mutex_id_file[index]; + *mutex = (__iar_Rmtx *)&std_mutex_id_file[index]; return; } } @@ -158,16 +158,16 @@ void __iar_file_Mtxinit(__iar_Rmtx *mutex) /* Initialize a file lock */ void __iar_file_Mtxdst(__iar_Rmtx *mutex) /* Destroy a file lock */ { - osMutexDelete(*(osMutexId_t*)*mutex); + osMutexDelete(*(osMutexId_t *)*mutex); *mutex = 0; } void __iar_file_Mtxlock(__iar_Rmtx *mutex) /* Lock a file lock */ { - osMutexAcquire(*(osMutexId_t*)*mutex, osWaitForever); + osMutexAcquire(*(osMutexId_t *)*mutex, osWaitForever); } void __iar_file_Mtxunlock(__iar_Rmtx *mutex) /* Unlock a file lock */ { - osMutexRelease(*(osMutexId_t*)*mutex); + osMutexRelease(*(osMutexId_t *)*mutex); } diff --git a/rtos/TARGET_CORTEX/mbed_boot.c b/rtos/TARGET_CORTEX/mbed_boot.c index 0e8576c3e3..f09ff9345a 100644 --- a/rtos/TARGET_CORTEX/mbed_boot.c +++ b/rtos/TARGET_CORTEX/mbed_boot.c @@ -121,7 +121,7 @@ static void mbed_cpy_nvic(void) #if !defined(__CORTEX_M0) && !defined(__CORTEX_A9) #ifdef NVIC_RAM_VECTOR_ADDRESS uint32_t *old_vectors = (uint32_t *)SCB->VTOR; - uint32_t *vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS; + uint32_t *vectors = (uint32_t *)NVIC_RAM_VECTOR_ADDRESS; for (int i = 0; i < NVIC_NUM_VECTORS; i++) { vectors[i] = old_vectors[i]; } diff --git a/rtos/TARGET_CORTEX/mbed_boot.h b/rtos/TARGET_CORTEX/mbed_boot.h index 55a7e815a0..7aef50fe91 100644 --- a/rtos/TARGET_CORTEX/mbed_boot.h +++ b/rtos/TARGET_CORTEX/mbed_boot.h @@ -51,7 +51,7 @@ extern "C" { /* Define stack sizes if they haven't been set already */ #if !defined(ISR_STACK_SIZE) - #define ISR_STACK_SIZE ((uint32_t)1024) +#define ISR_STACK_SIZE ((uint32_t)1024) #endif /* Heap limits - only used if set */ diff --git a/rtos/TARGET_CORTEX/mbed_rtos_rtx.c b/rtos/TARGET_CORTEX/mbed_rtos_rtx.c index 4485a180be..934eb8a5ca 100644 --- a/rtos/TARGET_CORTEX/mbed_rtos_rtx.c +++ b/rtos/TARGET_CORTEX/mbed_rtos_rtx.c @@ -52,7 +52,7 @@ MBED_NORETURN void mbed_rtos_start() _main_thread_attr.cb_size = sizeof(_main_obj); _main_thread_attr.cb_mem = &_main_obj; _main_thread_attr.priority = osPriorityNormal; - _main_thread_attr.name = "main_thread"; + _main_thread_attr.name = "main"; /* Allow non-secure main thread to call secure functions */ #if defined(DOMAIN_NS) && (DOMAIN_NS == 1U) diff --git a/rtos/TARGET_CORTEX/mbed_rtx_conf.h b/rtos/TARGET_CORTEX/mbed_rtx_conf.h index f0b2fc3984..91db38a617 100644 --- a/rtos/TARGET_CORTEX/mbed_rtx_conf.h +++ b/rtos/TARGET_CORTEX/mbed_rtx_conf.h @@ -39,10 +39,16 @@ #define OS_TIMER_THREAD_STACK_SIZE MBED_CONF_RTOS_TIMER_THREAD_STACK_SIZE #endif -#ifdef MBED_CONF_APP_IDLE_THREAD_STACK_SIZE -#define OS_IDLE_THREAD_STACK_SIZE MBED_CONF_APP_IDLE_THREAD_STACK_SIZE +// Increase the idle thread stack size when tickless is enabled +#if defined(MBED_TICKLESS) && defined(LPTICKER_DELAY_TICKS) && (LPTICKER_DELAY_TICKS > 0) +#define EXTRA_IDLE_STACK MBED_CONF_RTOS_IDLE_THREAD_STACK_SIZE_TICKLESS_EXTRA #else -#define OS_IDLE_THREAD_STACK_SIZE MBED_CONF_RTOS_IDLE_THREAD_STACK_SIZE +#define EXTRA_IDLE_STACK 0 +#endif +#ifdef MBED_CONF_APP_IDLE_THREAD_STACK_SIZE +#define OS_IDLE_THREAD_STACK_SIZE (MBED_CONF_APP_IDLE_THREAD_STACK_SIZE + EXTRA_IDLE_STACK) +#else +#define OS_IDLE_THREAD_STACK_SIZE (MBED_CONF_RTOS_IDLE_THREAD_STACK_SIZE + EXTRA_IDLE_STACK) #endif #define OS_DYNAMIC_MEM_SIZE 0 @@ -70,8 +76,8 @@ // LIBSPACE default value set for ARMCC #define OS_THREAD_LIBSPACE_NUM 4 -#define OS_IDLE_THREAD_NAME "idle_thread" -#define OS_TIMER_THREAD_NAME "timer_thread" +#define OS_IDLE_THREAD_NAME "rtx_idle" +#define OS_TIMER_THREAD_NAME "rtx_timer" /* Enable only the evr events we use in Mbed-OS to save flash space. */ //Following events are used by Mbed-OS, DO NOT disable them diff --git a/rtos/TARGET_CORTEX/mbed_rtx_handlers.c b/rtos/TARGET_CORTEX/mbed_rtx_handlers.c index f0b2ad7402..8bc395cba3 100644 --- a/rtos/TARGET_CORTEX/mbed_rtx_handlers.c +++ b/rtos/TARGET_CORTEX/mbed_rtx_handlers.c @@ -22,6 +22,7 @@ #include "mbed_interface.h" #include "RTX_Config.h" #include "rtos/rtos_handlers.h" +#include "rtos/rtos_idle.h" #ifdef RTE_Compiler_EventRecorder #include "EventRecorder.h" // Keil::Compiler:Event Recorder @@ -30,8 +31,6 @@ #define EvtRtxThreadTerminate EventID(EventLevelAPI, 0xF2U, 0x1AU) #endif -extern void rtos_idle_loop(void); - static void (*terminate_hook)(osThreadId_t id); static void thread_terminate_hook(osThreadId_t id) @@ -48,9 +47,7 @@ void rtos_attach_thread_terminate_hook(void (*fptr)(osThreadId_t id)) __NO_RETURN void osRtxIdleThread(void *argument) { - for (;;) { - rtos_idle_loop(); - } + rtos_idle_loop(); } __NO_RETURN uint32_t osRtxErrorNotify(uint32_t code, void *object_id) diff --git a/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp b/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp index f300e7e1e9..78d03220b0 100644 --- a/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp +++ b/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp @@ -28,9 +28,10 @@ #include "mbed_assert.h" #include #include "rtx_os.h" + +/* Everything in rtx_lib.h, and provided by this file, has C linkage */ extern "C" { #include "rtx_lib.h" -} using namespace mbed; @@ -42,7 +43,7 @@ static rtos::internal::SysTimer *os_timer; static uint64_t os_timer_data[sizeof(rtos::internal::SysTimer) / 8]; /// Enable System Timer. -void OS_Tick_Enable (void) +void OS_Tick_Enable(void) { // Do not use SingletonPtr since this relies on the RTOS if (NULL == os_timer) { @@ -55,41 +56,51 @@ void OS_Tick_Enable (void) } /// Disable System Timer. -void OS_Tick_Disable (void) +void OS_Tick_Disable(void) { os_timer->cancel_tick(); } /// Acknowledge System Timer IRQ. -void OS_Tick_AcknowledgeIRQ (void) +void OS_Tick_AcknowledgeIRQ(void) { } /// Get System Timer count. -uint32_t OS_Tick_GetCount (void) +uint32_t OS_Tick_GetCount(void) { return os_timer->get_time() & 0xFFFFFFFF; } // Get OS Tick IRQ number. -int32_t OS_Tick_GetIRQn (void) { - return -1; +int32_t OS_Tick_GetIRQn(void) +{ + return -1; } // Get OS Tick overflow status. -uint32_t OS_Tick_GetOverflow (void) { - return 0; +uint32_t OS_Tick_GetOverflow(void) +{ + return 0; } // Get OS Tick interval. -uint32_t OS_Tick_GetInterval (void) { - return 1000; +uint32_t OS_Tick_GetInterval(void) +{ + return 1000; } static void default_idle_hook(void) { uint32_t ticks_to_sleep = osKernelSuspend(); + const bool block_deep_sleep = ticks_to_sleep <= MBED_CONF_TARGET_DEEP_SLEEP_LATENCY; + + if (block_deep_sleep) { + sleep_manager_lock_deep_sleep(); + } else { + ticks_to_sleep -= MBED_CONF_TARGET_DEEP_SLEEP_LATENCY; + } os_timer->suspend(ticks_to_sleep); bool event_pending = false; @@ -106,6 +117,11 @@ static void default_idle_hook(void) // Ensure interrupts get a chance to fire __ISB(); } + + if (block_deep_sleep) { + sleep_manager_unlock_deep_sleep(); + } + osKernelResume(os_timer->resume()); } @@ -136,10 +152,12 @@ void rtos_attach_idle_hook(void (*fptr)(void)) } } -extern "C" void rtos_idle_loop(void) +MBED_NORETURN void rtos_idle_loop(void) { //Continuously call the idle hook function pointer while (1) { idle_hook_fptr(); } } + +} // extern "C" diff --git a/rtos/ThisThread.cpp b/rtos/ThisThread.cpp index 8df8e04fe4..1ddbfe57ae 100644 --- a/rtos/ThisThread.cpp +++ b/rtos/ThisThread.cpp @@ -23,9 +23,9 @@ #define __STDC_LIMIT_MACROS #include "rtos/ThisThread.h" -#include "mbed.h" +#include "rtos/Kernel.h" #include "rtos/rtos_idle.h" -#include "mbed_assert.h" +#include "platform/mbed_assert.h" namespace rtos { diff --git a/rtos/Thread.cpp b/rtos/Thread.cpp index 4faf8058f4..6d3350618e 100644 --- a/rtos/Thread.cpp +++ b/rtos/Thread.cpp @@ -21,11 +21,10 @@ */ #include "rtos/Thread.h" #include "rtos/ThisThread.h" - -#include "mbed.h" #include "rtos/rtos_idle.h" #include "rtos/rtos_handlers.h" -#include "mbed_assert.h" +#include "platform/mbed_assert.h" +#include "platform/mbed_error.h" #define ALIGN_UP(pos, align) ((pos) % (align) ? (pos) + ((align) - (pos) % (align)) : (pos)) MBED_STATIC_ASSERT(ALIGN_UP(0, 8) == 0, "ALIGN_UP macro error"); @@ -68,7 +67,7 @@ void Thread::constructor(osPriority priority, constructor(MBED_TZ_DEFAULT_ACCESS, priority, stack_size, stack_mem, name); } -void Thread::constructor(Callback task, +void Thread::constructor(mbed::Callback task, osPriority priority, uint32_t stack_size, unsigned char *stack_mem, const char *name) { constructor(MBED_TZ_DEFAULT_ACCESS, priority, stack_size, stack_mem, name); @@ -87,7 +86,7 @@ void Thread::constructor(Callback task, } } -osStatus Thread::start(Callback task) +osStatus Thread::start(mbed::Callback task) { _mutex.lock(); diff --git a/rtos/mbed_lib.json b/rtos/mbed_lib.json index 7714cdd743..76e5321c67 100644 --- a/rtos/mbed_lib.json +++ b/rtos/mbed_lib.json @@ -17,7 +17,28 @@ "thread-stack-size": { "help": "The default stack size of new threads", "value": 4096 + }, + "idle-thread-stack-size-tickless-extra": { + "help": "Additional size to add to the idle thread when tickless is enabled and LPTICKER_DELAY_TICKS is used", + "value": 256 } }, - "macros": ["_RTE_"] + "macros": ["_RTE_"], + "target_overrides": { + "*": { + "target.boot-stack-size": "0x400" + }, + "MCU_NRF51": { + "target.boot-stack-size": "0x800" + }, + "MCU_NRF52840": { + "target.boot-stack-size": "0x800" + }, + "MCU_NRF52832": { + "target.boot-stack-size": "0x800" + }, + "MCU_NRF51_UNIFIED": { + "target.boot-stack-size": "0x800" + } + } } diff --git a/rtos/rtos_idle.h b/rtos/rtos_idle.h index c2894c23e3..f1f5d6fc3d 100644 --- a/rtos/rtos_idle.h +++ b/rtos/rtos_idle.h @@ -25,6 +25,7 @@ #ifndef RTOS_IDLE_H #define RTOS_IDLE_H +#include "mbed_toolchain.h" #include #ifdef __cplusplus @@ -35,12 +36,16 @@ extern "C" { * \defgroup rtos_Idle Idle hook function * @{ */ -/** +/** @note Sets the hook function called by idle task @param fptr Hook function pointer. */ void rtos_attach_idle_hook(void (*fptr)(void)); + +/** @private */ +MBED_NORETURN void rtos_idle_loop(void); + /** @}*/ #ifdef __cplusplus diff --git a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0/device/TOOLCHAIN_GCC_ARM/MPS2.ld b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0/device/TOOLCHAIN_GCC_ARM/MPS2.ld index 20097e1c12..f50b4d5629 100644 --- a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0/device/TOOLCHAIN_GCC_ARM/MPS2.ld +++ b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0/device/TOOLCHAIN_GCC_ARM/MPS2.ld @@ -77,12 +77,12 @@ SECTIONS { __vector_table = .; KEEP(*(.vector_table)) - . = ALIGN(4); + . = ALIGN(8); } > VECTORS .text : { - . = ALIGN(4); + . = ALIGN(8); *(.text*) KEEP(*(.init)) @@ -121,30 +121,30 @@ SECTIONS .interrupts_ram : { - . = ALIGN(4); + . = ALIGN(8); __VECTOR_RAM__ = .; __interrupts_ram_start__ = .; /* Create a global symbol at data start */ . += M_VECTOR_RAM_SIZE; - . = ALIGN(4); + . = ALIGN(8); __interrupts_ram_end__ = .; /* Define a global symbol at data end */ } > RAM .data : { PROVIDE(__etext = LOADADDR(.data)); - . = ALIGN(4); + . = ALIGN(8); __data_start__ = .; *(vtable) *(.data) *(.data*) - . = ALIGN(4); + . = ALIGN(8); /* preinit data */ PROVIDE (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE (__preinit_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* init data */ PROVIDE (__init_array_start = .); KEEP(*(SORT(.init_array.*))) @@ -152,14 +152,14 @@ SECTIONS PROVIDE (__init_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* finit data */ PROVIDE (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE (__fini_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* All data end */ __data_end__ = .; @@ -177,13 +177,13 @@ SECTIONS .bss : { - . = ALIGN(4); + . = ALIGN(8); __START_BSS = .; __bss_start__ = .; *(.bss) *(.bss*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); __bss_end__ = .; __END_BSS = .; diff --git a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S index e82e72b469..55ab8446b1 100644 --- a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S +++ b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S @@ -70,7 +70,7 @@ __isr_vector: .long UARTTX4_Handler /* UART 4 TX Handler */ .long ADCSPI_Handler /* SHIELD ADC SPI exceptions Handler */ .long SHIELDSPI_Handler /* SHIELD SPI exceptions Handler */ - .long PORT0_0_Handler /* GPIO Port 0 pin 0 Handler */ + .long PORT0_0_Handler /* GPIO Port 0 pin 0 Handler */ .long PORT0_1_Handler /* GPIO Port 0 pin 1 Handler */ .long PORT0_2_Handler /* GPIO Port 0 pin 2 Handler */ .long PORT0_3_Handler /* GPIO Port 0 pin 3 Handler */ @@ -193,7 +193,7 @@ system_startup: def_irq_default_handler UARTTX4_Handler /* 21: UART 4 TX Handler */ def_irq_default_handler ADCSPI_Handler /* 22: SHIELD ADC SPI exceptions Handler */ def_irq_default_handler SHIELDSPI_Handler /* 23: SHIELD SPI exceptions Handler */ - def_irq_default_handler PORT0_0_Handler /* 24: GPIO Port 0 pin 0 Handler */ + def_irq_default_handler PORT0_0_Handler /* 24: GPIO Port 0 pin 0 Handler */ def_irq_default_handler PORT0_1_Handler /* 25: GPIO Port 0 pin 1 Handler */ def_irq_default_handler PORT0_2_Handler /* 26: GPIO Port 0 pin 2 Handler */ def_irq_default_handler PORT0_3_Handler /* 27: GPIO Port 0 pin 3 Handler */ diff --git a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0P/device/TOOLCHAIN_GCC_ARM/MPS2.ld b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0P/device/TOOLCHAIN_GCC_ARM/MPS2.ld index 647cc848ea..7e2c8bdf3e 100644 --- a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0P/device/TOOLCHAIN_GCC_ARM/MPS2.ld +++ b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0P/device/TOOLCHAIN_GCC_ARM/MPS2.ld @@ -77,12 +77,12 @@ SECTIONS { __vector_table = .; KEEP(*(.vector_table)) - . = ALIGN(4); + . = ALIGN(8); } > VECTORS .text : { - . = ALIGN(4); + . = ALIGN(8); *(.text*) KEEP(*(.init)) @@ -121,30 +121,30 @@ SECTIONS .interrupts_ram : { - . = ALIGN(4); + . = ALIGN(8); __VECTOR_RAM__ = .; __interrupts_ram_start__ = .; /* Create a global symbol at data start */ . += M_VECTOR_RAM_SIZE; - . = ALIGN(4); + . = ALIGN(8); __interrupts_ram_end__ = .; /* Define a global symbol at data end */ } > RAM .data : { PROVIDE(__etext = LOADADDR(.data)); - . = ALIGN(4); + . = ALIGN(8); __data_start__ = .; *(vtable) *(.data) *(.data*) - . = ALIGN(4); + . = ALIGN(8); /* preinit data */ PROVIDE (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE (__preinit_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* init data */ PROVIDE (__init_array_start = .); KEEP(*(SORT(.init_array.*))) @@ -152,14 +152,14 @@ SECTIONS PROVIDE (__init_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* finit data */ PROVIDE (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE (__fini_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* All data end */ __data_end__ = .; @@ -177,13 +177,13 @@ SECTIONS .bss : { - . = ALIGN(4); + . = ALIGN(8); __START_BSS = .; __bss_start__ = .; *(.bss) *(.bss*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); __bss_end__ = .; __END_BSS = .; diff --git a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0P/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0P/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S index e82e72b469..55ab8446b1 100644 --- a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0P/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S +++ b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M0P/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S @@ -70,7 +70,7 @@ __isr_vector: .long UARTTX4_Handler /* UART 4 TX Handler */ .long ADCSPI_Handler /* SHIELD ADC SPI exceptions Handler */ .long SHIELDSPI_Handler /* SHIELD SPI exceptions Handler */ - .long PORT0_0_Handler /* GPIO Port 0 pin 0 Handler */ + .long PORT0_0_Handler /* GPIO Port 0 pin 0 Handler */ .long PORT0_1_Handler /* GPIO Port 0 pin 1 Handler */ .long PORT0_2_Handler /* GPIO Port 0 pin 2 Handler */ .long PORT0_3_Handler /* GPIO Port 0 pin 3 Handler */ @@ -193,7 +193,7 @@ system_startup: def_irq_default_handler UARTTX4_Handler /* 21: UART 4 TX Handler */ def_irq_default_handler ADCSPI_Handler /* 22: SHIELD ADC SPI exceptions Handler */ def_irq_default_handler SHIELDSPI_Handler /* 23: SHIELD SPI exceptions Handler */ - def_irq_default_handler PORT0_0_Handler /* 24: GPIO Port 0 pin 0 Handler */ + def_irq_default_handler PORT0_0_Handler /* 24: GPIO Port 0 pin 0 Handler */ def_irq_default_handler PORT0_1_Handler /* 25: GPIO Port 0 pin 1 Handler */ def_irq_default_handler PORT0_2_Handler /* 26: GPIO Port 0 pin 2 Handler */ def_irq_default_handler PORT0_3_Handler /* 27: GPIO Port 0 pin 3 Handler */ diff --git a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M3/device/TOOLCHAIN_GCC_ARM/MPS2.ld b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M3/device/TOOLCHAIN_GCC_ARM/MPS2.ld index dc784fcae4..af52d7fe12 100644 --- a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M3/device/TOOLCHAIN_GCC_ARM/MPS2.ld +++ b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M3/device/TOOLCHAIN_GCC_ARM/MPS2.ld @@ -77,12 +77,12 @@ SECTIONS { __vector_table = .; KEEP(*(.vector_table)) - . = ALIGN(4); + . = ALIGN(8); } > VECTORS .text : { - . = ALIGN(4); + . = ALIGN(8); *(.text*) KEEP(*(.init)) @@ -121,30 +121,30 @@ SECTIONS .interrupts_ram : { - . = ALIGN(4); + . = ALIGN(8); __VECTOR_RAM__ = .; __interrupts_ram_start__ = .; /* Create a global symbol at data start */ . += M_VECTOR_RAM_SIZE; - . = ALIGN(4); + . = ALIGN(8); __interrupts_ram_end__ = .; /* Define a global symbol at data end */ } > RAM .data : { PROVIDE(__etext = LOADADDR(.data)); - . = ALIGN(4); + . = ALIGN(8); __data_start__ = .; *(vtable) *(.data) *(.data*) - . = ALIGN(4); + . = ALIGN(8); /* preinit data */ PROVIDE (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE (__preinit_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* init data */ PROVIDE (__init_array_start = .); KEEP(*(SORT(.init_array.*))) @@ -152,14 +152,14 @@ SECTIONS PROVIDE (__init_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* finit data */ PROVIDE (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE (__fini_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* All data end */ __data_end__ = .; @@ -177,13 +177,13 @@ SECTIONS .bss : { - . = ALIGN(4); + . = ALIGN(8); __START_BSS = .; __bss_start__ = .; *(.bss) *(.bss*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); __bss_end__ = .; __END_BSS = .; diff --git a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M3/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M3/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S index c5d12692ec..a47f9ea383 100644 --- a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M3/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S +++ b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M3/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S @@ -46,63 +46,38 @@ __isr_vector: .long SysTick_Handler /* SysTick Handler */ /* External Interrupts */ - .long UART0_IRQHandler /* 0: UART 0 RX and TX Combined Interrupt */ - .long Spare_IRQHandler /* 1: Undefined */ - .long UART1_IRQHandler /* 2: UART 1 RX and TX Combined Interrupt */ - .long APB_Slave0_IRQHandler /* 3: Reserved for APB Slave */ - .long APB_Slave1_IRQHandler /* 4: Reserved for APB Slave */ - .long RTC_IRQHandler /* 5: RTC Interrupt */ - .long PORT0_IRQHandler /* 6: GPIO Port 0 combined Interrupt */ - .long PORT1_ALL_IRQHandler /* 7: GPIO Port 1 combined Interrupt */ - .long TIMER0_IRQHandler /* 8: TIMER 0 Interrupt */ - .long TIMER1_IRQHandler /* 9: TIMER 1 Interrupt */ - .long DUALTIMER_IRQHandler /* 10: Dual Timer Interrupt */ - .long APB_Slave2_IRQHandler /* 11: Reserved for APB Slave */ - .long UARTOVF_IRQHandler /* 12: UART 0,1,2 Overflow Interrupt */ - .long APB_Slave3_IRQHandler /* 13: Reserved for APB Slave */ - .long RESERVED0_IRQHandler /* 14: Reserved */ - .long TSC_IRQHandler /* 15: Touch Screen Interrupt */ - .long PORT0_0_IRQHandler /* 16: GPIO Port 0 pin 0 Handler */ - .long PORT0_1_IRQHandler /* 17: GPIO Port 0 pin 1 Handler */ - .long PORT0_2_IRQHandler /* 18: GPIO Port 0 pin 2 Handler */ - .long PORT0_3_IRQHandler /* 19: GPIO Port 0 pin 3 Handler */ - .long PORT0_4_IRQHandler /* 20: GPIO Port 0 pin 4 Handler */ - .long PORT0_5_IRQHandler /* 21: GPIO Port 0 pin 5 Handler */ - .long PORT0_6_IRQHandler /* 22: GPIO Port 0 pin 6 Handler */ - .long PORT0_7_IRQHandler /* 23: GPIO Port 0 pin 7 Handler */ - .long PORT0_8_IRQHandler /* 24: GPIO Port 0 pin 8 Handler */ - .long PORT0_9_IRQHandler /* 25: GPIO Port 0 pin 9 Handler */ - .long PORT0_10_IRQHandler /* 26: GPIO Port 0 pin 10 Handler */ - .long PORT0_11_IRQHandler /* 27: GPIO Port 0 pin 11 Handler */ - .long PORT0_12_IRQHandler /* 28: GPIO Port 0 pin 12 Handler */ - .long PORT0_13_IRQHandler /* 29: GPIO Port 0 pin 13 Handler */ - .long PORT0_14_IRQHandler /* 30: GPIO Port 0 pin 14 Handler */ - .long PORT0_15_IRQHandler /* 31: GPIO Port 0 pin 15 Handler */ - .long FLASH0_IRQHandler /* 32: Reserved for Flash */ - .long FLASH1_IRQHandler /* 33: Reserved for Flash */ - .long RESERVED1_IRQHandler /* 34: Reserved */ - .long RESERVED2_IRQHandler /* 35: Reserved */ - .long RESERVED3_IRQHandler /* 36: Reserved */ - .long RESERVED4_IRQHandler /* 37: Reserved */ - .long RESERVED5_IRQHandler /* 38: Reserved */ - .long RESERVED6_IRQHandler /* 39: Reserved */ - .long RESERVED7_IRQHandler /* 40: Reserved */ - .long RESERVED8_IRQHandler /* 41: Reserved */ - .long PORT2_ALL_IRQHandler /* 42: GPIO Port 2 combined Interrupt */ - .long PORT3_ALL_IRQHandler /* 43: GPIO Port 3 combined Interrupt */ - .long TRNG_IRQHandler /* 44: Random number generator Interrupt */ - .long UART2_IRQHandler /* 45: UART 2 RX and TX Combined Interrupt */ - .long UART3_IRQHandler /* 46: UART 3 RX and TX Combined Interrupt */ - .long ETHERNET_IRQHandler /* 47: Ethernet interrupt t.b.a. */ - .long I2S_IRQHandler /* 48: I2S Interrupt */ - .long MPS2_SPI0_IRQHandler /* 49: SPI Interrupt (spi header) */ - .long MPS2_SPI1_IRQHandler /* 50: SPI Interrupt (clcd) */ - .long MPS2_SPI2_IRQHandler /* 51: SPI Interrupt (spi 1 ADC replacement) */ - .long MPS2_SPI3_IRQHandler /* 52: SPI Interrupt (spi 0 shield 0 replacement) */ - .long MPS2_SPI4_IRQHandler /* 53: SPI Interrupt (shield 1) */ - .long PORT4_ALL_IRQHandler /* 54: GPIO Port 4 combined Interrupt */ - .long PORT5_ALL_IRQHandler /* 55: GPIO Port 5 combined Interrupt */ - .long UART4_IRQHandler /* 56: UART 4 RX and TX Combined Interrupt */ + .long UARTRX0_Handler /* UART 0 RX Handler */ + .long UARTTX0_Handler /* UART 0 TX Handler */ + .long UARTRX1_Handler /* UART 1 RX Handler */ + .long UARTTX1_Handler /* UART 1 TX Handler */ + .long UARTRX2_Handler /* UART 2 RX Handler */ + .long UARTTX2_Handler /* UART 2 TX Handler */ + .long PORT0_COMB_Handler /* GPIO Port 0 Combined Handler */ + .long PORT1_COMB_Handler /* GPIO Port 1 Combined Handler */ + .long TIMER0_Handler /* TIMER 0 handler */ + .long TIMER1_Handler /* TIMER 1 handler */ + .long DUALTIMER_HANDLER /* Dual timer handler */ + .long SPI_Handler /* SPI exceptions Handler */ + .long UARTOVF_Handler /* UART 0,1,2 Overflow Handler */ + .long ETHERNET_Handler /* Ethernet Overflow Handler */ + .long I2S_Handler /* I2S Handler */ + .long TSC_Handler /* Touch Screen handler */ + .long PORT2_COMB_Handler /* GPIO Port 2 Combined Handler */ + .long PORT3_COMB_Handler /* GPIO Port 3 Combined Handler */ + .long UARTRX3_Handler /* UART 3 RX Handler */ + .long UARTTX3_Handler /* UART 3 TX Handler */ + .long UARTRX4_Handler /* UART 4 RX Handler */ + .long UARTTX4_Handler /* UART 4 TX Handler */ + .long ADCSPI_Handler /* SHIELD ADC SPI exceptions Handler */ + .long SHIELDSPI_Handler /* SHIELD SPI exceptions Handler */ + .long PORT0_0_Handler /* GPIO Port 0 pin 0 Handler */ + .long PORT0_1_Handler /* GPIO Port 0 pin 1 Handler */ + .long PORT0_2_Handler /* GPIO Port 0 pin 2 Handler */ + .long PORT0_3_Handler /* GPIO Port 0 pin 3 Handler */ + .long PORT0_4_Handler /* GPIO Port 0 pin 4 Handler */ + .long PORT0_5_Handler /* GPIO Port 0 pin 5 Handler */ + .long PORT0_6_Handler /* GPIO Port 0 pin 6 Handler */ + .long PORT0_7_Handler /* GPIO Port 0 pin 7 Handler */ .size __isr_vector, . - __isr_vector @@ -196,62 +171,37 @@ system_startup: .endm /* External interrupts */ - def_irq_default_handler UART0_IRQHandler /* 0: UART 0 RX and TX Combined Interrupt */ - def_irq_default_handler Spare_IRQHandler /* 1: Undefined */ - def_irq_default_handler UART1_IRQHandler /* 2: UART 1 RX and TX Combined Interrupt */ - def_irq_default_handler APB_Slave0_IRQHandler /* 3: Reserved for APB Slave */ - def_irq_default_handler APB_Slave1_IRQHandler /* 4: Reserved for APB Slave */ - def_irq_default_handler RTC_IRQHandler /* 5: RTC Interrupt */ - def_irq_default_handler PORT0_IRQHandler /* 6: GPIO Port 0 combined Interrupt */ - def_irq_default_handler PORT1_ALL_IRQHandler /* 7: GPIO Port 1 combined Interrupt */ - def_irq_default_handler TIMER0_IRQHandler /* 8: TIMER 0 Interrupt */ - def_irq_default_handler TIMER1_IRQHandler /* 9: TIMER 1 Interrupt */ - def_irq_default_handler DUALTIMER_IRQHandler /* 10: Dual Timer Interrupt */ - def_irq_default_handler APB_Slave2_IRQHandler /* 11: Reserved for APB Slave */ - def_irq_default_handler UARTOVF_IRQHandler /* 12: UART 0,1,2 Overflow Interrupt */ - def_irq_default_handler APB_Slave3_IRQHandler /* 13: Reserved for APB Slave */ - def_irq_default_handler RESERVED0_IRQHandler /* 14: Reserved */ - def_irq_default_handler TSC_IRQHandler /* 15: Touch Screen Interrupt */ - def_irq_default_handler PORT0_0_IRQHandler /* 16: GPIO Port 0 pin 0 Handler */ - def_irq_default_handler PORT0_1_IRQHandler /* 17: GPIO Port 0 pin 1 Handler */ - def_irq_default_handler PORT0_2_IRQHandler /* 18: GPIO Port 0 pin 2 Handler */ - def_irq_default_handler PORT0_3_IRQHandler /* 19: GPIO Port 0 pin 3 Handler */ - def_irq_default_handler PORT0_4_IRQHandler /* 20: GPIO Port 0 pin 4 Handler */ - def_irq_default_handler PORT0_5_IRQHandler /* 21: GPIO Port 0 pin 5 Handler */ - def_irq_default_handler PORT0_6_IRQHandler /* 22: GPIO Port 0 pin 6 Handler */ - def_irq_default_handler PORT0_7_IRQHandler /* 23: GPIO Port 0 pin 7 Handler */ - def_irq_default_handler PORT0_8_IRQHandler /* 24: GPIO Port 0 pin 8 Handler */ - def_irq_default_handler PORT0_9_IRQHandler /* 25: GPIO Port 0 pin 9 Handler */ - def_irq_default_handler PORT0_10_IRQHandler /* 26: GPIO Port 0 pin 10 Handler */ - def_irq_default_handler PORT0_11_IRQHandler /* 27: GPIO Port 0 pin 11 Handler */ - def_irq_default_handler PORT0_12_IRQHandler /* 28: GPIO Port 0 pin 12 Handler */ - def_irq_default_handler PORT0_13_IRQHandler /* 29: GPIO Port 0 pin 13 Handler */ - def_irq_default_handler PORT0_14_IRQHandler /* 30: GPIO Port 0 pin 14 Handler */ - def_irq_default_handler PORT0_15_IRQHandler /* 31: GPIO Port 0 pin 15 Handler */ - def_irq_default_handler FLASH0_IRQHandler /* 32: Reserved for Flash */ - def_irq_default_handler FLASH1_IRQHandler /* 33: Reserved for Flash */ - def_irq_default_handler RESERVED1_IRQHandler /* 34: Reserved */ - def_irq_default_handler RESERVED2_IRQHandler /* 35: Reserved */ - def_irq_default_handler RESERVED3_IRQHandler /* 36: Reserved */ - def_irq_default_handler RESERVED4_IRQHandler /* 37: Reserved */ - def_irq_default_handler RESERVED5_IRQHandler /* 38: Reserved */ - def_irq_default_handler RESERVED6_IRQHandler /* 39: Reserved */ - def_irq_default_handler RESERVED7_IRQHandler /* 40: Reserved */ - def_irq_default_handler RESERVED8_IRQHandler /* 41: Reserved */ - def_irq_default_handler PORT2_ALL_IRQHandler /* 42: GPIO Port 2 combined Interrupt */ - def_irq_default_handler PORT3_ALL_IRQHandler /* 43: GPIO Port 3 combined Interrupt */ - def_irq_default_handler TRNG_IRQHandler /* 44: Random number generator Interrupt */ - def_irq_default_handler UART2_IRQHandler /* 45: UART 2 RX and TX Combined Interrupt */ - def_irq_default_handler UART3_IRQHandler /* 46: UART 3 RX and TX Combined Interrupt */ - def_irq_default_handler ETHERNET_IRQHandler /* 47: Ethernet interrupt t.b.a. */ - def_irq_default_handler I2S_IRQHandler /* 48: I2S Interrupt */ - def_irq_default_handler MPS2_SPI0_IRQHandler /* 49: SPI Interrupt (spi header) */ - def_irq_default_handler MPS2_SPI1_IRQHandler /* 50: SPI Interrupt (clcd) */ - def_irq_default_handler MPS2_SPI2_IRQHandler /* 51: SPI Interrupt (spi 1 ADC replacement) */ - def_irq_default_handler MPS2_SPI3_IRQHandler /* 52: SPI Interrupt (spi 0 shield 0 replacement) */ - def_irq_default_handler MPS2_SPI4_IRQHandler /* 53: SPI Interrupt (shield 1) */ - def_irq_default_handler PORT4_ALL_IRQHandler /* 54: GPIO Port 4 combined Interrupt */ - def_irq_default_handler PORT5_ALL_IRQHandler /* 55: GPIO Port 5 combined Interrupt */ - def_irq_default_handler UART4_IRQHandler /* 56: UART 4 RX and TX Combined Interrupt */ + def_irq_default_handler UARTRX0_Handler /* 0: UART 0 RX Handler */ + def_irq_default_handler UARTTX0_Handler /* 1: UART 0 TX Handler */ + def_irq_default_handler UARTRX1_Handler /* 2: UART 1 RX Handler */ + def_irq_default_handler UARTTX1_Handler /* 3: UART 1 TX Handler */ + def_irq_default_handler UARTRX2_Handler /* 4: UART 2 RX Handler */ + def_irq_default_handler UARTTX2_Handler /* 5: UART 2 TX Handler */ + def_irq_default_handler PORT0_COMB_Handler /* 6: GPIO Port 0 Combined Handler */ + def_irq_default_handler PORT1_COMB_Handler /* 7: GPIO Port 1 Combined Handler */ + def_irq_default_handler TIMER0_Handler /* 8: TIMER 0 handler */ + def_irq_default_handler TIMER1_Handler /* 9: TIMER 1 handler */ + def_irq_default_handler DUALTIMER_HANDLER /* 10: Dual timer handler */ + def_irq_default_handler SPI_Handler /* 11: SPI exceptions Handler */ + def_irq_default_handler UARTOVF_Handler /* 12: UART 0,1,2 Overflow Handler */ + def_irq_default_handler ETHERNET_Handler /* 13: Ethernet Overflow Handler */ + def_irq_default_handler I2S_Handler /* 14: I2S Handler */ + def_irq_default_handler TSC_Handler /* 15: Touch Screen handler */ + def_irq_default_handler PORT2_COMB_Handler /* 16: GPIO Port 2 Combined Handler */ + def_irq_default_handler PORT3_COMB_Handler /* 17: GPIO Port 3 Combined Handler */ + def_irq_default_handler UARTRX3_Handler /* 18: UART 3 RX Handler */ + def_irq_default_handler UARTTX3_Handler /* 19: UART 3 TX Handler */ + def_irq_default_handler UARTRX4_Handler /* 20: UART 4 RX Handler */ + def_irq_default_handler UARTTX4_Handler /* 21: UART 4 TX Handler */ + def_irq_default_handler ADCSPI_Handler /* 22: SHIELD ADC SPI exceptions Handler */ + def_irq_default_handler SHIELDSPI_Handler /* 23: SHIELD SPI exceptions Handler */ + def_irq_default_handler PORT0_0_Handler /* 24: GPIO Port 0 pin 0 Handler */ + def_irq_default_handler PORT0_1_Handler /* 25: GPIO Port 0 pin 1 Handler */ + def_irq_default_handler PORT0_2_Handler /* 26: GPIO Port 0 pin 2 Handler */ + def_irq_default_handler PORT0_3_Handler /* 27: GPIO Port 0 pin 3 Handler */ + def_irq_default_handler PORT0_4_Handler /* 28: GPIO Port 0 pin 4 Handler */ + def_irq_default_handler PORT0_5_Handler /* 29: GPIO Port 0 pin 5 Handler */ + def_irq_default_handler PORT0_6_Handler /* 30: GPIO Port 0 pin 6 Handler */ + def_irq_default_handler PORT0_7_Handler /* 31: GPIO Port 0 pin 7 Handler */ .end diff --git a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M4/device/TOOLCHAIN_GCC_ARM/MPS2.ld b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M4/device/TOOLCHAIN_GCC_ARM/MPS2.ld index 31e576bf98..23435e3167 100644 --- a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M4/device/TOOLCHAIN_GCC_ARM/MPS2.ld +++ b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M4/device/TOOLCHAIN_GCC_ARM/MPS2.ld @@ -77,12 +77,12 @@ SECTIONS { __vector_table = .; KEEP(*(.vector_table)) - . = ALIGN(4); + . = ALIGN(8); } > VECTORS .text : { - . = ALIGN(4); + . = ALIGN(8); *(.text*) KEEP(*(.init)) @@ -121,30 +121,30 @@ SECTIONS .interrupts_ram : { - . = ALIGN(4); + . = ALIGN(8); __VECTOR_RAM__ = .; __interrupts_ram_start__ = .; /* Create a global symbol at data start */ . += M_VECTOR_RAM_SIZE; - . = ALIGN(4); + . = ALIGN(8); __interrupts_ram_end__ = .; /* Define a global symbol at data end */ } > RAM .data : { PROVIDE(__etext = LOADADDR(.data)); - . = ALIGN(4); + . = ALIGN(8); __data_start__ = .; *(vtable) *(.data) *(.data*) - . = ALIGN(4); + . = ALIGN(8); /* preinit data */ PROVIDE (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE (__preinit_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* init data */ PROVIDE (__init_array_start = .); KEEP(*(SORT(.init_array.*))) @@ -152,14 +152,14 @@ SECTIONS PROVIDE (__init_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* finit data */ PROVIDE (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE (__fini_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* All data end */ __data_end__ = .; @@ -177,13 +177,13 @@ SECTIONS .bss : { - . = ALIGN(4); + . = ALIGN(8); __START_BSS = .; __bss_start__ = .; *(.bss) *(.bss*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); __bss_end__ = .; __END_BSS = .; diff --git a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M4/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M4/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S index 57dc8d21f2..188f0de8bc 100644 --- a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M4/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S +++ b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M4/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S @@ -46,63 +46,38 @@ __isr_vector: .long SysTick_Handler /* SysTick Handler */ /* External Interrupts */ - .long UART0_IRQHandler /* 0: UART 0 RX and TX Combined Interrupt */ - .long Spare_IRQHandler /* 1: Undefined */ - .long UART1_IRQHandler /* 2: UART 1 RX and TX Combined Interrupt */ - .long APB_Slave0_IRQHandler /* 3: Reserved for APB Slave */ - .long APB_Slave1_IRQHandler /* 4: Reserved for APB Slave */ - .long RTC_IRQHandler /* 5: RTC Interrupt */ - .long PORT0_IRQHandler /* 6: GPIO Port 0 combined Interrupt */ - .long PORT1_ALL_IRQHandler /* 7: GPIO Port 1 combined Interrupt */ - .long TIMER0_IRQHandler /* 8: TIMER 0 Interrupt */ - .long TIMER1_IRQHandler /* 9: TIMER 1 Interrupt */ - .long DUALTIMER_IRQHandler /* 10: Dual Timer Interrupt */ - .long APB_Slave2_IRQHandler /* 11: Reserved for APB Slave */ - .long UARTOVF_IRQHandler /* 12: UART 0,1,2 Overflow Interrupt */ - .long APB_Slave3_IRQHandler /* 13: Reserved for APB Slave */ - .long RESERVED0_IRQHandler /* 14: Reserved */ - .long TSC_IRQHandler /* 15: Touch Screen Interrupt */ - .long PORT0_0_IRQHandler /* 16: GPIO Port 0 pin 0 Handler */ - .long PORT0_1_IRQHandler /* 17: GPIO Port 0 pin 1 Handler */ - .long PORT0_2_IRQHandler /* 18: GPIO Port 0 pin 2 Handler */ - .long PORT0_3_IRQHandler /* 19: GPIO Port 0 pin 3 Handler */ - .long PORT0_4_IRQHandler /* 20: GPIO Port 0 pin 4 Handler */ - .long PORT0_5_IRQHandler /* 21: GPIO Port 0 pin 5 Handler */ - .long PORT0_6_IRQHandler /* 22: GPIO Port 0 pin 6 Handler */ - .long PORT0_7_IRQHandler /* 23: GPIO Port 0 pin 7 Handler */ - .long PORT0_8_IRQHandler /* 24: GPIO Port 0 pin 8 Handler */ - .long PORT0_9_IRQHandler /* 25: GPIO Port 0 pin 9 Handler */ - .long PORT0_10_IRQHandler /* 26: GPIO Port 0 pin 10 Handler */ - .long PORT0_11_IRQHandler /* 27: GPIO Port 0 pin 11 Handler */ - .long PORT0_12_IRQHandler /* 28: GPIO Port 0 pin 12 Handler */ - .long PORT0_13_IRQHandler /* 29: GPIO Port 0 pin 13 Handler */ - .long PORT0_14_IRQHandler /* 30: GPIO Port 0 pin 14 Handler */ - .long PORT0_15_IRQHandler /* 31: GPIO Port 0 pin 15 Handler */ - .long FLASH0_IRQHandler /* 32: Reserved for Flash */ - .long FLASH1_IRQHandler /* 33: Reserved for Flash */ - .long RESERVED1_IRQHandler /* 34: Reserved */ - .long RESERVED2_IRQHandler /* 35: Reserved */ - .long RESERVED3_IRQHandler /* 36: Reserved */ - .long RESERVED4_IRQHandler /* 37: Reserved */ - .long RESERVED5_IRQHandler /* 38: Reserved */ - .long RESERVED6_IRQHandler /* 39: Reserved */ - .long RESERVED7_IRQHandler /* 40: Reserved */ - .long RESERVED8_IRQHandler /* 41: Reserved */ - .long PORT2_ALL_IRQHandler /* 42: GPIO Port 2 combined Interrupt */ - .long PORT3_ALL_IRQHandler /* 43: GPIO Port 3 combined Interrupt */ - .long TRNG_IRQHandler /* 44: Random number generator Interrupt */ - .long UART2_IRQHandler /* 45: UART 2 RX and TX Combined Interrupt */ - .long UART3_IRQHandler /* 46: UART 3 RX and TX Combined Interrupt */ - .long ETHERNET_IRQHandler /* 47: Ethernet interrupt t.b.a. */ - .long I2S_IRQHandler /* 48: I2S Interrupt */ - .long MPS2_SPI0_IRQHandler /* 49: SPI Interrupt (spi header) */ - .long MPS2_SPI1_IRQHandler /* 50: SPI Interrupt (clcd) */ - .long MPS2_SPI2_IRQHandler /* 51: SPI Interrupt (spi 1 ADC replacement) */ - .long MPS2_SPI3_IRQHandler /* 52: SPI Interrupt (spi 0 shield 0 replacement) */ - .long MPS2_SPI4_IRQHandler /* 53: SPI Interrupt (shield 1) */ - .long PORT4_ALL_IRQHandler /* 54: GPIO Port 4 combined Interrupt */ - .long PORT5_ALL_IRQHandler /* 55: GPIO Port 5 combined Interrupt */ - .long UART4_IRQHandler /* 56: UART 4 RX and TX Combined Interrupt */ + .long UARTRX0_Handler /* UART 0 RX Handler */ + .long UARTTX0_Handler /* UART 0 TX Handler */ + .long UARTRX1_Handler /* UART 1 RX Handler */ + .long UARTTX1_Handler /* UART 1 TX Handler */ + .long UARTRX2_Handler /* UART 2 RX Handler */ + .long UARTTX2_Handler /* UART 2 TX Handler */ + .long PORT0_COMB_Handler /* GPIO Port 0 Combined Handler */ + .long PORT1_COMB_Handler /* GPIO Port 1 Combined Handler */ + .long TIMER0_Handler /* TIMER 0 handler */ + .long TIMER1_Handler /* TIMER 1 handler */ + .long DUALTIMER_HANDLER /* Dual timer handler */ + .long SPI_Handler /* SPI exceptions Handler */ + .long UARTOVF_Handler /* UART 0,1,2 Overflow Handler */ + .long ETHERNET_Handler /* Ethernet Overflow Handler */ + .long I2S_Handler /* I2S Handler */ + .long TSC_Handler /* Touch Screen handler */ + .long PORT2_COMB_Handler /* GPIO Port 2 Combined Handler */ + .long PORT3_COMB_Handler /* GPIO Port 3 Combined Handler */ + .long UARTRX3_Handler /* UART 3 RX Handler */ + .long UARTTX3_Handler /* UART 3 TX Handler */ + .long UARTRX4_Handler /* UART 4 RX Handler */ + .long UARTTX4_Handler /* UART 4 TX Handler */ + .long ADCSPI_Handler /* SHIELD ADC SPI exceptions Handler */ + .long SHIELDSPI_Handler /* SHIELD SPI exceptions Handler */ + .long PORT0_0_Handler /* GPIO Port 0 pin 0 Handler */ + .long PORT0_1_Handler /* GPIO Port 0 pin 1 Handler */ + .long PORT0_2_Handler /* GPIO Port 0 pin 2 Handler */ + .long PORT0_3_Handler /* GPIO Port 0 pin 3 Handler */ + .long PORT0_4_Handler /* GPIO Port 0 pin 4 Handler */ + .long PORT0_5_Handler /* GPIO Port 0 pin 5 Handler */ + .long PORT0_6_Handler /* GPIO Port 0 pin 6 Handler */ + .long PORT0_7_Handler /* GPIO Port 0 pin 7 Handler */ .size __isr_vector, . - __isr_vector @@ -196,62 +171,37 @@ system_startup: .endm /* External interrupts */ - def_irq_default_handler UART0_IRQHandler /* 0: UART 0 RX and TX Combined Interrupt */ - def_irq_default_handler Spare_IRQHandler /* 1: Undefined */ - def_irq_default_handler UART1_IRQHandler /* 2: UART 1 RX and TX Combined Interrupt */ - def_irq_default_handler APB_Slave0_IRQHandler /* 3: Reserved for APB Slave */ - def_irq_default_handler APB_Slave1_IRQHandler /* 4: Reserved for APB Slave */ - def_irq_default_handler RTC_IRQHandler /* 5: RTC Interrupt */ - def_irq_default_handler PORT0_IRQHandler /* 6: GPIO Port 0 combined Interrupt */ - def_irq_default_handler PORT1_ALL_IRQHandler /* 7: GPIO Port 1 combined Interrupt */ - def_irq_default_handler TIMER0_IRQHandler /* 8: TIMER 0 Interrupt */ - def_irq_default_handler TIMER1_IRQHandler /* 9: TIMER 1 Interrupt */ - def_irq_default_handler DUALTIMER_IRQHandler /* 10: Dual Timer Interrupt */ - def_irq_default_handler APB_Slave2_IRQHandler /* 11: Reserved for APB Slave */ - def_irq_default_handler UARTOVF_IRQHandler /* 12: UART 0,1,2 Overflow Interrupt */ - def_irq_default_handler APB_Slave3_IRQHandler /* 13: Reserved for APB Slave */ - def_irq_default_handler RESERVED0_IRQHandler /* 14: Reserved */ - def_irq_default_handler TSC_IRQHandler /* 15: Touch Screen Interrupt */ - def_irq_default_handler PORT0_0_IRQHandler /* 16: GPIO Port 0 pin 0 Handler */ - def_irq_default_handler PORT0_1_IRQHandler /* 17: GPIO Port 0 pin 1 Handler */ - def_irq_default_handler PORT0_2_IRQHandler /* 18: GPIO Port 0 pin 2 Handler */ - def_irq_default_handler PORT0_3_IRQHandler /* 19: GPIO Port 0 pin 3 Handler */ - def_irq_default_handler PORT0_4_IRQHandler /* 20: GPIO Port 0 pin 4 Handler */ - def_irq_default_handler PORT0_5_IRQHandler /* 21: GPIO Port 0 pin 5 Handler */ - def_irq_default_handler PORT0_6_IRQHandler /* 22: GPIO Port 0 pin 6 Handler */ - def_irq_default_handler PORT0_7_IRQHandler /* 23: GPIO Port 0 pin 7 Handler */ - def_irq_default_handler PORT0_8_IRQHandler /* 24: GPIO Port 0 pin 8 Handler */ - def_irq_default_handler PORT0_9_IRQHandler /* 25: GPIO Port 0 pin 9 Handler */ - def_irq_default_handler PORT0_10_IRQHandler /* 26: GPIO Port 0 pin 10 Handler */ - def_irq_default_handler PORT0_11_IRQHandler /* 27: GPIO Port 0 pin 11 Handler */ - def_irq_default_handler PORT0_12_IRQHandler /* 28: GPIO Port 0 pin 12 Handler */ - def_irq_default_handler PORT0_13_IRQHandler /* 29: GPIO Port 0 pin 13 Handler */ - def_irq_default_handler PORT0_14_IRQHandler /* 30: GPIO Port 0 pin 14 Handler */ - def_irq_default_handler PORT0_15_IRQHandler /* 31: GPIO Port 0 pin 15 Handler */ - def_irq_default_handler FLASH0_IRQHandler /* 32: Reserved for Flash */ - def_irq_default_handler FLASH1_IRQHandler /* 33: Reserved for Flash */ - def_irq_default_handler RESERVED1_IRQHandler /* 34: Reserved */ - def_irq_default_handler RESERVED2_IRQHandler /* 35: Reserved */ - def_irq_default_handler RESERVED3_IRQHandler /* 36: Reserved */ - def_irq_default_handler RESERVED4_IRQHandler /* 37: Reserved */ - def_irq_default_handler RESERVED5_IRQHandler /* 38: Reserved */ - def_irq_default_handler RESERVED6_IRQHandler /* 39: Reserved */ - def_irq_default_handler RESERVED7_IRQHandler /* 40: Reserved */ - def_irq_default_handler RESERVED8_IRQHandler /* 41: Reserved */ - def_irq_default_handler PORT2_ALL_IRQHandler /* 42: GPIO Port 2 combined Interrupt */ - def_irq_default_handler PORT3_ALL_IRQHandler /* 43: GPIO Port 3 combined Interrupt */ - def_irq_default_handler TRNG_IRQHandler /* 44: Random number generator Interrupt */ - def_irq_default_handler UART2_IRQHandler /* 45: UART 2 RX and TX Combined Interrupt */ - def_irq_default_handler UART3_IRQHandler /* 46: UART 3 RX and TX Combined Interrupt */ - def_irq_default_handler ETHERNET_IRQHandler /* 47: Ethernet interrupt t.b.a. */ - def_irq_default_handler I2S_IRQHandler /* 48: I2S Interrupt */ - def_irq_default_handler MPS2_SPI0_IRQHandler /* 49: SPI Interrupt (spi header) */ - def_irq_default_handler MPS2_SPI1_IRQHandler /* 50: SPI Interrupt (clcd) */ - def_irq_default_handler MPS2_SPI2_IRQHandler /* 51: SPI Interrupt (spi 1 ADC replacement) */ - def_irq_default_handler MPS2_SPI3_IRQHandler /* 52: SPI Interrupt (spi 0 shield 0 replacement) */ - def_irq_default_handler MPS2_SPI4_IRQHandler /* 53: SPI Interrupt (shield 1) */ - def_irq_default_handler PORT4_ALL_IRQHandler /* 54: GPIO Port 4 combined Interrupt */ - def_irq_default_handler PORT5_ALL_IRQHandler /* 55: GPIO Port 5 combined Interrupt */ - def_irq_default_handler UART4_IRQHandler /* 56: UART 4 RX and TX Combined Interrupt */ + def_irq_default_handler UARTRX0_Handler /* 0: UART 0 RX Handler */ + def_irq_default_handler UARTTX0_Handler /* 1: UART 0 TX Handler */ + def_irq_default_handler UARTRX1_Handler /* 2: UART 1 RX Handler */ + def_irq_default_handler UARTTX1_Handler /* 3: UART 1 TX Handler */ + def_irq_default_handler UARTRX2_Handler /* 4: UART 2 RX Handler */ + def_irq_default_handler UARTTX2_Handler /* 5: UART 2 TX Handler */ + def_irq_default_handler PORT0_COMB_Handler /* 6: GPIO Port 0 Combined Handler */ + def_irq_default_handler PORT1_COMB_Handler /* 7: GPIO Port 1 Combined Handler */ + def_irq_default_handler TIMER0_Handler /* 8: TIMER 0 handler */ + def_irq_default_handler TIMER1_Handler /* 9: TIMER 1 handler */ + def_irq_default_handler DUALTIMER_HANDLER /* 10: Dual timer handler */ + def_irq_default_handler SPI_Handler /* 11: SPI exceptions Handler */ + def_irq_default_handler UARTOVF_Handler /* 12: UART 0,1,2 Overflow Handler */ + def_irq_default_handler ETHERNET_Handler /* 13: Ethernet Overflow Handler */ + def_irq_default_handler I2S_Handler /* 14: I2S Handler */ + def_irq_default_handler TSC_Handler /* 15: Touch Screen handler */ + def_irq_default_handler PORT2_COMB_Handler /* 16: GPIO Port 2 Combined Handler */ + def_irq_default_handler PORT3_COMB_Handler /* 17: GPIO Port 3 Combined Handler */ + def_irq_default_handler UARTRX3_Handler /* 18: UART 3 RX Handler */ + def_irq_default_handler UARTTX3_Handler /* 19: UART 3 TX Handler */ + def_irq_default_handler UARTRX4_Handler /* 20: UART 4 RX Handler */ + def_irq_default_handler UARTTX4_Handler /* 21: UART 4 TX Handler */ + def_irq_default_handler ADCSPI_Handler /* 22: SHIELD ADC SPI exceptions Handler */ + def_irq_default_handler SHIELDSPI_Handler /* 23: SHIELD SPI exceptions Handler */ + def_irq_default_handler PORT0_0_Handler /* 24: GPIO Port 0 pin 0 Handler */ + def_irq_default_handler PORT0_1_Handler /* 25: GPIO Port 0 pin 1 Handler */ + def_irq_default_handler PORT0_2_Handler /* 26: GPIO Port 0 pin 2 Handler */ + def_irq_default_handler PORT0_3_Handler /* 27: GPIO Port 0 pin 3 Handler */ + def_irq_default_handler PORT0_4_Handler /* 28: GPIO Port 0 pin 4 Handler */ + def_irq_default_handler PORT0_5_Handler /* 29: GPIO Port 0 pin 5 Handler */ + def_irq_default_handler PORT0_6_Handler /* 30: GPIO Port 0 pin 6 Handler */ + def_irq_default_handler PORT0_7_Handler /* 31: GPIO Port 0 pin 7 Handler */ .end diff --git a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M7/device/TOOLCHAIN_GCC_ARM/MPS2.ld b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M7/device/TOOLCHAIN_GCC_ARM/MPS2.ld index df16163d48..8e065ba413 100644 --- a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M7/device/TOOLCHAIN_GCC_ARM/MPS2.ld +++ b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M7/device/TOOLCHAIN_GCC_ARM/MPS2.ld @@ -77,12 +77,12 @@ SECTIONS { __vector_table = .; KEEP(*(.vector_table)) - . = ALIGN(4); + . = ALIGN(8); } > VECTORS .text : { - . = ALIGN(4); + . = ALIGN(8); *(.text*) KEEP(*(.init)) @@ -121,30 +121,30 @@ SECTIONS .interrupts_ram : { - . = ALIGN(4); + . = ALIGN(8); __VECTOR_RAM__ = .; __interrupts_ram_start__ = .; /* Create a global symbol at data start */ . += M_VECTOR_RAM_SIZE; - . = ALIGN(4); + . = ALIGN(8); __interrupts_ram_end__ = .; /* Define a global symbol at data end */ } > RAM .data : { PROVIDE(__etext = LOADADDR(.data)); - . = ALIGN(4); + . = ALIGN(8); __data_start__ = .; *(vtable) *(.data) *(.data*) - . = ALIGN(4); + . = ALIGN(8); /* preinit data */ PROVIDE (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE (__preinit_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* init data */ PROVIDE (__init_array_start = .); KEEP(*(SORT(.init_array.*))) @@ -152,14 +152,14 @@ SECTIONS PROVIDE (__init_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* finit data */ PROVIDE (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE (__fini_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* All data end */ __data_end__ = .; @@ -177,13 +177,13 @@ SECTIONS .bss : { - . = ALIGN(4); + . = ALIGN(8); __START_BSS = .; __bss_start__ = .; *(.bss) *(.bss*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); __bss_end__ = .; __END_BSS = .; diff --git a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M7/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M7/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S index c5d12692ec..a47f9ea383 100644 --- a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M7/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S +++ b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/TARGET_FVP_MPS2_M7/device/TOOLCHAIN_GCC_ARM/startup_MPS2.S @@ -46,63 +46,38 @@ __isr_vector: .long SysTick_Handler /* SysTick Handler */ /* External Interrupts */ - .long UART0_IRQHandler /* 0: UART 0 RX and TX Combined Interrupt */ - .long Spare_IRQHandler /* 1: Undefined */ - .long UART1_IRQHandler /* 2: UART 1 RX and TX Combined Interrupt */ - .long APB_Slave0_IRQHandler /* 3: Reserved for APB Slave */ - .long APB_Slave1_IRQHandler /* 4: Reserved for APB Slave */ - .long RTC_IRQHandler /* 5: RTC Interrupt */ - .long PORT0_IRQHandler /* 6: GPIO Port 0 combined Interrupt */ - .long PORT1_ALL_IRQHandler /* 7: GPIO Port 1 combined Interrupt */ - .long TIMER0_IRQHandler /* 8: TIMER 0 Interrupt */ - .long TIMER1_IRQHandler /* 9: TIMER 1 Interrupt */ - .long DUALTIMER_IRQHandler /* 10: Dual Timer Interrupt */ - .long APB_Slave2_IRQHandler /* 11: Reserved for APB Slave */ - .long UARTOVF_IRQHandler /* 12: UART 0,1,2 Overflow Interrupt */ - .long APB_Slave3_IRQHandler /* 13: Reserved for APB Slave */ - .long RESERVED0_IRQHandler /* 14: Reserved */ - .long TSC_IRQHandler /* 15: Touch Screen Interrupt */ - .long PORT0_0_IRQHandler /* 16: GPIO Port 0 pin 0 Handler */ - .long PORT0_1_IRQHandler /* 17: GPIO Port 0 pin 1 Handler */ - .long PORT0_2_IRQHandler /* 18: GPIO Port 0 pin 2 Handler */ - .long PORT0_3_IRQHandler /* 19: GPIO Port 0 pin 3 Handler */ - .long PORT0_4_IRQHandler /* 20: GPIO Port 0 pin 4 Handler */ - .long PORT0_5_IRQHandler /* 21: GPIO Port 0 pin 5 Handler */ - .long PORT0_6_IRQHandler /* 22: GPIO Port 0 pin 6 Handler */ - .long PORT0_7_IRQHandler /* 23: GPIO Port 0 pin 7 Handler */ - .long PORT0_8_IRQHandler /* 24: GPIO Port 0 pin 8 Handler */ - .long PORT0_9_IRQHandler /* 25: GPIO Port 0 pin 9 Handler */ - .long PORT0_10_IRQHandler /* 26: GPIO Port 0 pin 10 Handler */ - .long PORT0_11_IRQHandler /* 27: GPIO Port 0 pin 11 Handler */ - .long PORT0_12_IRQHandler /* 28: GPIO Port 0 pin 12 Handler */ - .long PORT0_13_IRQHandler /* 29: GPIO Port 0 pin 13 Handler */ - .long PORT0_14_IRQHandler /* 30: GPIO Port 0 pin 14 Handler */ - .long PORT0_15_IRQHandler /* 31: GPIO Port 0 pin 15 Handler */ - .long FLASH0_IRQHandler /* 32: Reserved for Flash */ - .long FLASH1_IRQHandler /* 33: Reserved for Flash */ - .long RESERVED1_IRQHandler /* 34: Reserved */ - .long RESERVED2_IRQHandler /* 35: Reserved */ - .long RESERVED3_IRQHandler /* 36: Reserved */ - .long RESERVED4_IRQHandler /* 37: Reserved */ - .long RESERVED5_IRQHandler /* 38: Reserved */ - .long RESERVED6_IRQHandler /* 39: Reserved */ - .long RESERVED7_IRQHandler /* 40: Reserved */ - .long RESERVED8_IRQHandler /* 41: Reserved */ - .long PORT2_ALL_IRQHandler /* 42: GPIO Port 2 combined Interrupt */ - .long PORT3_ALL_IRQHandler /* 43: GPIO Port 3 combined Interrupt */ - .long TRNG_IRQHandler /* 44: Random number generator Interrupt */ - .long UART2_IRQHandler /* 45: UART 2 RX and TX Combined Interrupt */ - .long UART3_IRQHandler /* 46: UART 3 RX and TX Combined Interrupt */ - .long ETHERNET_IRQHandler /* 47: Ethernet interrupt t.b.a. */ - .long I2S_IRQHandler /* 48: I2S Interrupt */ - .long MPS2_SPI0_IRQHandler /* 49: SPI Interrupt (spi header) */ - .long MPS2_SPI1_IRQHandler /* 50: SPI Interrupt (clcd) */ - .long MPS2_SPI2_IRQHandler /* 51: SPI Interrupt (spi 1 ADC replacement) */ - .long MPS2_SPI3_IRQHandler /* 52: SPI Interrupt (spi 0 shield 0 replacement) */ - .long MPS2_SPI4_IRQHandler /* 53: SPI Interrupt (shield 1) */ - .long PORT4_ALL_IRQHandler /* 54: GPIO Port 4 combined Interrupt */ - .long PORT5_ALL_IRQHandler /* 55: GPIO Port 5 combined Interrupt */ - .long UART4_IRQHandler /* 56: UART 4 RX and TX Combined Interrupt */ + .long UARTRX0_Handler /* UART 0 RX Handler */ + .long UARTTX0_Handler /* UART 0 TX Handler */ + .long UARTRX1_Handler /* UART 1 RX Handler */ + .long UARTTX1_Handler /* UART 1 TX Handler */ + .long UARTRX2_Handler /* UART 2 RX Handler */ + .long UARTTX2_Handler /* UART 2 TX Handler */ + .long PORT0_COMB_Handler /* GPIO Port 0 Combined Handler */ + .long PORT1_COMB_Handler /* GPIO Port 1 Combined Handler */ + .long TIMER0_Handler /* TIMER 0 handler */ + .long TIMER1_Handler /* TIMER 1 handler */ + .long DUALTIMER_HANDLER /* Dual timer handler */ + .long SPI_Handler /* SPI exceptions Handler */ + .long UARTOVF_Handler /* UART 0,1,2 Overflow Handler */ + .long ETHERNET_Handler /* Ethernet Overflow Handler */ + .long I2S_Handler /* I2S Handler */ + .long TSC_Handler /* Touch Screen handler */ + .long PORT2_COMB_Handler /* GPIO Port 2 Combined Handler */ + .long PORT3_COMB_Handler /* GPIO Port 3 Combined Handler */ + .long UARTRX3_Handler /* UART 3 RX Handler */ + .long UARTTX3_Handler /* UART 3 TX Handler */ + .long UARTRX4_Handler /* UART 4 RX Handler */ + .long UARTTX4_Handler /* UART 4 TX Handler */ + .long ADCSPI_Handler /* SHIELD ADC SPI exceptions Handler */ + .long SHIELDSPI_Handler /* SHIELD SPI exceptions Handler */ + .long PORT0_0_Handler /* GPIO Port 0 pin 0 Handler */ + .long PORT0_1_Handler /* GPIO Port 0 pin 1 Handler */ + .long PORT0_2_Handler /* GPIO Port 0 pin 2 Handler */ + .long PORT0_3_Handler /* GPIO Port 0 pin 3 Handler */ + .long PORT0_4_Handler /* GPIO Port 0 pin 4 Handler */ + .long PORT0_5_Handler /* GPIO Port 0 pin 5 Handler */ + .long PORT0_6_Handler /* GPIO Port 0 pin 6 Handler */ + .long PORT0_7_Handler /* GPIO Port 0 pin 7 Handler */ .size __isr_vector, . - __isr_vector @@ -196,62 +171,37 @@ system_startup: .endm /* External interrupts */ - def_irq_default_handler UART0_IRQHandler /* 0: UART 0 RX and TX Combined Interrupt */ - def_irq_default_handler Spare_IRQHandler /* 1: Undefined */ - def_irq_default_handler UART1_IRQHandler /* 2: UART 1 RX and TX Combined Interrupt */ - def_irq_default_handler APB_Slave0_IRQHandler /* 3: Reserved for APB Slave */ - def_irq_default_handler APB_Slave1_IRQHandler /* 4: Reserved for APB Slave */ - def_irq_default_handler RTC_IRQHandler /* 5: RTC Interrupt */ - def_irq_default_handler PORT0_IRQHandler /* 6: GPIO Port 0 combined Interrupt */ - def_irq_default_handler PORT1_ALL_IRQHandler /* 7: GPIO Port 1 combined Interrupt */ - def_irq_default_handler TIMER0_IRQHandler /* 8: TIMER 0 Interrupt */ - def_irq_default_handler TIMER1_IRQHandler /* 9: TIMER 1 Interrupt */ - def_irq_default_handler DUALTIMER_IRQHandler /* 10: Dual Timer Interrupt */ - def_irq_default_handler APB_Slave2_IRQHandler /* 11: Reserved for APB Slave */ - def_irq_default_handler UARTOVF_IRQHandler /* 12: UART 0,1,2 Overflow Interrupt */ - def_irq_default_handler APB_Slave3_IRQHandler /* 13: Reserved for APB Slave */ - def_irq_default_handler RESERVED0_IRQHandler /* 14: Reserved */ - def_irq_default_handler TSC_IRQHandler /* 15: Touch Screen Interrupt */ - def_irq_default_handler PORT0_0_IRQHandler /* 16: GPIO Port 0 pin 0 Handler */ - def_irq_default_handler PORT0_1_IRQHandler /* 17: GPIO Port 0 pin 1 Handler */ - def_irq_default_handler PORT0_2_IRQHandler /* 18: GPIO Port 0 pin 2 Handler */ - def_irq_default_handler PORT0_3_IRQHandler /* 19: GPIO Port 0 pin 3 Handler */ - def_irq_default_handler PORT0_4_IRQHandler /* 20: GPIO Port 0 pin 4 Handler */ - def_irq_default_handler PORT0_5_IRQHandler /* 21: GPIO Port 0 pin 5 Handler */ - def_irq_default_handler PORT0_6_IRQHandler /* 22: GPIO Port 0 pin 6 Handler */ - def_irq_default_handler PORT0_7_IRQHandler /* 23: GPIO Port 0 pin 7 Handler */ - def_irq_default_handler PORT0_8_IRQHandler /* 24: GPIO Port 0 pin 8 Handler */ - def_irq_default_handler PORT0_9_IRQHandler /* 25: GPIO Port 0 pin 9 Handler */ - def_irq_default_handler PORT0_10_IRQHandler /* 26: GPIO Port 0 pin 10 Handler */ - def_irq_default_handler PORT0_11_IRQHandler /* 27: GPIO Port 0 pin 11 Handler */ - def_irq_default_handler PORT0_12_IRQHandler /* 28: GPIO Port 0 pin 12 Handler */ - def_irq_default_handler PORT0_13_IRQHandler /* 29: GPIO Port 0 pin 13 Handler */ - def_irq_default_handler PORT0_14_IRQHandler /* 30: GPIO Port 0 pin 14 Handler */ - def_irq_default_handler PORT0_15_IRQHandler /* 31: GPIO Port 0 pin 15 Handler */ - def_irq_default_handler FLASH0_IRQHandler /* 32: Reserved for Flash */ - def_irq_default_handler FLASH1_IRQHandler /* 33: Reserved for Flash */ - def_irq_default_handler RESERVED1_IRQHandler /* 34: Reserved */ - def_irq_default_handler RESERVED2_IRQHandler /* 35: Reserved */ - def_irq_default_handler RESERVED3_IRQHandler /* 36: Reserved */ - def_irq_default_handler RESERVED4_IRQHandler /* 37: Reserved */ - def_irq_default_handler RESERVED5_IRQHandler /* 38: Reserved */ - def_irq_default_handler RESERVED6_IRQHandler /* 39: Reserved */ - def_irq_default_handler RESERVED7_IRQHandler /* 40: Reserved */ - def_irq_default_handler RESERVED8_IRQHandler /* 41: Reserved */ - def_irq_default_handler PORT2_ALL_IRQHandler /* 42: GPIO Port 2 combined Interrupt */ - def_irq_default_handler PORT3_ALL_IRQHandler /* 43: GPIO Port 3 combined Interrupt */ - def_irq_default_handler TRNG_IRQHandler /* 44: Random number generator Interrupt */ - def_irq_default_handler UART2_IRQHandler /* 45: UART 2 RX and TX Combined Interrupt */ - def_irq_default_handler UART3_IRQHandler /* 46: UART 3 RX and TX Combined Interrupt */ - def_irq_default_handler ETHERNET_IRQHandler /* 47: Ethernet interrupt t.b.a. */ - def_irq_default_handler I2S_IRQHandler /* 48: I2S Interrupt */ - def_irq_default_handler MPS2_SPI0_IRQHandler /* 49: SPI Interrupt (spi header) */ - def_irq_default_handler MPS2_SPI1_IRQHandler /* 50: SPI Interrupt (clcd) */ - def_irq_default_handler MPS2_SPI2_IRQHandler /* 51: SPI Interrupt (spi 1 ADC replacement) */ - def_irq_default_handler MPS2_SPI3_IRQHandler /* 52: SPI Interrupt (spi 0 shield 0 replacement) */ - def_irq_default_handler MPS2_SPI4_IRQHandler /* 53: SPI Interrupt (shield 1) */ - def_irq_default_handler PORT4_ALL_IRQHandler /* 54: GPIO Port 4 combined Interrupt */ - def_irq_default_handler PORT5_ALL_IRQHandler /* 55: GPIO Port 5 combined Interrupt */ - def_irq_default_handler UART4_IRQHandler /* 56: UART 4 RX and TX Combined Interrupt */ + def_irq_default_handler UARTRX0_Handler /* 0: UART 0 RX Handler */ + def_irq_default_handler UARTTX0_Handler /* 1: UART 0 TX Handler */ + def_irq_default_handler UARTRX1_Handler /* 2: UART 1 RX Handler */ + def_irq_default_handler UARTTX1_Handler /* 3: UART 1 TX Handler */ + def_irq_default_handler UARTRX2_Handler /* 4: UART 2 RX Handler */ + def_irq_default_handler UARTTX2_Handler /* 5: UART 2 TX Handler */ + def_irq_default_handler PORT0_COMB_Handler /* 6: GPIO Port 0 Combined Handler */ + def_irq_default_handler PORT1_COMB_Handler /* 7: GPIO Port 1 Combined Handler */ + def_irq_default_handler TIMER0_Handler /* 8: TIMER 0 handler */ + def_irq_default_handler TIMER1_Handler /* 9: TIMER 1 handler */ + def_irq_default_handler DUALTIMER_HANDLER /* 10: Dual timer handler */ + def_irq_default_handler SPI_Handler /* 11: SPI exceptions Handler */ + def_irq_default_handler UARTOVF_Handler /* 12: UART 0,1,2 Overflow Handler */ + def_irq_default_handler ETHERNET_Handler /* 13: Ethernet Overflow Handler */ + def_irq_default_handler I2S_Handler /* 14: I2S Handler */ + def_irq_default_handler TSC_Handler /* 15: Touch Screen handler */ + def_irq_default_handler PORT2_COMB_Handler /* 16: GPIO Port 2 Combined Handler */ + def_irq_default_handler PORT3_COMB_Handler /* 17: GPIO Port 3 Combined Handler */ + def_irq_default_handler UARTRX3_Handler /* 18: UART 3 RX Handler */ + def_irq_default_handler UARTTX3_Handler /* 19: UART 3 TX Handler */ + def_irq_default_handler UARTRX4_Handler /* 20: UART 4 RX Handler */ + def_irq_default_handler UARTTX4_Handler /* 21: UART 4 TX Handler */ + def_irq_default_handler ADCSPI_Handler /* 22: SHIELD ADC SPI exceptions Handler */ + def_irq_default_handler SHIELDSPI_Handler /* 23: SHIELD SPI exceptions Handler */ + def_irq_default_handler PORT0_0_Handler /* 24: GPIO Port 0 pin 0 Handler */ + def_irq_default_handler PORT0_1_Handler /* 25: GPIO Port 0 pin 1 Handler */ + def_irq_default_handler PORT0_2_Handler /* 26: GPIO Port 0 pin 2 Handler */ + def_irq_default_handler PORT0_3_Handler /* 27: GPIO Port 0 pin 3 Handler */ + def_irq_default_handler PORT0_4_Handler /* 28: GPIO Port 0 pin 4 Handler */ + def_irq_default_handler PORT0_5_Handler /* 29: GPIO Port 0 pin 5 Handler */ + def_irq_default_handler PORT0_6_Handler /* 30: GPIO Port 0 pin 6 Handler */ + def_irq_default_handler PORT0_7_Handler /* 31: GPIO Port 0 pin 7 Handler */ .end diff --git a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/flash_api.c b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/flash_api.c index 019388a145..3fe832baf2 100644 --- a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/flash_api.c +++ b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/flash_api.c @@ -101,3 +101,10 @@ uint32_t flash_get_size(const flash_t *obj) return ZBT_SRAM1_SIZE; } + +uint8_t flash_get_erase_value(const flash_t *obj) +{ + (void)obj; + + return 0xFF; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_BEETLE/device/TOOLCHAIN_GCC_ARM/BEETLE.ld b/targets/TARGET_ARM_SSG/TARGET_BEETLE/device/TOOLCHAIN_GCC_ARM/BEETLE.ld index 5dd39c76d0..176804cb47 100644 --- a/targets/TARGET_ARM_SSG/TARGET_BEETLE/device/TOOLCHAIN_GCC_ARM/BEETLE.ld +++ b/targets/TARGET_ARM_SSG/TARGET_BEETLE/device/TOOLCHAIN_GCC_ARM/BEETLE.ld @@ -75,7 +75,7 @@ SECTIONS { __vector_table = .; KEEP(*(.vector_table)) - . = ALIGN(4); + . = ALIGN(8); } > VECTORS .text : @@ -124,30 +124,30 @@ SECTIONS .interrupts_ram : { - . = ALIGN(4); + . = ALIGN(8); __VECTOR_RAM__ = .; __interrupts_ram_start__ = .; /* Create a global symbol at data start */ . += M_VECTOR_RAM_SIZE; - . = ALIGN(4); + . = ALIGN(8); __interrupts_ram_end__ = .; /* Define a global symbol at data end */ } > RAM .data : { PROVIDE(__etext = LOADADDR(.data)); - . = ALIGN(4); + . = ALIGN(8); __data_start__ = .; *(vtable) *(.data) *(.data*) - . = ALIGN(4); + . = ALIGN(8); /* preinit data */ PROVIDE (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE (__preinit_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* init data */ PROVIDE (__init_array_start = .); KEEP(*(SORT(.init_array.*))) @@ -155,14 +155,14 @@ SECTIONS PROVIDE (__init_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* finit data */ PROVIDE (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE (__fini_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* All data end */ __data_end__ = .; @@ -182,13 +182,13 @@ SECTIONS .bss : { - . = ALIGN(4); + . = ALIGN(8); __START_BSS = .; __bss_start__ = .; *(.bss) *(.bss*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); __bss_end__ = .; __END_BSS = .; diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/TOOLCHAIN_GCC_ARM/MPS2.ld b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/TOOLCHAIN_GCC_ARM/MPS2.ld index c0cc2f68be..0fc60f6594 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/TOOLCHAIN_GCC_ARM/MPS2.ld +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/TOOLCHAIN_GCC_ARM/MPS2.ld @@ -72,12 +72,12 @@ SECTIONS { __vector_table = .; KEEP(*(.vector_table)) - . = ALIGN(4); + . = ALIGN(8); } > VECTORS .text : { - . = ALIGN(4); + . = ALIGN(8); *(.text*) KEEP(*(.init)) @@ -116,30 +116,30 @@ SECTIONS .interrupts_ram : { - . = ALIGN(4); + . = ALIGN(8); __VECTOR_RAM__ = .; __interrupts_ram_start__ = .; /* Create a global symbol at data start */ . += M_VECTOR_RAM_SIZE; - . = ALIGN(4); + . = ALIGN(8); __interrupts_ram_end__ = .; /* Define a global symbol at data end */ } > RAM .data : { PROVIDE(__etext = LOADADDR(.data)); - . = ALIGN(4); + . = ALIGN(8); __data_start__ = .; *(vtable) *(.data) *(.data*) - . = ALIGN(4); + . = ALIGN(8); /* preinit data */ PROVIDE (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE (__preinit_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* init data */ PROVIDE (__init_array_start = .); KEEP(*(SORT(.init_array.*))) @@ -147,14 +147,14 @@ SECTIONS PROVIDE (__init_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* finit data */ PROVIDE (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE (__fini_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* All data end */ __data_end__ = .; @@ -172,13 +172,13 @@ SECTIONS .bss : { - . = ALIGN(4); + . = ALIGN(8); __START_BSS = .; __bss_start__ = .; *(.bss) *(.bss*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); __bss_end__ = .; __END_BSS = .; diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h index dd39c21a0a..b18568b0d3 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h @@ -58,4 +58,10 @@ #define ARM_UART3 #define ARM_UART4 +/* SMSC9220 Ethernet */ +#ifdef COMPONENT_SMSC9220 +#define SMSC9220_ETH +#define SMSC9220_Ethernet_Interrupt_Handler ETHERNET_IRQHandler +#endif + #endif /* __ARM_LTD_DEVICE_CFG_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth.c deleted file mode 100644 index 0fee077abf..0000000000 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth.c +++ /dev/null @@ -1,746 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017-2018 ARM Limited - * - * 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. - */ - -/* - * Code implementation file for the LAN Ethernet interface. - * - * This file is the based on mps2_ethernet_api and Selftest's ETH_MPS2. - * MPS2 Selftest:https://silver.arm.com/browse/VEI10 -> - * \ISCM-1-0\AN491\software\Selftest\v2m_mps2\ - */ - -#include - -#include "mbed_retarget.h" -#include "mbed_wait_api.h" -#include "CM3DS.h" -#include "smsc9220_eth.h" - -#define REG_WRITE_TIME_OUT 50 -#define RESET_TIME_OUT 10 -#define PHY_RESET_TIME_OUT_MS 100 - -/* Forward declarations */ - -static unsigned int smsc9220_mac_regread(unsigned char regoffset, unsigned int *data); -static unsigned int smsc9220_mac_regwrite(unsigned char regoffset, unsigned int data); -static unsigned int smsc9220_phy_regread(unsigned char regoffset, unsigned int *data); -static unsigned int smsc9220_phy_regwrite(unsigned char regoffset, unsigned int data); - -static unsigned int smsc9220_read_id(void); -static unsigned int smsc9220_soft_reset(void); -static void smsc9220_set_txfifo(unsigned int val); -static unsigned int smsc9220_wait_eeprom(void); -static void smsc9220_init_irqs(void); -static unsigned int smsc9220_check_phy(void); -static unsigned int smsc9220_reset_phy(void); - -static void smsc9220_advertise_cap(void); -static void smsc9220_enable_xmit(void); -static void smsc9220_enable_mac_xmit(void); -static void smsc9220_enable_mac_recv(void); - -/* SMSC9220 low-level operations */ - -/** - * \brief Read MAC register. - * - * \param[in] regoffset Register offset - * \param[out] data Register value is read - * - * \return 0 in case of success, 1 otherwise - */ -static unsigned int smsc9220_mac_regread(unsigned char regoffset, unsigned int *data) -{ - unsigned int val = 0; - unsigned int maccmd = 0; - int time_out = REG_WRITE_TIME_OUT; - - val = SMSC9220->MAC_CSR_CMD; - if(!(val & ((unsigned int)1 << 31))) { /* Make sure there's no pending operation */ - maccmd |= regoffset; - maccmd |= ((unsigned int)1 << 30); /* Indicates read */ - maccmd |= ((unsigned int)1 << 31); /* Start bit */ - SMSC9220->MAC_CSR_CMD = maccmd; /* Start operation */ - - do { - val = SMSC9220->BYTE_TEST; /* A no-op read. */ - wait_ms(1); - time_out--; - } while(time_out && (SMSC9220->MAC_CSR_CMD & ((unsigned int)1 << 31))); - - if(!time_out) { - return 1; - } - else { - *data = SMSC9220->MAC_CSR_DATA; - } - } else { - *data = 0; - } - return 0; -} - -/** - * \brief Write MAC register. - * - * \param[in] regoffset Register offset - * \param[in] data Register value to write - * - * \return 0 in case of success, 1 otherwise - */ -static unsigned int smsc9220_mac_regwrite(unsigned char regoffset, unsigned int data) -{ - unsigned int read = 0; - unsigned int maccmd = 0; - int time_out = REG_WRITE_TIME_OUT; - - read = SMSC9220->MAC_CSR_CMD; - if(!(read & ((unsigned int)1 << 31))) { /* Make sure there's no pending operation */ - SMSC9220->MAC_CSR_DATA = data; /* Store data. */ - maccmd |= regoffset; - maccmd &= ~((unsigned int)1 << 30); /* Clear indicates write */ - maccmd |= ((unsigned int)1 << 31); /* Indicate start of operation */ - SMSC9220->MAC_CSR_CMD = maccmd; - - do { - read = SMSC9220->BYTE_TEST; /* A no-op read. */ - wait_ms(1); - time_out--; - } while(time_out && (SMSC9220->MAC_CSR_CMD & ((unsigned int)1 << 31))); - - if(!time_out) { - return 1; - } - } else { - printf("Error: SMSC9220 MAC CSR is busy. No data written.\n"); - } - return 0; -} - -/** - * \brief Read PHY register. - * - * \param[in] regoffset Register offset - * \param[out] data Register value is read - * - * \return 0 in case of success, 1 otherwise - */ -static unsigned int smsc9220_phy_regread(unsigned char regoffset, unsigned int *data) -{ - unsigned int val = 0; - unsigned int phycmd = 0; - int time_out = REG_WRITE_TIME_OUT; - - if (smsc9220_mac_regread(SMSC9220_MAC_MII_ACC, &val)) { - return 1; - } - - if(!(val & 1)) { /* Not busy */ - phycmd = 0; - phycmd |= (1 << 11); /* 1 to [15:11] */ - phycmd |= ((regoffset & 0x1F) << 6); /* Put regoffset to [10:6] */ - phycmd &= ~(1 << 1); /* Clear [1] indicates read. */ - phycmd |= (1 << 0); /* Set [0] indicates operation start */ - - if (smsc9220_mac_regwrite(SMSC9220_MAC_MII_ACC, phycmd)) { - return 1; - } - - val = 0; - do { - wait_ms(1); - time_out--; - if (smsc9220_mac_regread(SMSC9220_MAC_MII_ACC,&val)) { - return 1; - } - } while(time_out && (val & ((unsigned int)1 << 0))); - - if (!time_out) { - return 1; - } else if (smsc9220_mac_regread(SMSC9220_MAC_MII_DATA, data)) { - return 1; - } - } else { - *data = 0; - return 1; - } - return 0; -} - -/** - * \brief Write PHY register. - * - * \param[in] regoffset Register offset - * \param[in] data Register value to write - * - * \return 0 in case of success, 1 otherwise - */ -static unsigned int smsc9220_phy_regwrite(unsigned char regoffset, unsigned int data) -{ - unsigned int val = 0; - unsigned int phycmd = 0; - int time_out = REG_WRITE_TIME_OUT; - - if (smsc9220_mac_regread(SMSC9220_MAC_MII_ACC, &val)) { - return 1; - } - - if(!(val & 1)) { /* Not busy */ - /* Load the data */ - if (smsc9220_mac_regwrite(SMSC9220_MAC_MII_DATA, (data & 0xFFFF))) { - return 1; - } - phycmd = 0; - phycmd |= (1 << 11); /* 1 to [15:11] */ - phycmd |= ((regoffset & 0x1F) << 6); /* Put regoffset to [10:6] */ - phycmd |= (1 << 1); /* Set [1] indicates write. */ - phycmd |= (1 << 0); /* Set [0] indicates operation start */ - /* Start operation */ - if (smsc9220_mac_regwrite(SMSC9220_MAC_MII_ACC, phycmd)) { - return 1; - } - - phycmd = 0; - - do { - wait_ms(1); - time_out--; - if (smsc9220_mac_regread(SMSC9220_MAC_MII_ACC, &phycmd)){ - return 1; - } - } while(time_out && (phycmd & (1 << 0))); - - if (!time_out) { - return 1; - } - - } else { - printf("Error: SMSC9220 MAC MII is busy. No data written.\n"); - } - return 0; -} - -/** - * \brief Read SMSC9220 ID. - * - * \return ID number - */ -inline static unsigned int smsc9220_read_id(void) -{ - return SMSC9220->ID_REV; -} - -/** - * \brief Initiates a soft reset, returns failure or success. - * - * \return 0 in case of success, 1 otherwise - */ -static unsigned int smsc9220_soft_reset(void) -{ - int time_out = RESET_TIME_OUT; - - /* Soft reset */ - SMSC9220->HW_CFG |= 1; - - do { - wait_ms(1); - time_out--; - } while(time_out && (SMSC9220->HW_CFG & 1)); - - if (!time_out) { - return 1; - } - - return 0; -} - -/** - * \brief Set maximum transition unit by Tx fifo size. - * Note: The MTU will be smaller by 512 bytes, - * because the status uses this fixed space. - * - * \param[in] val Size of the fifo in kbytes, 2-14 - */ -static void smsc9220_set_txfifo(unsigned int val) -{ - /* 2kb minimum, 14kb maximum */ - if(val >= 2 && val <= 14) { - SMSC9220->HW_CFG = val << 16; - } -} - -/** - * \brief Wait for EEPROM to be ready to use. - * - * \return 0 if ready, 1 in case of timeout - */ -static unsigned int smsc9220_wait_eeprom(void) -{ - int time_out = REG_WRITE_TIME_OUT; - - do { - wait_ms(1); - time_out--; - } while(time_out && (SMSC9220->E2P_CMD & ((unsigned int) 1 << 31))); - - if (!time_out) { - return 1; - } - - return 0; -} - -/** - * \brief Initialise irqs - */ -static void smsc9220_init_irqs(void) -{ - SMSC9220->INT_EN = 0x0; - SMSC9220->INT_STS = 0xFFFFFFFF; /* clear all interrupts */ - SMSC9220->IRQ_CFG = 0x22000100; /* irq deassertion at 220 usecs and master IRQ enable. */ -} - -/** - * \brief Check PHY ID registers. - * - * \return 0 in case of success, 1 otherwise - */ -static unsigned int smsc9220_check_phy(void) -{ - unsigned int phyid1, phyid2; - - if (smsc9220_phy_regread(SMSC9220_PHY_ID1,&phyid1)) { - return 1; - } - if (smsc9220_phy_regread(SMSC9220_PHY_ID2,&phyid2)) { - return 1; - } - return ((phyid1 == 0xFFFF && phyid2 == 0xFFFF) || - (phyid1 == 0x0 && phyid2 == 0x0)); -} - -/** - * \brief Reset PHY - * - * \return 0 in case of success, 1 otherwise - */ -static unsigned int smsc9220_reset_phy(void) -{ - unsigned int read; - - if(smsc9220_phy_regread(SMSC9220_PHY_BCONTROL, &read)) { - return 1; - } - - read |= (1 << 15); - if(smsc9220_phy_regwrite(SMSC9220_PHY_BCONTROL, read)) { - return 1; - } - return 0; -} - - -/** - * \brief Advertise all speeds and pause capabilities - * - * \return 0 in case of success, 1 otherwise - */ -static void smsc9220_advertise_cap(void) -{ - unsigned int aneg_adv = 0; - - smsc9220_phy_regread(SMSC9220_PHY_ANEG_ADV, &aneg_adv); - aneg_adv |= 0xDE0; - - smsc9220_phy_regwrite(SMSC9220_PHY_ANEG_ADV, aneg_adv); - smsc9220_phy_regread(SMSC9220_PHY_ANEG_ADV, &aneg_adv); -} - -/** - * \brief Enable trasmission - */ -inline static void smsc9220_enable_xmit(void) -{ - SMSC9220->TX_CFG = 0x2; -} - -static void smsc9220_enable_mac_xmit(void) -{ - unsigned int mac_cr = 0; - - smsc9220_mac_regread(SMSC9220_MAC_CR, &mac_cr); - - mac_cr |= (1 << 3); /* xmit enable */ - mac_cr |= (1 << 28); /* Heartbeat disable */ - - smsc9220_mac_regwrite(SMSC9220_MAC_CR, mac_cr); -} - -/** - * \brief Enable receive - */ -static void smsc9220_enable_mac_recv(void) -{ - unsigned int mac_cr = 0; - - smsc9220_mac_regread(SMSC9220_MAC_CR, &mac_cr); - mac_cr |= (1 << 2); /* Recv enable */ - smsc9220_mac_regwrite(SMSC9220_MAC_CR, mac_cr); -} - -/** - * \brief Check device ID. - * - * \return 0 in case of success, 1 otherwise - */ -static int smsc9220_check_id(void) -{ - unsigned int id = smsc9220_read_id(); - - /* If bottom and top halves of the word are the same */ - if(((id >> 16) & 0xFFFF) == (id & 0xFFFF)) { - return 1; - } - switch(((id >> 16) & 0xFFFF)) { - case 0x9220: - break; - - default: - return 1; - } - - return 0; -} - -/** - * \brief Fill the SMSC9220 TX FIFO with a number of words at an aligned - * address. - * - * \param[in] data Pointer to the aligned data that should be sent. - * \param[in] dwords_to_write Number of data words to write. - */ -static void fill_tx_fifo_aligned(unsigned int *data, - unsigned int dwords_to_write) -{ - while (dwords_to_write > 0) { - SMSC9220->TX_DATA_PORT = *data; - data++; - dwords_to_write--; - } -} - -/** - * \brief Fill the SMSC9220 TX FIFO with a number of words at an unaligned - * address. This function ensures that loading words at that address will - * not generate unaligned access which can trigger an exception to the - * processor. - * - * \param[in] data Pointer to the unaligned data that should be sent. - * \param[in] dwords_to_write Number of data words to write. - */ -static void fill_tx_fifo_unaligned(uint8_t *data, unsigned int dwords_to_write) -{ - /* - * Prevent unaligned word access from data pointer, 4 bytes are copied to - * this variable for each word that need to be sent. - */ - unsigned int tx_data_port_tmp = 0; - uint8_t *tx_data_port_tmp_ptr = (uint8_t *)&tx_data_port_tmp; - - while (dwords_to_write > 0) { - /* Keep the same endianness in data than in the temp variable */ - tx_data_port_tmp_ptr[0] = data[0]; - tx_data_port_tmp_ptr[1] = data[1]; - tx_data_port_tmp_ptr[2] = data[2]; - tx_data_port_tmp_ptr[3] = data[3]; - SMSC9220->TX_DATA_PORT = tx_data_port_tmp; - data += 4; - dwords_to_write--; - } -} - -/*---------------------------------------------------------------------------- - Public API - *----------------------------------------------------------------------------*/ -int smsc9220_init(void) -{ - unsigned int phyreset = 0; - - if(smsc9220_check_id()) { - return 1; - } - - if(smsc9220_soft_reset()) { - return 1; - } - - smsc9220_set_txfifo(5); - - /* Sets automatic flow control thresholds, and backpressure */ - /* threshold to defaults specified. */ - SMSC9220->AFC_CFG = 0x006E3740; - - if(smsc9220_wait_eeprom()) { - return 1; - } - - /* Configure GPIOs as LED outputs. */ - SMSC9220->GPIO_CFG = 0x70070000; - - smsc9220_init_irqs(); - - /* Configure MAC addresses here if needed. */ - - if(smsc9220_check_phy()) { - return 1; - } - - if(smsc9220_reset_phy()) { - return 1; - } - - wait_ms(PHY_RESET_TIME_OUT_MS); - /* Checking whether phy reset completed successfully.*/ - if (smsc9220_phy_regread(SMSC9220_PHY_BCONTROL, &phyreset)) { - return 1; - } - if(phyreset & (1 << 15)) { - return 1; - } - - smsc9220_advertise_cap(); - smsc9220_establish_link(); /* bit [12] of BCONTROL seems self-clearing. */ - /* Although it's not so in the manual. */ - - /* Interrupt threshold */ - SMSC9220->FIFO_INT = 0xFF000000; - - smsc9220_enable_mac_xmit(); - smsc9220_enable_xmit(); - SMSC9220->RX_CFG = 0; - smsc9220_enable_mac_recv(); - - /* Rx status FIFO level irq threshold */ - SMSC9220->FIFO_INT &= ~(0xFF); /* Clear 2 bottom nibbles */ - - /* This sleep is compulsory otherwise txmit/receive will fail. */ - wait_ms(2000); - return 0; -} - -void smsc9220_enable_interrupt(enum smsc9220_interrupt_source source) -{ - SMSC9220->INT_EN |= (1 << source); -} - -void smsc9220_disable_interrupt(enum smsc9220_interrupt_source source) -{ - SMSC9220->INT_EN &= ~(1 << source); -} - -void smsc9220_clear_interrupt(enum smsc9220_interrupt_source source) -{ - SMSC9220->INT_STS |= (1 << source); -} - -int smsc9220_get_interrupt(enum smsc9220_interrupt_source source) -{ - return (SMSC9220->INT_STS & (1 << source)); -} - -void smsc9220_establish_link(void) -{ - unsigned int bcr = 0; - unsigned int hw_cfg = 0; - - smsc9220_phy_regread(SMSC9220_PHY_BCONTROL, &bcr); - bcr |= (1 << 12) | (1 << 9); - smsc9220_phy_regwrite(SMSC9220_PHY_BCONTROL, bcr); - smsc9220_phy_regread(SMSC9220_PHY_BCONTROL, &bcr); - - hw_cfg = SMSC9220->HW_CFG; - hw_cfg &= 0xF0000; - hw_cfg |= (1 << 20); - SMSC9220->HW_CFG = hw_cfg; -} - -int smsc9220_read_mac_address(char *mac) -{ - unsigned int mac_low = 0; - unsigned int mac_high = 0; - - if( !mac ) { - return 1; - } - - /* Read current mac address. */ - if (smsc9220_mac_regread(SMSC9220_MAC_ADDRH, &mac_high)) { - return 1; - } - if (smsc9220_mac_regread(SMSC9220_MAC_ADDRL, &mac_low)) { - return 1; - } - mac[0] = mac_low & 0xFF; - mac[1] = (mac_low >> 8) & 0xFF; - mac[2] = (mac_low >> 16) & 0xFF; - mac[3] = (mac_low >> 24) & 0xFF; - mac[4] = mac_high & 0xFF; - mac[5] = (mac_high >> 8) & 0xFF; - - return 0; -} - -unsigned int smsc9220_get_tx_data_fifo_size(void) -{ - const unsigned int tx_status_fifo_size = 512; /* fixed allocation in bytes */ - unsigned int tx_fifo_size = SMSC9220->HW_CFG; - tx_fifo_size = (( tx_fifo_size >> 16 ) & 0x0F) * 1024; /* size is set in kbytes */ - return (tx_fifo_size - tx_status_fifo_size); -} - -int smsc9220_send_by_chunks(unsigned int total_packet_length, int is_new_packet, - const char *data, unsigned int current_size) -{ - static unsigned int ongoing_packet_length = 0; /* size in bytes of the packet is sending */ - static unsigned int ongoing_packet_length_sent = 0; /* size in bytes of the packet has been sent */ - int is_first_segment = 0; /* signing this is the first segment of the packet to be sent */ - int is_last_segment = 0; /* signing this is the last segment of the packet to be sent */ - unsigned int txcmd_a, txcmd_b = 0; - unsigned int dwords_to_write = 0; - unsigned int xmit_inf = 0; - unsigned int tx_buffer_free_space = 0; - unsigned int xmit_stat = 0; - - if (!data) { - return -1; /* Invalid input parameter */ - } - - if (is_new_packet) { - is_first_segment = 1; - ongoing_packet_length = total_packet_length; - ongoing_packet_length_sent = 0; - } else if (ongoing_packet_length != total_packet_length || - ongoing_packet_length_sent >= total_packet_length) { - return -1; /* Invalid input parameter */ - } - - /* Would next chunk fit into buffer? */ - xmit_inf = SMSC9220->TX_FIFO_INF; - tx_buffer_free_space = xmit_inf & 0xFFFF; - if (current_size > tx_buffer_free_space) { - return -1; /* Not enough space in FIFO */ - } - if ((ongoing_packet_length_sent + current_size) == total_packet_length) { - is_last_segment = 1; - } - - txcmd_a = 0; - txcmd_b = 0; - - txcmd_a |= (is_last_segment << 12) | (is_first_segment << 13); /* Last and first segments */ - txcmd_a |= current_size & 0x7FF; /* [10:0] contains length */ - - txcmd_b |= ((current_size & 0xFFFF) << 16); /* [31:16] contains length */ - txcmd_b |= current_size & 0x7FF; /* [10:0] also contains length */ - - SMSC9220->TX_DATA_PORT = txcmd_a; - SMSC9220->TX_DATA_PORT = txcmd_b; - dwords_to_write = (current_size + 3) >> 2; - - /* - * Copy to TX FIFO - * The function to use depends on the alignment of the data pointer on a 32 - * bits boundary. - */ - if (((unsigned int)data % sizeof(uint32_t)) == 0) { - /* Cast is safe because we know data is aligned */ - fill_tx_fifo_aligned((unsigned int *)data, dwords_to_write); - } else { - fill_tx_fifo_unaligned((uint8_t *)data, dwords_to_write); - } - - if (is_last_segment) { - /* pop status port */ - /* for error check it should be checked "at a later time" according to data sheet */ - xmit_stat = SMSC9220->TX_STAT_PORT; - (void)xmit_stat; - } - - ongoing_packet_length_sent += current_size; - return 0; -} - -unsigned int smsc9220_get_rxfifo_data_used_space(void) -{ - unsigned int rxfifo_inf = SMSC9220->RX_FIFO_INF; - return rxfifo_inf & 0xFFFF; -} - -unsigned int smsc9220_receive_by_chunks(char *data, unsigned int dlen) -{ - static unsigned int current_packet_size_words = 0; - unsigned int rxfifo_inf = 0; - unsigned int rxfifo_stat = 0; - unsigned int dlen_word = 0; - unsigned int read_length_word = 0; - unsigned int i = 0; - - if (!data) { - return 0; /* Invalid input parameter */ - } - - if (current_packet_size_words == 0) { - /* First the packet status word should be read, */ - /* which tells the size of the data, */ - /* after the data can be read in synchron. */ - rxfifo_inf = SMSC9220->RX_FIFO_INF; - - if(rxfifo_inf & 0xFFFF) { /* If there's data */ - rxfifo_stat = SMSC9220->RX_STAT_PORT; - if(rxfifo_stat != 0) { /* Fetch status of this packet */ - if(rxfifo_stat & (1 << 15)) { - current_packet_size_words = 0; /* error */ - } - else { - /* Ethernet controller is padding to 32bit aligned data */ - current_packet_size_words = (((rxfifo_stat >> 16) & 0x3FFF) + 3) >> 2; - } - } - } - } - dlen_word = dlen / 4; - read_length_word = (dlen_word < current_packet_size_words) ? dlen_word : current_packet_size_words; - - for (i = 0; i < read_length_word; i++) { - ((unsigned int*)data)[i] = SMSC9220->RX_DATA_PORT; - current_packet_size_words--; - } - return (current_packet_size_words * 4); -} - -unsigned int smsc9220_peek_next_packet_size(void) -{ - unsigned int packet_size = 0; - unsigned int rx_stat_peek = 0; - - if(smsc9220_get_rxfifo_data_used_space()) { - rx_stat_peek = SMSC9220->RX_STAT_PEEK; - packet_size = ((rx_stat_peek >> 16) & 0x3FFF); - } - return (((packet_size + 3) >> 2) << 2); -} - diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth.h deleted file mode 100644 index 7db5437937..0000000000 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth.h +++ /dev/null @@ -1,170 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * 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. - */ - -/* This file is the re-implementation of mps2_ethernet_api and Selftest's ETH_MPS2. - * MPS2 Selftest:https://silver.arm.com/browse/VEI10 -> - * \ISCM-1-0\AN491\software\Selftest\v2m_mps2\ - */ -#ifndef _SMSC9220_ETH_H_ -#define _SMSC9220_ETH_H_ - -enum smsc9220_interrupt_source { - enum_smsc9220_interrupt_gpio0 = 0, - enum_smsc9220_interrupt_gpio1 = 1, - enum_smsc9220_interrupt_gpio2 = 2, - enum_smsc9220_interrupt_rxstatus_fifo_level = 3, - enum_smsc9220_interrupt_rxstatus_fifo_full = 4, - /* 5 Reserved according to Datasheet */ - enum_smsc9220_interrupt_rx_dropped_frame = 6, - enum_smsc9220_interrupt_txstatus_fifo_level = 7, - enum_smsc9220_interrupt_txstatus_fifo_full = 8, - enum_smsc9220_interrupt_txdata_fifo_available = 9, - enum_smsc9220_interrupt_txdata_fifo_overrun = 10, - /* 11, 12 Reserved according to Datasheet */ - enum_smsc9220_interrupt_transmit_error = 13, - enum_smsc9220_interrupt_receive_error = 14, - enum_smsc9220_interrupt_receive_watchdog_timeout = 15, - enum_smsc9220_interrupt_txstatus_overflow = 16, - enum_smsc9220_interrupt_power_management = 17, - enum_smsc9220_interrupt_phy = 18, - enum_smsc9220_interrupt_gp_timer = 19, - enum_smsc9220_interrupt_rx_dma = 20, - enum_smsc9220_interrupt_tx_ioc = 21, - /* 22 Reserved according to Datasheet*/ - enum_smsc9220_interrupt_rx_dropped_frame_half = 23, - enum_smsc9220_interrupt_rx_stopped = 24, - enum_smsc9220_interrupt_tx_stopped = 25, - /* 26 - 30 Reserved according to Datasheet*/ - enum_smsc9220_interrupt_sw = 31 -}; - -/* Function declarations */ - -/** - * \brief Initialize SMS9220 Ethernet controller - * - * \return 0 if init is successful, 1 otherwise - */ -int smsc9220_init(void); - -/** - * \brief Enable the given interrupt source. - * - * \param[in] source Enum of the interrupt source. - */ -void smsc9220_enable_interrupt(enum smsc9220_interrupt_source source); - -/** - * \brief Disable the given interrupt source. - * - * \param[in] source Enum of the interrupt source. - */ -void smsc9220_disable_interrupt(enum smsc9220_interrupt_source source); - -/** - * \brief Clear the given interrupt source. - * - * \param[in] source Enum of the interrupt source. - */ -void smsc9220_clear_interrupt(enum smsc9220_interrupt_source source); - -/** - * \brief Get the status of the given interrupt source. - * - * \param[in] source Enum of the interrupt source. - * - * \return non-zero if the given interrupt source is triggered, zero otherwise - */ -int smsc9220_get_interrupt(enum smsc9220_interrupt_source source); - -/** - * \brief Establish link - */ -void smsc9220_establish_link(void); - -/** - * \brief Read MAC address from EEPROM. - * - * \param[in,out] mac array will include the read MAC address in - * 6 bytes hexadecimal format. - * It should be allocated by the caller to 6 bytes. - * - * \return 0 if read is successful, 1 otherwise - */ -int smsc9220_read_mac_address(char *mac); - -/** - * \brief Get the data size of the Tx buffer, aka Maximum Transition Unit - * - * \return Fifo data size in bytes - */ -unsigned int smsc9220_get_tx_data_fifo_size(void); - -/** - * \brief Send Ethernet packet from buffer chain. - * The full packet length should be known in the beginning - * of a new packet. - * - * \param[in] total_packet_length Length of the packet. Should be equal to - * the sum of passed buffers within a packet. - * \param[in] is_new_packet Should be set to non-zero if the passed buffer - * should be sent as the start of a new packet. - * If the current buffer should be sent as a full packet, - * it should be set to non-zero respectively. - * \param[in] data Pointer to the data should be sent. - * \param[in] current_size Size of the data in bytes. - * - * \return 0 if the send process is successful, standard C error code otherwise - */ -int smsc9220_send_by_chunks(unsigned int total_packet_length, int is_new_packet, - const char *data, unsigned int current_size); - -/** - * \brief Receive Ethernet packet from Rx FIFO to the passed buffer. - * Stops reading at packet border. - * If the passed buffer is larger than the current packet, - * the whole packet will be read into the buffer. - * If the current packet is larger than the passed buffer, - * the buffer will be filled with data and the next call - * will continue the read from that point. - * - * \param[in,out] data Pointer where the data will be read to. - * The caller is responsible to allocate it. - * \param[in] dlen Length of the allocated data in bytes. - * - * \return Remaining bytes left in the fifo of the current packet. - */ -unsigned int smsc9220_receive_by_chunks(char *data, unsigned int dlen); - -/** - * \brief Get the used space of Rx fifo in bytes. - * - * \return Data received and waiting for read in bytes - */ -unsigned int smsc9220_get_rxfifo_data_used_space(void); - -/** - * \brief Get the size of next unread packet in Rx buffer, using the peak - * register, which is not destructive so can be read asynchronously. - * Warning: In case of heavy receiving load, it's possible this register - * is not perfectly in sync. - * - * \return Size in bytes of the next packet can be read from Rx fifo, according - * to the peek register. - */ -unsigned int smsc9220_peek_next_packet_size(void); - -#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth_drv.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth_drv.c new file mode 100644 index 0000000000..b9b6b57fcc --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth_drv.c @@ -0,0 +1,1074 @@ +/* + * Copyright (c) 2016-2018 ARM Limited + * + * 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. + */ + +#include "cmsis.h" +#include "smsc9220_eth_drv.h" + +/** Setter bit manipulation macro */ +#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX))) +/** Clearing bit manipulation macro */ +#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX))) +/** Getter bit manipulation macro */ +#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX)))) + +/** Setter bit-field manipulation macro */ +#define SET_BIT_FIELD(WORD, BIT_MASK, BIT_OFFSET, VALUE) \ + (WORD |= ((VALUE & BIT_MASK) << BIT_OFFSET)) + +/** Clearing bit-field manipulation macro */ +#define CLR_BIT_FIELD(WORD, BIT_MASK, BIT_OFFSET, VALUE) \ + (WORD &= ~((VALUE & BIT_MASK) << BIT_OFFSET)) + +/** Getter bit-field manipulation macro */ +#define GET_BIT_FIELD(WORD, BIT_MASK, BIT_OFFSET) \ + ((WORD >> BIT_OFFSET) & BIT_MASK) + +/** Millisec timeout macros */ +#define RESET_TIME_OUT_MS 10U +#define REG_WRITE_TIME_OUT_MS 50U +#define PHY_RESET_TIME_OUT_MS 100U +#define INIT_FINISH_DELAY 2000U + +struct smsc9220_eth_reg_map_t { +__I uint32_t rx_data_port; /**< Receive FIFO Ports (offset 0x0) */ + uint32_t reserved1[0x7]; +__O uint32_t tx_data_port; /**< Transmit FIFO Ports (offset 0x20) */ + uint32_t reserved2[0x7]; + +__I uint32_t rx_status_port; /**< Receive FIFO status port (offset 0x40) */ +__I uint32_t rx_status_peek; /**< Receive FIFO status peek (offset 0x44) */ +__I uint32_t tx_status_port; /**< Transmit FIFO status port (offset 0x48) */ +__I uint32_t tx_status_peek; /**< Transmit FIFO status peek (offset 0x4C) */ + +__I uint32_t id_revision; /**< Chip ID and Revision (offset 0x50) */ +__IO uint32_t irq_cfg; /**< Main Interrupt Config (offset 0x54) */ +__IO uint32_t irq_status; /**< Interrupt Status (offset 0x58) */ +__IO uint32_t irq_enable; /**< Interrupt Enable Register (offset 0x5C) */ + uint32_t reserved3; /**< Reserved for future use (offset 0x60) */ +__I uint32_t byte_test; /**< Byte order test 87654321h (offset 0x64) */ +__IO uint32_t fifo_level_irq; /**< FIFO Level Interrupts (offset 0x68) */ +__IO uint32_t rx_cfg; /**< Receive Configuration (offset 0x6C) */ +__IO uint32_t tx_cfg; /**< Transmit Configuration (offset 0x70) */ +__IO uint32_t hw_cfg; /**< Hardware Configuration (offset 0x74) */ +__IO uint32_t rx_datapath_ctrl; /**< RX Datapath Control (offset 0x78) */ +__I uint32_t rx_fifo_inf; /**< Receive FIFO Information (offset 0x7C) */ +__I uint32_t tx_fifo_inf; /**< Transmit FIFO Information (offset 0x80) */ +__IO uint32_t pmt_ctrl; /**< Power Management Control (offset 0x84) */ +__IO uint32_t gpio_cfg; /**< GPIO Configuration (offset 0x88) */ +__IO uint32_t gptimer_cfg; /**< GP Timer Configuration (offset 0x8C) */ +__I uint32_t gptimer_count; /**< GP Timer Count (offset 0x90) */ + uint32_t reserved4; /**< Reserved for future use (offset 0x94) */ +__IO uint32_t word_swap; /**< WORD SWAP Register (offset 0x98) */ +__I uint32_t free_run_counter; /**< Free Run Counter (offset 0x9C) */ +__I uint32_t rx_dropped_frames;/**< RX Dropped Frames Counter (offset 0xA0) */ +__IO uint32_t mac_csr_cmd; /**< MAC CSR Synchronizer Cmd (offset 0xA4) */ +__IO uint32_t mac_csr_data; /**< MAC CSR Synchronizer Data (offset 0xA8) */ +__IO uint32_t afc_cfg; /**< AutomaticFlow Ctrl Config (offset 0xAC) */ +__IO uint32_t eeprom_cmd; /**< EEPROM Command (offset 0xB0) */ +__IO uint32_t eeprom_data; /**< EEPROM Data (offset 0xB4) */ +}; + +/** + * \brief TX FIFO Size definitions + * + */ +#define TX_STATUS_FIFO_SIZE_BYTES 512U /*< fixed allocation in bytes */ +#define TX_DATA_FIFO_SIZE_KBYTES_POS 16U +#define TX_DATA_FIFO_SIZE_KBYTES_MASK 0x0FU +#define KBYTES_TO_BYTES_MULTIPLIER 1024U + +/** + * \brief FIFO Info definitions + * + */ +#define FIFO_USED_SPACE_MASK 0xFFFFU +#define DATA_FIFO_USED_SPACE_POS 0U +#define STATUS_FIFO_USED_SPACE_POS 16U + +/** + * \brief MAC CSR Synchronizer Command bit definitions + * + */ +enum mac_csr_cmd_bits_t{ + MAC_CSR_CMD_RW_INDEX = 30U, + MAC_CSR_CMD_BUSY_INDEX = 31U, +}; + +#define MAC_CSR_CMD_ADDRESS_MASK 0x0FU + +/** + * \brief MAC Control register bit definitions + * + */ +enum mac_reg_cr_bits_t{ + MAC_REG_CR_RXEN_INDEX = 2U, + MAC_REG_CR_TXEN_INDEX = 3U +}; + +/** + * \brief MII Access register bit definitions + * + */ +enum mac_reg_mii_acc_bits_t{ + MAC_REG_MII_ACC_BUSY_INDEX = 0U, + MAC_REG_MII_ACC_WRITE_INDEX = 1U, + MAC_REG_MII_ACC_PHYADDR_INDEX = 11U +}; +#define MAC_REG_MII_ACC_MII_REG_MASK 0x1FU +#define MAC_REG_MII_ACC_MII_REG_OFFSET 6U + +/** + * \brief Hardware config register bit definitions + * + */ +enum hw_cfg_reg_bits_t{ + HW_CFG_REG_SRST_INDEX = 0U, + HW_CFG_REG_SRST_TIMEOUT_INDEX = 1U, + HW_CFG_REG_MUST_BE_ONE_INDEX = 20U, +}; +#define HW_CFG_REG_TX_FIFO_SIZE_POS 16U +#define HW_CFG_REG_TX_FIFO_SIZE_MIN 2U /*< Min Tx fifo size in KB */ +#define HW_CFG_REG_TX_FIFO_SIZE_MAX 14U /*< Max Tx fifo size in KB */ +#define HW_CFG_REG_TX_FIFO_SIZE 5U /*< Tx fifo size in KB */ + +/** + * \brief EEPROM command register bit definitions + * + */ +enum eeprom_cmd_reg_bits_t{ + EEPROM_CMD_REG_BUSY_INDEX = 31U, +}; + +/** + * \brief PHY Basic Control register bit definitions + * + */ +enum phy_reg_bctrl_reg_bits_t{ + PHY_REG_BCTRL_RST_AUTO_NEG_INDEX = 9U, + PHY_REG_BCTRL_AUTO_NEG_EN_INDEX = 12U, + PHY_REG_BCTRL_RESET_INDEX = 15U +}; + +/** + * \brief TX Command A bit definitions + * + */ + +#define TX_CMD_DATA_START_OFFSET_BYTES_POS 16U +#define TX_CMD_DATA_START_OFFSET_BYTES_MASK 0x1FU + + +enum tx_command_a_bits_t{ + TX_COMMAND_A_LAST_SEGMENT_INDEX = 12U, + TX_COMMAND_A_FIRST_SEGMENT_INDEX = 13U +}; + +#define TX_CMD_PKT_LEN_BYTES_MASK 0x7FFU +#define TX_CMD_PKT_TAG_MASK 0xFFFFU +#define TX_CMD_PKT_TAG_POS 16U + + +/** + * \brief RX Fifo Status bit definitions + * + */ +enum rx_fifo_status_bits_t{ + RX_FIFO_STATUS_ERROR_INDEX = 15U +}; +#define RX_FIFO_STATUS_PKT_LENGTH_POS 16U +#define RX_FIFO_STATUS_PKT_LENGTH_MASK 0x3FFFU + +/** + * \brief Interrupt Configuration register bit definitions + * + */ +enum irq_cfg_bits_t{ + IRQ_CFG_IRQ_EN_INDEX = 8U +}; + +#define IRQ_CFG_INT_DEAS_MASK 0xFFU +#define IRQ_CFG_INT_DEAS_POS 24U +#define IRQ_CFG_INT_DEAS_10US 0x22U + +/** + * \brief Automatic Flow Control register bit definitions + * + */ +enum afc_bits_t{ + AFC_ANY_INDEX = 0U, + AFC_ADDR_INDEX = 1U, + AFC_BROADCAST_INDEX = 2U, + AFC_MULTICAST_INDEX = 3U +}; + +#define AFC_BACK_DUR_MASK 0x0FU +#define AFC_BACK_DUR_POS 4U +#define AFC_BACK_DUR 4U /**< equal to 50us */ + +#define AFC_LOW_LEVEL_MASK 0xFFU +#define AFC_LOW_LEVEL_POS 8U +#define AFC_LOW_LEVEL 55U /**< specifies in multiple of 64 bytes */ + +#define AFC_HIGH_LEVEL_MASK 0xFFU +#define AFC_HIGH_LEVEL_POS 16U +#define AFC_HIGH_LEVEL 110U /**< specifies in multiple of 64 bytes */ + +/** + * \brief Auto-Negotiation Advertisement register bit definitions + * + */ +enum aneg_bits_t{ + ANEG_10_BASE_T_INDEX = 5U, /**< 10Mbps able */ + ANEG_10_BASE_T_FULL_DUPL_INDEX = 6U, /**< 10Mbps with full duplex */ + ANEG_100_BASE_TX_INDEX = 7U, /**< 100Mbps Tx able */ + ANEG_100_BASE_TX_FULL_DUPL_INDEX = 8U, /**< 100Mbps with full duplex */ + ANEG_SYMM_PAUSE_INDEX = 10U, /**< Symmetric Pause */ + ANEG_ASYMM_PAUSE_INDEX = 11U /**< Asymmetric Pause */ +}; + +/** + * \brief Transmit Configuration register bit definitions + * + */ +enum tx_cfg_bits_t{ + TX_CFG_STOP_INDEX = 0U, /*< stop */ + TX_CFG_ON_INDEX = 1U, /*< on */ + TX_CFG_AO_INDEX = 2U, /*< allow overrun */ + TX_CFG_TXD_DUMP_INDEX = 14U, /*< Data FIFO dump */ + TX_CFG_TXS_DUMP_INDEX = 15U /*< Status FIFO dump */ +}; + +/** + * \brief Chip ID definitions + * + */ +#define CHIP_ID 0x9220U +#define CHIP_ID_MASK 0xFFFFU +#define CHIP_ID_POS 16U + +/** + * \brief GPIO Configuration register bit definitions + * + */ +enum gpio_cfg_bits_t{ + GPIO_CFG_GPIO0_PUSHPULL_INDEX = 16U, /*< GPIO0 push/pull or open-drain */ + GPIO_CFG_GPIO1_PUSHPULL_INDEX = 17U, /*< GPIO1 push/pull or open-drain */ + GPIO_CFG_GPIO2_PUSHPULL_INDEX = 18U, /*< GPIO2 push/pull or open-drain */ + GPIO_CFG_GPIO0_LED_INDEX = 28U, /*< GPIO0 set to LED1 */ + GPIO_CFG_GPIO1_LED_INDEX = 29U, /*< GPIO1 set to LED2 */ + GPIO_CFG_GPIO2_LED_INDEX = 30U /*< GPIO2 set to LED3 */ +}; + + +static void fill_tx_fifo(const struct smsc9220_eth_dev_t* dev, + uint8_t *data, uint32_t size_bytes) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + uint32_t tx_data_port_tmp = 0; + uint8_t *tx_data_port_tmp_ptr = (uint8_t *)&tx_data_port_tmp; + + /*If the data length is not a multiple of 4, then the beginning of the first + * DWORD of the TX DATA FIFO gets filled up with zeros and a byte offset is + * set accordingly to guarantee proper transmission.*/ + uint32_t remainder_bytes = (size_bytes % 4); + uint32_t filler_bytes = (4 - remainder_bytes); + for(uint32_t i = 0; i < 4; i++){ + if(i < filler_bytes){ + tx_data_port_tmp_ptr[i] = 0; + } else { + tx_data_port_tmp_ptr[i] = data[i-filler_bytes]; + } + } + register_map->tx_data_port = tx_data_port_tmp; + size_bytes -= remainder_bytes; + data += remainder_bytes; + + while (size_bytes > 0) { + /* Keep the same endianness in data than in the temp variable */ + tx_data_port_tmp_ptr[0] = data[0]; + tx_data_port_tmp_ptr[1] = data[1]; + tx_data_port_tmp_ptr[2] = data[2]; + tx_data_port_tmp_ptr[3] = data[3]; + register_map->tx_data_port = tx_data_port_tmp; + data += 4; + size_bytes -= 4; + } +} + +static void empty_rx_fifo(const struct smsc9220_eth_dev_t* dev, + uint8_t *data, uint32_t size_bytes) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + uint32_t rx_data_port_tmp = 0; + uint8_t *rx_data_port_tmp_ptr = (uint8_t *)&rx_data_port_tmp; + + uint32_t remainder_bytes = (size_bytes % 4); + size_bytes -= remainder_bytes; + + while (size_bytes > 0) { + /* Keep the same endianness in data than in the temp variable */ + rx_data_port_tmp = register_map->rx_data_port; + data[0] = rx_data_port_tmp_ptr[0]; + data[1] = rx_data_port_tmp_ptr[1]; + data[2] = rx_data_port_tmp_ptr[2]; + data[3] = rx_data_port_tmp_ptr[3]; + data += 4; + size_bytes -= 4; + } + + rx_data_port_tmp = register_map->rx_data_port; + for(uint32_t i = 0; i < remainder_bytes; i++) { + data[i] = rx_data_port_tmp_ptr[i]; + } +} + +enum smsc9220_error_t smsc9220_mac_regread( + const struct smsc9220_eth_dev_t* dev, + enum smsc9220_mac_reg_offsets_t regoffset, + uint32_t *data) +{ + volatile uint32_t val; + uint32_t maccmd = GET_BIT_FIELD(regoffset, + MAC_CSR_CMD_ADDRESS_MASK, 0); + uint32_t time_out = REG_WRITE_TIME_OUT_MS; + + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + /* Make sure there's no pending operation */ + if(!(GET_BIT(register_map->mac_csr_cmd, MAC_CSR_CMD_BUSY_INDEX))) { + SET_BIT(maccmd, MAC_CSR_CMD_RW_INDEX); + SET_BIT(maccmd, MAC_CSR_CMD_BUSY_INDEX); + register_map->mac_csr_cmd = maccmd; /* Start operation */ + + do { + val = register_map->byte_test; /* A no-op read. */ + (void)val; + if (dev->data->wait_ms) { + dev->data->wait_ms(1); + } + time_out--; + } while(time_out && + GET_BIT(register_map->mac_csr_cmd,MAC_CSR_CMD_BUSY_INDEX)); + + if(!time_out) { + return SMSC9220_ERROR_TIMEOUT; + } + else { + *data = register_map->mac_csr_data; + } + } else { + return SMSC9220_ERROR_BUSY; + } + return SMSC9220_ERROR_NONE; +} + +enum smsc9220_error_t smsc9220_mac_regwrite( + const struct smsc9220_eth_dev_t* dev, + enum smsc9220_mac_reg_offsets_t regoffset, + uint32_t data) +{ + volatile uint32_t read = 0; + uint32_t maccmd = GET_BIT_FIELD(regoffset, + MAC_CSR_CMD_ADDRESS_MASK, 0); + uint32_t time_out = REG_WRITE_TIME_OUT_MS; + + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + /* Make sure there's no pending operation */ + if(!GET_BIT(register_map->mac_csr_cmd, MAC_CSR_CMD_BUSY_INDEX)) { + register_map->mac_csr_data = data; /* Store data. */ + CLR_BIT(maccmd, MAC_CSR_CMD_RW_INDEX); + SET_BIT(maccmd, MAC_CSR_CMD_BUSY_INDEX); + register_map->mac_csr_cmd = maccmd; + + do { + read = register_map->byte_test; /* A no-op read. */ + (void)read; + if (dev->data->wait_ms) { + dev->data->wait_ms(1); + } + time_out--; + } while(time_out && + (register_map->mac_csr_cmd & + GET_BIT(register_map->mac_csr_cmd, MAC_CSR_CMD_BUSY_INDEX))); + + if(!time_out) { + return SMSC9220_ERROR_TIMEOUT; + } + } else { + return SMSC9220_ERROR_BUSY; + } + return SMSC9220_ERROR_NONE; +} + +enum smsc9220_error_t smsc9220_phy_regread( + const struct smsc9220_eth_dev_t* dev, + enum phy_reg_offsets_t regoffset, + uint32_t *data) +{ + uint32_t val = 0; + uint32_t phycmd = 0; + uint32_t time_out = REG_WRITE_TIME_OUT_MS; + + if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, &val)) { + return SMSC9220_ERROR_INTERNAL; + } + + if(!GET_BIT(val, MAC_REG_MII_ACC_BUSY_INDEX)) { + phycmd = 0; + SET_BIT(phycmd, MAC_REG_MII_ACC_PHYADDR_INDEX); + SET_BIT_FIELD(phycmd, MAC_REG_MII_ACC_MII_REG_MASK, + MAC_REG_MII_ACC_MII_REG_OFFSET, regoffset); + CLR_BIT(phycmd, MAC_REG_MII_ACC_WRITE_INDEX); + SET_BIT(phycmd, MAC_REG_MII_ACC_BUSY_INDEX); + + if (smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, + phycmd)) { + return SMSC9220_ERROR_INTERNAL; + } + + val = 0; + do { + if (dev->data->wait_ms) { + dev->data->wait_ms(1); + } + time_out--; + if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, + &val)) { + return SMSC9220_ERROR_INTERNAL; + } + } while(time_out && (GET_BIT(val, MAC_REG_MII_ACC_BUSY_INDEX))); + + if (!time_out) { + return SMSC9220_ERROR_TIMEOUT; + } else if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_MII_DATA, + data)) { + return SMSC9220_ERROR_INTERNAL; + } + } else { + return SMSC9220_ERROR_BUSY; + } + return SMSC9220_ERROR_NONE; +} + +enum smsc9220_error_t smsc9220_phy_regwrite( + const struct smsc9220_eth_dev_t* dev, + enum phy_reg_offsets_t regoffset, + uint32_t data) +{ + uint32_t val = 0; + uint32_t phycmd = 0; + uint32_t time_out = REG_WRITE_TIME_OUT_MS; + + if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, &val)) { + return SMSC9220_ERROR_INTERNAL; + } + + if(!GET_BIT(val, MAC_REG_MII_ACC_BUSY_INDEX)) { + /* Load the data */ + if (smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_MII_DATA, + (data & 0xFFFF))) { + return SMSC9220_ERROR_INTERNAL; + } + phycmd = 0; + SET_BIT(phycmd, MAC_REG_MII_ACC_PHYADDR_INDEX); + SET_BIT_FIELD(phycmd, MAC_REG_MII_ACC_MII_REG_MASK, + MAC_REG_MII_ACC_MII_REG_OFFSET, regoffset); + SET_BIT(phycmd, MAC_REG_MII_ACC_WRITE_INDEX); + SET_BIT(phycmd, MAC_REG_MII_ACC_BUSY_INDEX); + /* Start operation */ + if (smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, + phycmd)) { + return SMSC9220_ERROR_INTERNAL; + } + + phycmd = 0; + + do { + if (dev->data->wait_ms) { + dev->data->wait_ms(1); + } + time_out--; + if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, + &phycmd)){ + return SMSC9220_ERROR_INTERNAL; + } + } while(time_out && GET_BIT(phycmd, 0)); + + if (!time_out) { + return SMSC9220_ERROR_TIMEOUT; + } + + } else { + return SMSC9220_ERROR_BUSY; + } + return SMSC9220_ERROR_NONE; +} + +uint32_t smsc9220_read_id(const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + return register_map->id_revision; +} + +enum smsc9220_error_t smsc9220_soft_reset( + const struct smsc9220_eth_dev_t* dev) +{ + uint32_t time_out = RESET_TIME_OUT_MS; + + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + /* Soft reset */ + SET_BIT(register_map->hw_cfg, HW_CFG_REG_SRST_INDEX); + + do { + if (dev->data->wait_ms) { + dev->data->wait_ms(1); + } + time_out--; + } while(time_out && + GET_BIT(register_map->hw_cfg, HW_CFG_REG_SRST_TIMEOUT_INDEX)); + + if (!time_out) { + return SMSC9220_ERROR_TIMEOUT; + } + + return SMSC9220_ERROR_NONE; +} + +void smsc9220_set_txfifo(const struct smsc9220_eth_dev_t* dev, + uint32_t val) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + if(val >= HW_CFG_REG_TX_FIFO_SIZE_MIN && + val <= HW_CFG_REG_TX_FIFO_SIZE_MAX) { + register_map->hw_cfg = val << HW_CFG_REG_TX_FIFO_SIZE_POS; + } +} + +enum smsc9220_error_t smsc9220_set_fifo_level_irq( + const struct smsc9220_eth_dev_t* dev, + enum smsc9220_fifo_level_irq_pos_t irq_level_pos, + uint32_t level) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + if (level < SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN || + level > SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX) { + return SMSC9220_ERROR_PARAM; + } + + CLR_BIT_FIELD(register_map->fifo_level_irq, SMSC9220_FIFO_LEVEL_IRQ_MASK, + irq_level_pos, SMSC9220_FIFO_LEVEL_IRQ_MASK); + SET_BIT_FIELD(register_map->fifo_level_irq, SMSC9220_FIFO_LEVEL_IRQ_MASK, + irq_level_pos, level); + return SMSC9220_ERROR_NONE; +} + +enum smsc9220_error_t smsc9220_wait_eeprom( + const struct smsc9220_eth_dev_t* dev) +{ + uint32_t time_out = REG_WRITE_TIME_OUT_MS; + + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + do { + if (dev->data->wait_ms) { + dev->data->wait_ms(1); + } + time_out--; + } while(time_out && + GET_BIT(register_map->eeprom_cmd, EEPROM_CMD_REG_BUSY_INDEX)); + + if (!time_out) { + return SMSC9220_ERROR_TIMEOUT; + } + + return SMSC9220_ERROR_NONE; +} + +void smsc9220_init_irqs(const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + smsc9220_disable_all_interrupts(dev); + smsc9220_clear_all_interrupts(dev); + + /* Set IRQ deassertion interval */ + SET_BIT_FIELD(register_map->irq_cfg, IRQ_CFG_INT_DEAS_MASK, + IRQ_CFG_INT_DEAS_POS, IRQ_CFG_INT_DEAS_10US); + + /* enable interrupts */ + SET_BIT(register_map->irq_cfg, IRQ_CFG_IRQ_EN_INDEX); +} + +enum smsc9220_error_t smsc9220_check_phy(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t phyid1 = 0; + uint32_t phyid2 = 0; + + if (smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_ID1,&phyid1)) { + return SMSC9220_ERROR_INTERNAL; + } + if (smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_ID2,&phyid2)) { + return SMSC9220_ERROR_INTERNAL; + } + if ((phyid1 == 0xFFFF && phyid2 == 0xFFFF) || + (phyid1 == 0x0 && phyid2 == 0x0)) { + return SMSC9220_ERROR_INTERNAL; + } + return SMSC9220_ERROR_NONE; +} + +enum smsc9220_error_t smsc9220_reset_phy(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t read = 0; + + if(smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_BCTRL, &read)) { + return SMSC9220_ERROR_INTERNAL; + } + + SET_BIT(read, PHY_REG_BCTRL_RESET_INDEX); + if(smsc9220_phy_regwrite(dev, SMSC9220_PHY_REG_OFFSET_BCTRL, read)) { + return SMSC9220_ERROR_INTERNAL; + } + return SMSC9220_ERROR_NONE; +} + +void smsc9220_advertise_cap(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t aneg_adv = 0; + smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_ANEG_ADV, &aneg_adv); + + SET_BIT(aneg_adv, ANEG_10_BASE_T_INDEX); + SET_BIT(aneg_adv, ANEG_10_BASE_T_FULL_DUPL_INDEX); + SET_BIT(aneg_adv, ANEG_100_BASE_TX_INDEX); + SET_BIT(aneg_adv, ANEG_100_BASE_TX_FULL_DUPL_INDEX); + SET_BIT(aneg_adv, ANEG_SYMM_PAUSE_INDEX); + SET_BIT(aneg_adv, ANEG_ASYMM_PAUSE_INDEX); + + smsc9220_phy_regwrite(dev, SMSC9220_PHY_REG_OFFSET_ANEG_ADV, aneg_adv); +} + +void smsc9220_enable_xmit(const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + SET_BIT(register_map->tx_cfg, TX_CFG_ON_INDEX); +} + +void smsc9220_disable_xmit(const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + CLR_BIT(register_map->tx_cfg, TX_CFG_ON_INDEX); +} + +void smsc9220_enable_mac_xmit(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t mac_cr = 0; + smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_CR, &mac_cr); + + SET_BIT(mac_cr, MAC_REG_CR_TXEN_INDEX); + + smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_CR, mac_cr); +} + +void smsc9220_disable_mac_xmit(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t mac_cr = 0; + smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_CR, &mac_cr); + + CLR_BIT(mac_cr, MAC_REG_CR_TXEN_INDEX); + + smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_CR, mac_cr); +} + +void smsc9220_enable_mac_recv(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t mac_cr = 0; + smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_CR, &mac_cr); + + SET_BIT(mac_cr, MAC_REG_CR_RXEN_INDEX); + + smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_CR, mac_cr); +} + +void smsc9220_disable_mac_recv(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t mac_cr = 0; + smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_CR, &mac_cr); + + CLR_BIT(mac_cr, MAC_REG_CR_RXEN_INDEX); + + smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_CR, mac_cr); +} + +int smsc9220_check_id(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t id = smsc9220_read_id(dev); + + return ((GET_BIT_FIELD(id, CHIP_ID_MASK, CHIP_ID_POS) == CHIP_ID) ? 0 : 1); +} + + +void smsc9220_enable_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + SET_BIT(register_map->irq_enable, source); +} + +void smsc9220_disable_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + CLR_BIT(register_map->irq_enable, source); +} + +void smsc9220_disable_all_interrupts(const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + register_map->irq_enable = 0; +} + +void smsc9220_clear_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + SET_BIT(register_map->irq_status, source); +} + +void smsc9220_clear_all_interrupts(const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + register_map->irq_status = UINT32_MAX; +} + +int smsc9220_get_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + return GET_BIT(register_map->irq_status, source); +} + +void smsc9220_establish_link(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t bcr = 0; + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_BCTRL, &bcr); + SET_BIT(bcr, PHY_REG_BCTRL_AUTO_NEG_EN_INDEX); + SET_BIT(bcr, PHY_REG_BCTRL_RST_AUTO_NEG_INDEX); + smsc9220_phy_regwrite(dev, SMSC9220_PHY_REG_OFFSET_BCTRL, bcr); + + SET_BIT(register_map->hw_cfg, HW_CFG_REG_MUST_BE_ONE_INDEX); +} + +enum smsc9220_error_t smsc9220_read_mac_address( + const struct smsc9220_eth_dev_t* dev, char *mac) +{ + uint32_t mac_low = 0; + uint32_t mac_high = 0; + + if(!mac) { + return SMSC9220_ERROR_PARAM; + } + + /* Read current mac address. */ + if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_ADDRH, &mac_high)) { + return SMSC9220_ERROR_INTERNAL; + } + if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_ADDRL, &mac_low)) { + return SMSC9220_ERROR_INTERNAL; + } + mac[0] = mac_low & 0xFF; + mac[1] = (mac_low >> 8) & 0xFF; + mac[2] = (mac_low >> 16) & 0xFF; + mac[3] = (mac_low >> 24) & 0xFF; + mac[4] = mac_high & 0xFF; + mac[5] = (mac_high >> 8) & 0xFF; + + return SMSC9220_ERROR_NONE; +} + +uint32_t smsc9220_get_tx_data_fifo_size( + const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + uint32_t tx_fifo_size = + GET_BIT_FIELD(register_map->hw_cfg, + TX_DATA_FIFO_SIZE_KBYTES_MASK, + TX_DATA_FIFO_SIZE_KBYTES_POS) * KBYTES_TO_BYTES_MULTIPLIER; + + return (tx_fifo_size - TX_STATUS_FIFO_SIZE_BYTES); +} + +enum smsc9220_error_t smsc9220_init( + const struct smsc9220_eth_dev_t* dev, + void(* wait_ms_function)(int)) +{ + uint32_t phyreset = 0; + enum smsc9220_error_t error = SMSC9220_ERROR_NONE; + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + if (!wait_ms_function) { + return SMSC9220_ERROR_PARAM; + } + dev->data->wait_ms = wait_ms_function; + + error = smsc9220_check_id(dev); + if(error != SMSC9220_ERROR_NONE) { + return error; + } + + error = smsc9220_soft_reset(dev); + if(error != SMSC9220_ERROR_NONE) { + return error; + } + + smsc9220_set_txfifo(dev, HW_CFG_REG_TX_FIFO_SIZE); + + SET_BIT_FIELD(register_map->afc_cfg, AFC_BACK_DUR_MASK, + AFC_BACK_DUR_POS, AFC_BACK_DUR); + SET_BIT_FIELD(register_map->afc_cfg, AFC_LOW_LEVEL_MASK, + AFC_LOW_LEVEL_POS, AFC_LOW_LEVEL); + SET_BIT_FIELD(register_map->afc_cfg, AFC_HIGH_LEVEL_MASK, + AFC_HIGH_LEVEL_POS, AFC_HIGH_LEVEL); + + error = smsc9220_wait_eeprom(dev); + if(error != SMSC9220_ERROR_NONE) { + return error; + } + + /* Configure GPIOs as LED outputs. */ + register_map->gpio_cfg = 0; + SET_BIT(register_map->gpio_cfg, GPIO_CFG_GPIO0_PUSHPULL_INDEX); + SET_BIT(register_map->gpio_cfg, GPIO_CFG_GPIO1_PUSHPULL_INDEX); + SET_BIT(register_map->gpio_cfg, GPIO_CFG_GPIO2_PUSHPULL_INDEX); + SET_BIT(register_map->gpio_cfg, GPIO_CFG_GPIO0_LED_INDEX); + SET_BIT(register_map->gpio_cfg, GPIO_CFG_GPIO1_LED_INDEX); + SET_BIT(register_map->gpio_cfg, GPIO_CFG_GPIO2_LED_INDEX); + + smsc9220_init_irqs(dev); + + /* Configure MAC addresses here if needed. */ + + error = smsc9220_check_phy(dev); + if(error != SMSC9220_ERROR_NONE) { + return error; + } + + error = smsc9220_reset_phy(dev); + if(error != SMSC9220_ERROR_NONE) { + return error; + } + + if (dev->data->wait_ms) { + dev->data->wait_ms(PHY_RESET_TIME_OUT_MS); + } + /* Checking whether phy reset completed successfully.*/ + error = smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_BCTRL, + &phyreset); + if(error != SMSC9220_ERROR_NONE) { + return error; + } + + if(GET_BIT(phyreset, PHY_REG_BCTRL_RESET_INDEX)) { + return SMSC9220_ERROR_INTERNAL; + } + + smsc9220_advertise_cap(dev); + smsc9220_establish_link(dev); + + smsc9220_enable_mac_xmit(dev); + smsc9220_enable_xmit(dev); + smsc9220_enable_mac_recv(dev); + + /* This sleep is compulsory otherwise txmit/receive will fail. */ + if (dev->data->wait_ms) { + dev->data->wait_ms(INIT_FINISH_DELAY); + } + dev->data->state = 1; + + return SMSC9220_ERROR_NONE; +} + +enum smsc9220_error_t smsc9220_send_by_chunks( + const struct smsc9220_eth_dev_t* dev, + uint32_t total_payload_length, + bool is_new_packet, + const char *data, uint32_t current_size) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + /* signing this is the first segment of the packet to be sent */ + bool is_first_segment = false; + /* signing this is the last segment of the packet to be sent */ + bool is_last_segment = false; + uint32_t txcmd_a, txcmd_b = 0; + uint32_t tx_buffer_free_space = 0; + volatile uint32_t xmit_stat = 0; + + if (!data) { + return SMSC9220_ERROR_PARAM; + } + + if (is_new_packet) { + is_first_segment = true; + dev->data->ongoing_packet_length = total_payload_length; + dev->data->ongoing_packet_length_sent = 0; + } else if (dev->data->ongoing_packet_length != total_payload_length || + dev->data->ongoing_packet_length_sent >= total_payload_length) { + return SMSC9220_ERROR_PARAM; + } + + /* Would next chunk fit into buffer? */ + tx_buffer_free_space = GET_BIT_FIELD(register_map->tx_fifo_inf, + FIFO_USED_SPACE_MASK, + DATA_FIFO_USED_SPACE_POS); + if (current_size > tx_buffer_free_space) { + return SMSC9220_ERROR_INTERNAL; /* Not enough space in FIFO */ + } + if ((dev->data->ongoing_packet_length_sent + current_size) == + total_payload_length) { + is_last_segment = true; + } + + txcmd_a = 0; + txcmd_b = 0; + + if (is_last_segment) { + SET_BIT(txcmd_a, TX_COMMAND_A_LAST_SEGMENT_INDEX); + } + if (is_first_segment) { + SET_BIT(txcmd_a, TX_COMMAND_A_FIRST_SEGMENT_INDEX); + } + + uint32_t data_start_offset_bytes = (4 - (current_size % 4)); + + SET_BIT_FIELD(txcmd_a, TX_CMD_PKT_LEN_BYTES_MASK, 0, current_size); + SET_BIT_FIELD(txcmd_a, TX_CMD_DATA_START_OFFSET_BYTES_MASK, + TX_CMD_DATA_START_OFFSET_BYTES_POS, + data_start_offset_bytes); + + SET_BIT_FIELD(txcmd_b, TX_CMD_PKT_LEN_BYTES_MASK, 0, current_size); + SET_BIT_FIELD(txcmd_b, TX_CMD_PKT_TAG_MASK, TX_CMD_PKT_TAG_POS, + current_size); + + register_map->tx_data_port = txcmd_a; + register_map->tx_data_port = txcmd_b; + + fill_tx_fifo(dev, (uint8_t *)data, current_size); + + if (is_last_segment) { + /* Pop status port for error check */ + xmit_stat = register_map->tx_status_port; + (void)xmit_stat; + } + dev->data->ongoing_packet_length_sent += current_size; + return SMSC9220_ERROR_NONE; +} + +uint32_t smsc9220_get_rxfifo_data_used_space(const struct + smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + return GET_BIT_FIELD(register_map->rx_fifo_inf, FIFO_USED_SPACE_MASK, + DATA_FIFO_USED_SPACE_POS); +} + +uint32_t smsc9220_receive_by_chunks(const struct smsc9220_eth_dev_t* dev, + char *data, uint32_t dlen) +{ + + uint32_t rxfifo_inf = 0; + uint32_t rxfifo_stat = 0; + uint32_t packet_length_byte = 0; + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + if (!data) { + return 0; /* Invalid input parameter, cannot read */ + } + rxfifo_inf = register_map->rx_fifo_inf; + + if(rxfifo_inf & 0xFFFF) { /* If there's data */ + rxfifo_stat = register_map->rx_status_port; + if(rxfifo_stat != 0) { /* Fetch status of this packet */ + /* Ethernet controller is padding to 32bit aligned data */ + packet_length_byte = GET_BIT_FIELD(rxfifo_stat, + RX_FIFO_STATUS_PKT_LENGTH_MASK, + RX_FIFO_STATUS_PKT_LENGTH_POS); + packet_length_byte -= 4; + dev->data->current_rx_size_words = packet_length_byte; + } + } + + empty_rx_fifo(dev, (uint8_t *)data, packet_length_byte); + dev->data->current_rx_size_words = 0; + return packet_length_byte; +} + +uint32_t smsc9220_peek_next_packet_size(const struct + smsc9220_eth_dev_t* dev) +{ + uint32_t packet_size = 0; + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + if(smsc9220_get_rxfifo_data_used_space(dev)) { + packet_size = GET_BIT_FIELD(register_map->rx_status_peek, + RX_FIFO_STATUS_PKT_LENGTH_MASK, + RX_FIFO_STATUS_PKT_LENGTH_POS); + } + return packet_size; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth_drv.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth_drv.h new file mode 100644 index 0000000000..aa60b4f95f --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth_drv.h @@ -0,0 +1,548 @@ +/* + * Copyright (c) 2016-2018 ARM Limited + * + * 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. + */ + +/** + * \file smsc9220_drv.h + * \brief Generic driver for SMSC9220 Ethernet controller + */ + +#ifndef __SMSC9220_ETH_H__ +#define __SMSC9220_ETH_H__ + +#include "stdbool.h" +#include "stdint.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** SMSC9220 device configuration structure */ +struct smsc9220_eth_dev_cfg_t { + const uint32_t base; /*!< SMSC9220 base address */ +}; + +/** SMSC9220 device data structure */ +struct smsc9220_eth_dev_data_t { + uint32_t state; /*!< Indicates if the SMSC9220 driver + is initialized and enabled */ + void (*wait_ms) (int);/*!< function pointer to system's millisec delay + function, will be used for delays */ + uint32_t ongoing_packet_length;/*!< size in bytes of the packet + is being sent */ + uint32_t ongoing_packet_length_sent; /*!< size in bytes of the packet + has been sent */ + uint32_t current_rx_size_words; /*!< Data length in words, + currently is being read */ +}; + +/** SMSC9220 device structure */ +struct smsc9220_eth_dev_t { + const struct smsc9220_eth_dev_cfg_t* const cfg; /*!< configuration */ + struct smsc9220_eth_dev_data_t* const data; /*!< data */ +}; + +/** + * \brief Error code definitions + * + */ +enum smsc9220_error_t{ + SMSC9220_ERROR_NONE = 0U, /*!< no error */ + SMSC9220_ERROR_TIMEOUT = 1U, /*!< timeout */ + SMSC9220_ERROR_BUSY = 2U, /*!< no error */ + SMSC9220_ERROR_PARAM = 3U, /*!< invalid parameter */ + SMSC9220_ERROR_INTERNAL = 4U /*!< internal error */ +}; + +/** + * \brief Interrupt source definitions + * + */ +enum smsc9220_interrupt_source { + SMSC9220_INTERRUPT_GPIO0 = 0U, + SMSC9220_INTERRUPT_GPIO1 = 1U, + SMSC9220_INTERRUPT_GPIO2 = 2U, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL = 3U, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_FULL = 4U, + /* 5 Reserved according to Datasheet */ + SMSC9220_INTERRUPT_RX_DROPPED_FRAME = 6U, + SMSC9220_INTERRUPT_TX_STATUS_FIFO_LEVEL = 7U, + SMSC9220_INTERRUPT_TX_STATUS_FIFO_FULL = 8U, + SMSC9220_INTERRUPT_TX_DATA_FIFO_AVAILABLE = 9U, + SMSC9220_INTERRUPT_TX_DATA_FIFO_OVERRUN = 10U, + /* 11, 12 Reserved according to Datasheet */ + SMSC9220_INTERRUPT_TX_ERROR = 13U, + SMSC9220_INTERRUPT_RX_ERROR = 14U, + SMSC9220_INTERRUPT_RX_WATCHDOG_TIMEOUT = 15U, + SMSC9220_INTERRUPT_TX_STATUS_OVERFLOW = 16U, + SMSC9220_INTERRUPT_TX_POWER_MANAGEMENT = 17U, + SMSC9220_INTERRUPT_PHY = 18U, + SMSC9220_INTERRUPT_GP_TIMER = 19U, + SMSC9220_INTERRUPT_RX_DMA = 20U, + SMSC9220_INTERRUPT_TX_IOC = 21U, + /* 22 Reserved according to Datasheet*/ + SMSC9220_INTERRUPT_RX_DROPPED_FRAME_HALF = 23U, + SMSC9220_INTERRUPT_RX_STOPPED = 24U, + SMSC9220_INTERRUPT_TX_STOPPED = 25U, + /* 26 - 30 Reserved according to Datasheet*/ + SMSC9220_INTERRUPT_SW = 31U +}; + +/** + * \brief MAC register offset definitions + * + */ +enum smsc9220_mac_reg_offsets_t{ + SMSC9220_MAC_REG_OFFSET_CR = 0x1U, + SMSC9220_MAC_REG_OFFSET_ADDRH = 0x2U, + SMSC9220_MAC_REG_OFFSET_ADDRL = 0x3U, + SMSC9220_MAC_REG_OFFSET_HASHH = 0x4U, + SMSC9220_MAC_REG_OFFSET_HASHL = 0x5U, + SMSC9220_MAC_REG_OFFSET_MII_ACC = 0x6U, + SMSC9220_MAC_REG_OFFSET_MII_DATA = 0x7U, + SMSC9220_MAC_REG_OFFSET_FLOW = 0x8U, + SMSC9220_MAC_REG_OFFSET_VLAN1 = 0x9U, + SMSC9220_MAC_REG_OFFSET_VLAN2 = 0xAU, + SMSC9220_MAC_REG_OFFSET_WUFF = 0xBU, + SMSC9220_MAC_REG_OFFSET_WUCSR = 0xCU, + SMSC9220_MAC_REG_OFFSET_COE_CR = 0xDU +}; + +/** + * \brief PHY register offset definitions + * + */ +enum phy_reg_offsets_t{ + SMSC9220_PHY_REG_OFFSET_BCTRL = 0x0U, + SMSC9220_PHY_REG_OFFSET_BSTATUS = 0x1U, + SMSC9220_PHY_REG_OFFSET_ID1 = 0x2U, + SMSC9220_PHY_REG_OFFSET_ID2 = 0x3U, + SMSC9220_PHY_REG_OFFSET_ANEG_ADV = 0x4U, + SMSC9220_PHY_REG_OFFSET_ANEG_LPA = 0x5U, + SMSC9220_PHY_REG_OFFSET_ANEG_EXP = 0x6U, + SMSC9220_PHY_REG_OFFSET_MCONTROL = 0x17U, + SMSC9220_PHY_REG_OFFSET_MSTATUS = 0x18U, + SMSC9220_PHY_REG_OFFSET_CSINDICATE = 0x27U, + SMSC9220_PHY_REG_OFFSET_INTSRC = 0x29U, + SMSC9220_PHY_REG_OFFSET_INTMASK = 0x30U, + SMSC9220_PHY_REG_OFFSET_CS = 0x31U +}; + +/* Bit definitions for PHY Basic Status Register */ +#define PHY_REG_BSTATUS_EXTENDED_CAPABILITIES_INDEX 0U +#define PHY_REG_BSTATUS_JABBER_DETECT_INDEX 1U +#define PHY_REG_BSTATUS_LINK_STATUS_INDEX 2U +#define PHY_REG_BSTATUS_AUTO_NEG_ABILITY_INDEX 3U +#define PHY_REG_BSTATUS_REMOTE_FAULT_INDEX 4U +#define PHY_REG_BSTATUS_AUTO_NEG_COMPLETE_INDEX 5U +#define PHY_REG_BSTATUS_10BASE_T_HALF_DUPLEX_INDEX 11U +#define PHY_REG_BSTATUS_10BASE_T_FULL_DUPLEX_INDEX 12U +#define PHY_REG_BSTATUS_100BASE_TX_HALF_DUPLEX_INDEX 13U +#define PHY_REG_BSTATUS_100BASE_TX_FULL_DUPLEX_INDEX 14U +#define PHY_REG_BSTATUS_100BASE_T4_INDEX 15U + +/** + * \brief FIFO Level Interrupt bit definitions + * + */ +enum smsc9220_fifo_level_irq_pos_t{ + SMSC9220_FIFO_LEVEL_IRQ_RX_STATUS_POS = 0U, + SMSC9220_FIFO_LEVEL_IRQ_TX_STATUS_POS = 16U, + SMSC9220_FIFO_LEVEL_IRQ_TX_DATA_POS = 24U +}; + +/** + * \brief FIFO Level Interrupt limits + * + */ +#define SMSC9220_FIFO_LEVEL_IRQ_MASK 0xFFU +#define SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN 0U +#define SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX SMSC9220_FIFO_LEVEL_IRQ_MASK + +/** + * \brief Initializes SMSC9220 Ethernet controller to a known default state: + * - device ID is checked + * - global interrupt is enabled, but all irq sources are disabled + * - all capabilities are advertised + * - 10Mbps able + * - 10Mbps with full duplex + * - 100Mbps Tx able + * - 100Mbps with full duplex + * - Symmetric Pause + * - Asymmetric Pause + * - Establish link enabled + * - Rx enabled + * - Tx enabled + * Init should be called prior to any other process and + * it's the caller's responsibility to follow proper call order. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] wait_ms_function function pointer to a millisec delay function + * for proper timing of some processes + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_init(const struct smsc9220_eth_dev_t* dev, + void(* wait_ms_function)(int)); + +/** + * \brief Read MAC register. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] regoffset Register offset + * \param[in, out] data Pointer to register will be read + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_mac_regread( + const struct smsc9220_eth_dev_t* dev, + enum smsc9220_mac_reg_offsets_t regoffset, + uint32_t *data); + +/** + * \brief Write MAC register. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] regoffset Register offset + * \param[in] data Register value to write + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_mac_regwrite( + const struct smsc9220_eth_dev_t* dev, + enum smsc9220_mac_reg_offsets_t regoffset, + uint32_t data); + +/** + * \brief Read PHY register. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] regoffset Register offset + * \param[out] data Register value is read + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_phy_regread( + const struct smsc9220_eth_dev_t* dev, + enum phy_reg_offsets_t, + uint32_t *data); + +/** + * \brief Write PHY register. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] regoffset Register offset + * \param[in] data Register value to write + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_phy_regwrite( + const struct smsc9220_eth_dev_t* dev, + enum phy_reg_offsets_t, + uint32_t data); + +/** + * \brief Read SMSC9220 ID. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return ID number + */ +uint32_t smsc9220_read_id(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Initiates a soft reset, returns failure or success. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_soft_reset( + const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Set maximum transition unit by Tx fifo size. + * Note: The MTU will be smaller by 512 bytes, + * because the status uses this fixed space. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] val Size of the fifo in kbytes + * \ref HW_CFG_REG_TX_FIFO_SIZE_MIN + * \ref HW_CFG_REG_TX_FIFO_SIZE_MAX + */ +void smsc9220_set_txfifo(const struct smsc9220_eth_dev_t* dev, + uint32_t val); + +/** + * \brief Set FIFO level interrupt for a given source + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] irq_level_pos Bit position of the FIFO to set + * \ref smsc9220_fifo_level_irq_pos_t + * \param[in] level Level of the FIFO, when the FIFO used space is greater + * than this value, corresponding interrupt will be generated. + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_set_fifo_level_irq( + const struct smsc9220_eth_dev_t* dev, + enum smsc9220_fifo_level_irq_pos_t irq_level_pos, + uint32_t level); + +/** + * \brief Wait for EEPROM to be ready to use. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_wait_eeprom( + const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Initialise irqs by clearing and disabling all interrupt sources + * and enable interrupts. Since all interrupt sources are disabled, + * interrupt won't be triggered, until interrupt sources won't be + * enabled by \ref smsc9220_enable_interrupt + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_init_irqs(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Check PHY ID registers. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_check_phy(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Reset PHY + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_reset_phy(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Advertise all speeds and pause capabilities + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_advertise_cap(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Enable transmission + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_enable_xmit(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Disable transmission + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_disable_xmit(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Enable MAC transmitter + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_enable_mac_xmit(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Disable MAC transmitter + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_disable_mac_xmit(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Enable receive + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_enable_mac_recv(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Disable receive + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_disable_mac_recv(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Enable the given interrupt source. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] source Enum of the interrupt source. + */ +void smsc9220_enable_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source); + +/** + * \brief Disable the given interrupt source. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] source Enum of the interrupt source. + */ +void smsc9220_disable_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source); + +/** + * \brief Disable all of the interrupt sources. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_disable_all_interrupts(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Clear the given interrupt source. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] source Enum of the interrupt source. + */ +void smsc9220_clear_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source); + +/** + * \brief Clear all of the interrupt sources. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_clear_all_interrupts(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Get the status of the given interrupt source. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] source Enum of the interrupt source. + * + * \return non-zero if the given interrupt source is triggered, zero otherwise + */ +int smsc9220_get_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source); + +/** + * \brief Establish link + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_establish_link(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Read MAC address from EEPROM. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in,out] mac array will include the read MAC address in + * 6 bytes hexadecimal format. + * It should be allocated by the caller to 6 bytes. + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_read_mac_address( + const struct smsc9220_eth_dev_t* dev, char *mac); + +/** + * \brief Check device ID. + * + * \return error code /ref smsc9220_error_t + */ +int smsc9220_check_id(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Get the data size of the Tx buffer, aka Maximum Transition Unit + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return Fifo data size in bytes + */ +uint32_t smsc9220_get_tx_data_fifo_size(const struct + smsc9220_eth_dev_t* dev); + +/** + * \brief Send Ethernet packet from buffer chain. + * The full packet length should be known in the beginning + * of a new packet. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] total_payload_length Length of the ethernet payload. + * Should be equal to the sum of passed buffers within a packet. + * \param[in] is_new_packet Should be set to true if the input buffer has to + * be sent as the start of a new packet or as a full packet. + * \param[in] data Pointer to the data should be sent. + * \param[in] current_size Size of the data in bytes. + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_send_by_chunks( + const struct smsc9220_eth_dev_t* dev, + uint32_t total_payload_length, + bool is_new_packet, + const char *data, uint32_t current_size); + +/** + * \brief Receive Ethernet packet from Rx FIFO to the passed buffer. + * Stops reading at packet border. + * If the passed buffer is larger than the current packet, + * the whole packet will be read into the buffer. + * If the current packet is larger than the passed buffer, + * the buffer will be filled with data and the next call + * will continue the read from that point. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in,out] data Pointer where the data will be read to. + * The caller is responsible to allocate it. + * \param[in] dlen Length of the allocated data in bytes. + * + * \return Remaining bytes left in the fifo of the current packet. + */ +uint32_t smsc9220_receive_by_chunks(const struct smsc9220_eth_dev_t* dev, + char *data, uint32_t dlen); + +/** + * \brief Get the used space of Rx fifo in bytes. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return Data received and waiting for read in bytes + */ +uint32_t smsc9220_get_rxfifo_data_used_space(const struct + smsc9220_eth_dev_t* dev); + +/** + * \brief Get the size of next unread packet in Rx buffer, using the peak + * register, which is not destructive so can be read asynchronously. + * Warning: In case of heavy receiving load, it's possible this register + * is not perfectly in sync. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return Size in bytes of the next packet can be read from Rx fifo, according + * to the peek register. + */ +uint32_t smsc9220_peek_next_packet_size(const struct + smsc9220_eth_dev_t* dev); + +#ifdef __cplusplus +} +#endif + +#endif /* __SMSC9220_ETH_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c index 53524a3594..ccfab4b4ac 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c @@ -270,3 +270,13 @@ static struct arm_uart_dev_data_t ARM_UART4_DEV_DATA = { struct arm_uart_dev_t ARM_UART4_DEV = {&(ARM_UART4_DEV_CFG), &(ARM_UART4_DEV_DATA)}; #endif /* ARM_UART4 */ + +/* SMSC9220 Ethernet driver structures */ +#ifdef SMSC9220_ETH +static const struct smsc9220_eth_dev_cfg_t SMSC9220_ETH_DEV_CFG = { + .base = SMSC9220_BASE}; +static struct smsc9220_eth_dev_data_t SMSC9220_ETH_DEV_DATA = { + .state = 0}; +struct smsc9220_eth_dev_t SMSC9220_ETH_DEV = {&(SMSC9220_ETH_DEV_CFG), + &(SMSC9220_ETH_DEV_DATA)}; +#endif \ No newline at end of file diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h index c33f07e25b..14fdc45bc2 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h @@ -26,6 +26,7 @@ #include "arm_mps2_io_drv.h" #include "spi_pl022_drv.h" #include "arm_uart_drv.h" +#include "smsc9220_eth_drv.h" /* ======= Defines peripheral configuration structures ======= */ @@ -96,4 +97,8 @@ extern struct arm_uart_dev_t ARM_UART3_DEV; extern struct arm_uart_dev_t ARM_UART4_DEV; #endif +#ifdef SMSC9220_ETH +extern struct smsc9220_eth_dev_t SMSC9220_ETH_DEV; +#endif + #endif /* __ARM_LTD_PLATFORM_DEVICES_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/ethernet_api.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/ethernet_api.c deleted file mode 100644 index d9755dfb33..0000000000 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/ethernet_api.c +++ /dev/null @@ -1,85 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited - * - * 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. - */ -#include - -#include "ethernet_api.h" -#include "cmsis.h" -#include "mbed_interface.h" -#include "mbed_toolchain.h" -#include "mbed_error.h" -#include "mbed_wait_api.h" -#include "smsc9220_eth.h" - -/*---------------------------------------------------------------------------- - Ethernet Device initialize - *----------------------------------------------------------------------------*/ -int ethernet_init() -{ - return smsc9220_init(); -} - -/*---------------------------------------------------------------------------- - Ethernet Device Uninitialize - *----------------------------------------------------------------------------*/ -void ethernet_free() -{ - /* Uninitialize function is not implemented in Ethernet driver. */ -} - -int ethernet_write(const char *data, int size) -{ - /* smsc9220 cannot provide the functionality of writing into the tx buffer */ - /* by chunks, without knowing the full size of the packet in the beginning */ - return 0; -} - -int ethernet_send() -{ - /* smsc9220 cannot provide the functionality of writing into the tx buffer */ - /* by chunks, without knowing the full size of the packet in the beginning */ - return 0; -} - -int ethernet_receive() -{ - return smsc9220_peek_next_packet_size(); -} - -/* Read from an recevied ethernet packet.*/ -/* After receive returnd a number bigger than 0 it is*/ -/* possible to read bytes from this packet.*/ -/* Read will write up to size bytes into data.*/ -/* It is possible to use read multible times.*/ -/* Each time read will start reading after the last read byte before. */ -int ethernet_read(char *data, int dlen) -{ - return smsc9220_receive_by_chunks(data, dlen); -} - -void ethernet_address(char *mac) -{ - smsc9220_read_mac_address(mac); -} - -int ethernet_link(void) -{ - return 0; -} - -void ethernet_set_link(int speed, int duplex) -{ - smsc9220_establish_link(); -} diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/flash_api.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/flash_api.c index 2a96377aeb..a86a95fb9d 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/flash_api.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/flash_api.c @@ -101,3 +101,10 @@ uint32_t flash_get_size(const flash_t *obj) return FLASH_SIZE; } + +uint8_t flash_get_erase_value(const flash_t *obj) +{ + (void)obj; + + return 0xFF; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/mbed_overrides.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/mbed_overrides.c index 1531692bce..2fdfa0d75e 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/mbed_overrides.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/mbed_overrides.c @@ -1,6 +1,6 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited + * Copyright (c) 2006-2018 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,10 +15,12 @@ * limitations under the License. */ -#include "smsc9220_eth.h" +#include "platform_devices.h" +#include "smsc9220_eth_drv.h" /* Provide ethernet devices with a semi-unique MAC address from the UUID */ void mbed_mac_address(char *mac) { - smsc9220_read_mac_address(mac); + smsc9220_read_mac_address(&SMSC9220_ETH_DEV, mac); } + diff --git a/targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/TOOLCHAIN_GCC_ARM/ADuCM3029.ld b/targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/TOOLCHAIN_GCC_ARM/ADuCM3029.ld index c645aa5891..b78bfa9bc9 100755 --- a/targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/TOOLCHAIN_GCC_ARM/ADuCM3029.ld +++ b/targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/TOOLCHAIN_GCC_ARM/ADuCM3029.ld @@ -128,7 +128,7 @@ SECTIONS /* .copy.table : { - . = ALIGN(4); + . = ALIGN(8); __copy_table_start__ = .; LONG (__etext) LONG (__data_start__) @@ -146,7 +146,7 @@ SECTIONS .zero.table : { - . = ALIGN(4); + . = ALIGN(8); __zero_table_start__ = .; LONG (__bss_start__) LONG (__bss_end__ - __bss_start__) @@ -164,13 +164,13 @@ SECTIONS *(vtable) *(.data*) - . = ALIGN(4); + . = ALIGN(8); /* preinit data */ PROVIDE_HIDDEN (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* init data */ PROVIDE_HIDDEN (__init_array_start = .); KEEP(*(SORT(.init_array.*))) @@ -178,7 +178,7 @@ SECTIONS PROVIDE_HIDDEN (__init_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* finit data */ PROVIDE_HIDDEN (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) @@ -186,7 +186,7 @@ SECTIONS PROVIDE_HIDDEN (__fini_array_end = .); KEEP(*(.jcr*)) - . = ALIGN(4); + . = ALIGN(8); /* All data end */ __data_end__ = .; @@ -194,7 +194,7 @@ SECTIONS .bss : { - . = ALIGN(4); + . = ALIGN(8); __bss_start__ = .; KEEP(*(.bss.gChannelControlDataArray)) KEEP(*(.bss.thread_stack_main)) @@ -202,16 +202,16 @@ SECTIONS KEEP(*(.bss.os_thread_def_stack_event_loop_thread)) *(COMMON) *(.bss) - . = ALIGN(4); + . = ALIGN(8); __bss_end__ = .; } > DSRAM_C .bss2 : { - . = ALIGN(4); + . = ALIGN(8); __bss2_start__ = .; *(.bss*) - . = ALIGN(4); + . = ALIGN(8); __bss2_end__ = .; } > DSRAM_B diff --git a/targets/TARGET_Analog_Devices/TARGET_ADUCM4X50/TARGET_ADUCM4050/TOOLCHAIN_GCC_ARM/ADuCM4050.ld b/targets/TARGET_Analog_Devices/TARGET_ADUCM4X50/TARGET_ADUCM4050/TOOLCHAIN_GCC_ARM/ADuCM4050.ld index b5fbca4cb9..d025aae5c8 100755 --- a/targets/TARGET_Analog_Devices/TARGET_ADUCM4X50/TARGET_ADUCM4050/TOOLCHAIN_GCC_ARM/ADuCM4050.ld +++ b/targets/TARGET_Analog_Devices/TARGET_ADUCM4X50/TARGET_ADUCM4050/TOOLCHAIN_GCC_ARM/ADuCM4050.ld @@ -130,7 +130,7 @@ SECTIONS /* .copy.table : { - . = ALIGN(4); + . = ALIGN(8); __copy_table_start__ = .; LONG (__etext) LONG (__data_start__) @@ -148,7 +148,7 @@ SECTIONS .zero.table : { - . = ALIGN(4); + . = ALIGN(8); __zero_table_start__ = .; LONG (__bss_start__) LONG (__bss_end__ - __bss_start__) @@ -166,13 +166,13 @@ SECTIONS *(vtable) *(.data*) - . = ALIGN(4); + . = ALIGN(8); /* preinit data */ PROVIDE_HIDDEN (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* init data */ PROVIDE_HIDDEN (__init_array_start = .); KEEP(*(SORT(.init_array.*))) @@ -180,7 +180,7 @@ SECTIONS PROVIDE_HIDDEN (__init_array_end = .); - . = ALIGN(4); + . = ALIGN(8); /* finit data */ PROVIDE_HIDDEN (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) @@ -188,7 +188,7 @@ SECTIONS PROVIDE_HIDDEN (__fini_array_end = .); KEEP(*(.jcr*)) - . = ALIGN(4); + . = ALIGN(8); /* All data end */ __data_end__ = .; diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21G18A/device/TOOLCHAIN_ARM_MICRO/SAMD21G18A.sct b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21G18A/device/TOOLCHAIN_ARM_MICRO/SAMD21G18A.sct index ae0aa0031d..7fda6ed398 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21G18A/device/TOOLCHAIN_ARM_MICRO/SAMD21G18A.sct +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21G18A/device/TOOLCHAIN_ARM_MICRO/SAMD21G18A.sct @@ -11,8 +11,8 @@ LR_IROM1 0x00000000 0x40000 { ; load region size_region .ANY (+RO) } - ; [RAM] Vector table dynamic copy: 45 vectors * 4 bytes = (0xB4) - alignment - RW_IRAM1 (0x20000000+0xB4) (0x8000-0xB4) { ; RW data + ; [RAM] Vector table dynamic copy: 45 vectors * 4 bytes = (0xB4+0x4) 8-byte alignment + RW_IRAM1 (0x20000000+0xB8) (0x8000-0xB8) { ; RW data .ANY (+RW +ZI) } diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21G18A/device/TOOLCHAIN_ARM_STD/SAMD21G18A.sct b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21G18A/device/TOOLCHAIN_ARM_STD/SAMD21G18A.sct index ae0aa0031d..7fda6ed398 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21G18A/device/TOOLCHAIN_ARM_STD/SAMD21G18A.sct +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21G18A/device/TOOLCHAIN_ARM_STD/SAMD21G18A.sct @@ -11,8 +11,8 @@ LR_IROM1 0x00000000 0x40000 { ; load region size_region .ANY (+RO) } - ; [RAM] Vector table dynamic copy: 45 vectors * 4 bytes = (0xB4) - alignment - RW_IRAM1 (0x20000000+0xB4) (0x8000-0xB4) { ; RW data + ; [RAM] Vector table dynamic copy: 45 vectors * 4 bytes = (0xB4+0x4) 8-byte alignment + RW_IRAM1 (0x20000000+0xB8) (0x8000-0xB8) { ; RW data .ANY (+RW +ZI) } diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21G18A/device/TOOLCHAIN_GCC_ARM/samd21g18a.ld b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21G18A/device/TOOLCHAIN_GCC_ARM/samd21g18a.ld index b8c2983cd6..21334d715a 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21G18A/device/TOOLCHAIN_GCC_ARM/samd21g18a.ld +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21G18A/device/TOOLCHAIN_GCC_ARM/samd21g18a.ld @@ -5,7 +5,7 @@ SEARCH_DIR(.) /* Memory Spaces Definitions */ MEMORY { rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 - ram (rwx) : ORIGIN = 0x20000000 + 0xB4, LENGTH = 0x00008000 - 0xB4 + ram (rwx) : ORIGIN = 0x20000000 + 0xB8, LENGTH = 0x00008000 - 0xB8 } /* The stack size used by the application. NOTE: you need to adjust according to your application. */ @@ -15,7 +15,7 @@ MEMORY { SECTIONS { .text : { - . = ALIGN(4); + . = ALIGN(8); _sfixed = .; KEEP(*(.vectors .vectors.*)) *(.text .text.* .gnu.linkonce.t.*) @@ -25,29 +25,29 @@ MEMORY { /* Support C constructors, and C destructors in both user code and the C library. This also provides support for C++ code. */ - . = ALIGN(4); + . = ALIGN(8); KEEP(*(.init)) - . = ALIGN(4); + . = ALIGN(8); __preinit_array_start = .; KEEP (*(.preinit_array)) __preinit_array_end = .; - . = ALIGN(4); + . = ALIGN(8); __init_array_start = .; KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) __init_array_end = .; - . = ALIGN(4); + . = ALIGN(8); KEEP (*crtbegin.o(.ctors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*crtend.o(.ctors)) - . = ALIGN(4); + . = ALIGN(8); KEEP(*(.fini)) - . = ALIGN(4); + . = ALIGN(8); __fini_array_start = .; KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) @@ -58,7 +58,7 @@ MEMORY { KEEP (*(SORT(.dtors.*))) KEEP (*crtend.o(.dtors)) - . = ALIGN(4); + . = ALIGN(8); _efixed = .; /* End of text section */ } > rom @@ -70,36 +70,36 @@ MEMORY { } > rom PROVIDE_HIDDEN (__exidx_end = .); - . = ALIGN(4); + . = ALIGN(8); _etext = .; .relocate : AT (_etext) { - . = ALIGN(4); + . = ALIGN(8); _srelocate = .; *(.ramfunc .ramfunc.*); *(.data .data.*); - . = ALIGN(4); + . = ALIGN(8); _erelocate = .; } > ram /* .bss section which is used for uninitialized data */ .bss (NOLOAD) : { - . = ALIGN(4); + . = ALIGN(8); _sbss = . ; _szero = .; *(.bss .bss.*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); _ebss = . ; _ezero = .; } > ram .heap (NOLOAD) : { - . = ALIGN(4); + . = ALIGN(8); __end__ = . ; . = ORIGIN(ram) + LENGTH(ram) - STACK_SIZE; } > ram @@ -114,5 +114,5 @@ MEMORY { _estack = .; } > ram - . = ALIGN(4); + . = ALIGN(8); } diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21J18A/device/TOOLCHAIN_ARM_MICRO/SAMD21J18A.sct b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21J18A/device/TOOLCHAIN_ARM_MICRO/SAMD21J18A.sct index 2fa9c77d26..0d7409619f 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21J18A/device/TOOLCHAIN_ARM_MICRO/SAMD21J18A.sct +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21J18A/device/TOOLCHAIN_ARM_MICRO/SAMD21J18A.sct @@ -11,8 +11,8 @@ LR_IROM1 0x00000000 0x40000 { ; load region size_region .ANY (+RO) } - ; [RAM] Vector table dynamic copy: 45 vectors * 4 bytes = (0xB4) - alignment - RW_IRAM1 (0x20000000+0xB4) (0x8000-0xB4) { ; RW data + ; [RAM] Vector table dynamic copy: 45 vectors * 4 bytes = (0xB4 +0x4) 8-byte alignment + RW_IRAM1 (0x20000000+0xB8) (0x8000-0xB8) { ; RW data .ANY (+RW +ZI) } diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21J18A/device/TOOLCHAIN_ARM_STD/SAMD21J18A.sct b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21J18A/device/TOOLCHAIN_ARM_STD/SAMD21J18A.sct index 2fa9c77d26..49ff53cda2 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21J18A/device/TOOLCHAIN_ARM_STD/SAMD21J18A.sct +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21J18A/device/TOOLCHAIN_ARM_STD/SAMD21J18A.sct @@ -11,8 +11,8 @@ LR_IROM1 0x00000000 0x40000 { ; load region size_region .ANY (+RO) } - ; [RAM] Vector table dynamic copy: 45 vectors * 4 bytes = (0xB4) - alignment - RW_IRAM1 (0x20000000+0xB4) (0x8000-0xB4) { ; RW data + ; [RAM] Vector table dynamic copy: 45 vectors * 4 bytes = (0xB4+0x4) 8-byte alignment + RW_IRAM1 (0x20000000+0xB8) (0x8000-0xB8) { ; RW data .ANY (+RW +ZI) } diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21J18A/device/TOOLCHAIN_GCC_ARM/samd21j18a.ld b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21J18A/device/TOOLCHAIN_GCC_ARM/samd21j18a.ld index b8c2983cd6..21334d715a 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21J18A/device/TOOLCHAIN_GCC_ARM/samd21j18a.ld +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMD21J18A/device/TOOLCHAIN_GCC_ARM/samd21j18a.ld @@ -5,7 +5,7 @@ SEARCH_DIR(.) /* Memory Spaces Definitions */ MEMORY { rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 - ram (rwx) : ORIGIN = 0x20000000 + 0xB4, LENGTH = 0x00008000 - 0xB4 + ram (rwx) : ORIGIN = 0x20000000 + 0xB8, LENGTH = 0x00008000 - 0xB8 } /* The stack size used by the application. NOTE: you need to adjust according to your application. */ @@ -15,7 +15,7 @@ MEMORY { SECTIONS { .text : { - . = ALIGN(4); + . = ALIGN(8); _sfixed = .; KEEP(*(.vectors .vectors.*)) *(.text .text.* .gnu.linkonce.t.*) @@ -25,29 +25,29 @@ MEMORY { /* Support C constructors, and C destructors in both user code and the C library. This also provides support for C++ code. */ - . = ALIGN(4); + . = ALIGN(8); KEEP(*(.init)) - . = ALIGN(4); + . = ALIGN(8); __preinit_array_start = .; KEEP (*(.preinit_array)) __preinit_array_end = .; - . = ALIGN(4); + . = ALIGN(8); __init_array_start = .; KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) __init_array_end = .; - . = ALIGN(4); + . = ALIGN(8); KEEP (*crtbegin.o(.ctors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*crtend.o(.ctors)) - . = ALIGN(4); + . = ALIGN(8); KEEP(*(.fini)) - . = ALIGN(4); + . = ALIGN(8); __fini_array_start = .; KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) @@ -58,7 +58,7 @@ MEMORY { KEEP (*(SORT(.dtors.*))) KEEP (*crtend.o(.dtors)) - . = ALIGN(4); + . = ALIGN(8); _efixed = .; /* End of text section */ } > rom @@ -70,36 +70,36 @@ MEMORY { } > rom PROVIDE_HIDDEN (__exidx_end = .); - . = ALIGN(4); + . = ALIGN(8); _etext = .; .relocate : AT (_etext) { - . = ALIGN(4); + . = ALIGN(8); _srelocate = .; *(.ramfunc .ramfunc.*); *(.data .data.*); - . = ALIGN(4); + . = ALIGN(8); _erelocate = .; } > ram /* .bss section which is used for uninitialized data */ .bss (NOLOAD) : { - . = ALIGN(4); + . = ALIGN(8); _sbss = . ; _szero = .; *(.bss .bss.*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); _ebss = . ; _ezero = .; } > ram .heap (NOLOAD) : { - . = ALIGN(4); + . = ALIGN(8); __end__ = . ; . = ORIGIN(ram) + LENGTH(ram) - STACK_SIZE; } > ram @@ -114,5 +114,5 @@ MEMORY { _estack = .; } > ram - . = ALIGN(4); + . = ALIGN(8); } diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAML21J18A/device/TOOLCHAIN_ARM_MICRO/SAML21J18A.sct b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAML21J18A/device/TOOLCHAIN_ARM_MICRO/SAML21J18A.sct index eb079ebbc0..f1f0bb48f6 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAML21J18A/device/TOOLCHAIN_ARM_MICRO/SAML21J18A.sct +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAML21J18A/device/TOOLCHAIN_ARM_MICRO/SAML21J18A.sct @@ -18,8 +18,8 @@ LR_IROM1 0x00000000 0x40000 { ; } ; - [RAM] Vector table dynamic copy: 45 vectors * 4 bytes = (0xB4) - alignment - RW_IRAM1 (0x20000000+0xB4) (0x8000-0xB4) + [RAM] Vector table dynamic copy: 45 vectors * 4 bytes = (0xB4+0x4) 8-byte alignment + RW_IRAM1 (0x20000000+0xB8) (0x8000-0xB8) { ; RW data diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAML21J18A/device/TOOLCHAIN_ARM_STD/SAML21J18A.sct b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAML21J18A/device/TOOLCHAIN_ARM_STD/SAML21J18A.sct index d9fd77fbbf..86cae7a517 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAML21J18A/device/TOOLCHAIN_ARM_STD/SAML21J18A.sct +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAML21J18A/device/TOOLCHAIN_ARM_STD/SAML21J18A.sct @@ -10,8 +10,8 @@ LR_IROM1 0x00000000 0x40000 { ; load region size_region .ANY (+RO) } - ; [RAM] Vector table dynamic copy: 45 vectors * 4 bytes = (0xB4) - alignment - RW_IRAM1 (0x20000000+0xB4) (0x8000-0xB4) { ; RW data + ; [RAM] Vector table dynamic copy: 45 vectors * 4 bytes = (0xB4+0x4) 8-byte alignment + RW_IRAM1 (0x20000000+0xB8) (0x8000-0xB8) { ; RW data .ANY (+RW +ZI) } } diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAML21J18A/device/TOOLCHAIN_GCC_ARM/saml21j18a.ld b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAML21J18A/device/TOOLCHAIN_GCC_ARM/saml21j18a.ld index b8c2983cd6..21334d715a 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAML21J18A/device/TOOLCHAIN_GCC_ARM/saml21j18a.ld +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAML21J18A/device/TOOLCHAIN_GCC_ARM/saml21j18a.ld @@ -5,7 +5,7 @@ SEARCH_DIR(.) /* Memory Spaces Definitions */ MEMORY { rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 - ram (rwx) : ORIGIN = 0x20000000 + 0xB4, LENGTH = 0x00008000 - 0xB4 + ram (rwx) : ORIGIN = 0x20000000 + 0xB8, LENGTH = 0x00008000 - 0xB8 } /* The stack size used by the application. NOTE: you need to adjust according to your application. */ @@ -15,7 +15,7 @@ MEMORY { SECTIONS { .text : { - . = ALIGN(4); + . = ALIGN(8); _sfixed = .; KEEP(*(.vectors .vectors.*)) *(.text .text.* .gnu.linkonce.t.*) @@ -25,29 +25,29 @@ MEMORY { /* Support C constructors, and C destructors in both user code and the C library. This also provides support for C++ code. */ - . = ALIGN(4); + . = ALIGN(8); KEEP(*(.init)) - . = ALIGN(4); + . = ALIGN(8); __preinit_array_start = .; KEEP (*(.preinit_array)) __preinit_array_end = .; - . = ALIGN(4); + . = ALIGN(8); __init_array_start = .; KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) __init_array_end = .; - . = ALIGN(4); + . = ALIGN(8); KEEP (*crtbegin.o(.ctors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*crtend.o(.ctors)) - . = ALIGN(4); + . = ALIGN(8); KEEP(*(.fini)) - . = ALIGN(4); + . = ALIGN(8); __fini_array_start = .; KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) @@ -58,7 +58,7 @@ MEMORY { KEEP (*(SORT(.dtors.*))) KEEP (*crtend.o(.dtors)) - . = ALIGN(4); + . = ALIGN(8); _efixed = .; /* End of text section */ } > rom @@ -70,36 +70,36 @@ MEMORY { } > rom PROVIDE_HIDDEN (__exidx_end = .); - . = ALIGN(4); + . = ALIGN(8); _etext = .; .relocate : AT (_etext) { - . = ALIGN(4); + . = ALIGN(8); _srelocate = .; *(.ramfunc .ramfunc.*); *(.data .data.*); - . = ALIGN(4); + . = ALIGN(8); _erelocate = .; } > ram /* .bss section which is used for uninitialized data */ .bss (NOLOAD) : { - . = ALIGN(4); + . = ALIGN(8); _sbss = . ; _szero = .; *(.bss .bss.*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); _ebss = . ; _ezero = .; } > ram .heap (NOLOAD) : { - . = ALIGN(4); + . = ALIGN(8); __end__ = . ; . = ORIGIN(ram) + LENGTH(ram) - STACK_SIZE; } > ram @@ -114,5 +114,5 @@ MEMORY { _estack = .; } > ram - . = ALIGN(4); + . = ALIGN(8); } diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMR21G18A/device/TOOLCHAIN_GCC_ARM/samr21g18a.ld b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMR21G18A/device/TOOLCHAIN_GCC_ARM/samr21g18a.ld index 21479a889e..f060f236f6 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMR21G18A/device/TOOLCHAIN_GCC_ARM/samr21g18a.ld +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/TARGET_SAMR21G18A/device/TOOLCHAIN_GCC_ARM/samr21g18a.ld @@ -15,7 +15,7 @@ MEMORY { SECTIONS { .text : { - . = ALIGN(4); + . = ALIGN(8); _sfixed = .; KEEP(*(.vectors .vectors.*)) *(.text .text.* .gnu.linkonce.t.*) @@ -25,29 +25,29 @@ MEMORY { /* Support C constructors, and C destructors in both user code and the C library. This also provides support for C++ code. */ - . = ALIGN(4); + . = ALIGN(8); KEEP(*(.init)) - . = ALIGN(4); + . = ALIGN(8); __preinit_array_start = .; KEEP (*(.preinit_array)) __preinit_array_end = .; - . = ALIGN(4); + . = ALIGN(8); __init_array_start = .; KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) __init_array_end = .; - . = ALIGN(4); + . = ALIGN(8); KEEP (*crtbegin.o(.ctors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*crtend.o(.ctors)) - . = ALIGN(4); + . = ALIGN(8); KEEP(*(.fini)) - . = ALIGN(4); + . = ALIGN(8); __fini_array_start = .; KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) @@ -58,7 +58,7 @@ MEMORY { KEEP (*(SORT(.dtors.*))) KEEP (*crtend.o(.dtors)) - . = ALIGN(4); + . = ALIGN(8); _efixed = .; /* End of text section */ } > rom @@ -70,36 +70,36 @@ MEMORY { } > rom PROVIDE_HIDDEN (__exidx_end = .); - . = ALIGN(4); + . = ALIGN(8); _etext = .; .relocate : AT (_etext) { - . = ALIGN(4); + . = ALIGN(8); _srelocate = .; *(.ramfunc .ramfunc.*); *(.data .data.*); - . = ALIGN(4); + . = ALIGN(8); _erelocate = .; } > ram /* .bss section which is used for uninitialized data */ .bss (NOLOAD) : { - . = ALIGN(4); + . = ALIGN(8); _sbss = . ; _szero = .; *(.bss .bss.*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); _ebss = . ; _ezero = .; } > ram .heap (NOLOAD) : { - . = ALIGN(4); + . = ALIGN(8); __end__ = . ; . = ORIGIN(ram) + LENGTH(ram) - STACK_SIZE; } > ram @@ -114,5 +114,5 @@ MEMORY { _estack = .; } > ram - . = ALIGN(4); + . = ALIGN(8); } diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM4/TARGET_SAMG55J19/device/TOOLCHAIN_GCC_ARM/samg55j19.ld b/targets/TARGET_Atmel/TARGET_SAM_CortexM4/TARGET_SAMG55J19/device/TOOLCHAIN_GCC_ARM/samg55j19.ld index ff2da412b7..e3e802d714 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM4/TARGET_SAMG55J19/device/TOOLCHAIN_GCC_ARM/samg55j19.ld +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM4/TARGET_SAMG55J19/device/TOOLCHAIN_GCC_ARM/samg55j19.ld @@ -15,7 +15,7 @@ MEMORY { SECTIONS { .text : { - . = ALIGN(4); + . = ALIGN(8); _sfixed = .; KEEP(*(.vectors .vectors.*)) *(.text .text.* .gnu.linkonce.t.*) @@ -25,29 +25,29 @@ MEMORY { /* Support C constructors, and C destructors in both user code and the C library. This also provides support for C++ code. */ - . = ALIGN(4); + . = ALIGN(8); KEEP(*(.init)) - . = ALIGN(4); + . = ALIGN(8); __preinit_array_start = .; KEEP (*(.preinit_array)) __preinit_array_end = .; - . = ALIGN(4); + . = ALIGN(8); __init_array_start = .; KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) __init_array_end = .; - . = ALIGN(4); + . = ALIGN(8); KEEP (*crtbegin.o(.ctors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*crtend.o(.ctors)) - . = ALIGN(4); + . = ALIGN(8); KEEP(*(.fini)) - . = ALIGN(4); + . = ALIGN(8); __fini_array_start = .; KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) @@ -58,7 +58,7 @@ MEMORY { KEEP (*(SORT(.dtors.*))) KEEP (*crtend.o(.dtors)) - . = ALIGN(4); + . = ALIGN(8); _efixed = .; /* End of text section */ } > rom @@ -70,36 +70,36 @@ MEMORY { } > rom PROVIDE_HIDDEN (__exidx_end = .); - . = ALIGN(4); + . = ALIGN(8); _etext = .; .relocate : AT (_etext) { - . = ALIGN(4); + . = ALIGN(8); _srelocate = .; *(.ramfunc .ramfunc.*); *(.data .data.*); - . = ALIGN(4); + . = ALIGN(8); _erelocate = .; } > ram /* .bss section which is used for uninitialized data */ .bss (NOLOAD) : { - . = ALIGN(4); + . = ALIGN(8); _sbss = . ; _szero = .; *(.bss .bss.*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); _ebss = . ; _ezero = .; } > ram .heap (NOLOAD) : { - . = ALIGN(4); + . = ALIGN(8); __end__ = . ; . = ORIGIN(ram) + LENGTH(ram) - STACK_SIZE; } > ram @@ -114,5 +114,5 @@ MEMORY { _estack = .; } > ram - . = ALIGN(4); + . = ALIGN(8); } diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/PeripheralNames.h b/targets/TARGET_Cypress/TARGET_PSOC6/PeripheralNames.h new file mode 100644 index 0000000000..836df4692c --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/PeripheralNames.h @@ -0,0 +1,109 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#ifndef MBED_PERIPHERALNAMES_H +#define MBED_PERIPHERALNAMES_H + +#include "cmsis.h" +#include "PinNames.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + UART_0 = (int)SCB0_BASE, + UART_1 = (int)SCB1_BASE, + UART_2 = (int)SCB2_BASE, + UART_3 = (int)SCB3_BASE, + UART_4 = (int)SCB4_BASE, + UART_5 = (int)SCB5_BASE, + UART_6 = (int)SCB6_BASE, + UART_7 = (int)SCB7_BASE, +} UARTName; + + +typedef enum { + SPI_0 = (int)SCB0_BASE, + SPI_1 = (int)SCB1_BASE, + SPI_2 = (int)SCB2_BASE, + SPI_3 = (int)SCB3_BASE, + SPI_4 = (int)SCB4_BASE, + SPI_5 = (int)SCB5_BASE, + SPI_6 = (int)SCB6_BASE, + SPI_7 = (int)SCB7_BASE, +} SPIName; + +typedef enum { + I2C_0 = (int)SCB0_BASE, + I2C_1 = (int)SCB1_BASE, + I2C_2 = (int)SCB2_BASE, + I2C_3 = (int)SCB3_BASE, + I2C_4 = (int)SCB4_BASE, + I2C_5 = (int)SCB5_BASE, + I2C_6 = (int)SCB6_BASE, + I2C_7 = (int)SCB7_BASE, +} I2CName; + +typedef enum { + PWM_32b_0 = TCPWM0_BASE, + PWM_32b_1, + PWM_32b_2, + PWM_32b_3, + PWM_32b_4, + PWM_32b_5, + PWM_32b_6, + PWM_32b_7, + PWM_16b_0 = TCPWM1_BASE, + PWM_16b_1, + PWM_16b_2, + PWM_16b_3, + PWM_16b_4, + PWM_16b_5, + PWM_16b_6, + PWM_16b_7, + PWM_16b_8, + PWM_16b_9, + PWM_16b_10, + PWM_16b_11, + PWM_16b_12, + PWM_16b_13, + PWM_16b_14, + PWM_16b_15, + PWM_16b_16, + PWM_16b_17, + PWM_16b_18, + PWM_16b_19, + PWM_16b_20, + PWM_16b_21, + PWM_16b_22, + PWM_16b_23, +} PWMName; + +typedef enum { + ADC_0 = (int)SAR_BASE, +} ADCName; + +typedef enum { + DAC_0 = (int)CTDAC0_BASE, +} DACName; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/PeripheralPins.h b/targets/TARGET_Cypress/TARGET_PSOC6/PeripheralPins.h new file mode 100644 index 0000000000..07237af517 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/PeripheralPins.h @@ -0,0 +1,62 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#ifndef MBED_PERIPHERALPINS_H +#define MBED_PERIPHERALPINS_H + +#include "pinmap.h" +#include "PeripheralNames.h" + + +// //*** I2C *** +#if DEVICE_I2C +extern const PinMap PinMap_I2C_SDA[]; +extern const PinMap PinMap_I2C_SCL[]; +#endif + +//*** PWM *** +#if DEVICE_PWMOUT +extern const PinMap PinMap_PWM_OUT[]; +#endif + +//*** SERIAL *** +#ifdef DEVICE_SERIAL +extern const PinMap PinMap_UART_TX[]; +extern const PinMap PinMap_UART_RX[]; +extern const PinMap PinMap_UART_RTS[]; +extern const PinMap PinMap_UART_CTS[]; +#endif + +//*** SPI *** +#ifdef DEVICE_SPI +extern const PinMap PinMap_SPI_MOSI[]; +extern const PinMap PinMap_SPI_MISO[]; +extern const PinMap PinMap_SPI_SCLK[]; +extern const PinMap PinMap_SPI_SSEL[]; +#endif + +//*** ADC *** +#ifdef DEVICE_ANALOGIN +extern const PinMap PinMap_ADC[]; +#endif + +//*** DAC *** +#ifdef DEVICE_ANALOGOUT +extern const PinMap PinMap_DAC[]; +#endif + +#endif diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/PinNamesTypes.h b/targets/TARGET_Cypress/TARGET_PSOC6/PinNamesTypes.h new file mode 100644 index 0000000000..559e3cc2c3 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/PinNamesTypes.h @@ -0,0 +1,84 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#ifndef MBED_PINNAMESTYPES_H +#define MBED_PINNAMESTYPES_H + +#include "cmsis.h" + +typedef enum { + PIN_INPUT = 0, + PIN_OUTPUT +} PinDirection; + +typedef enum { + PullNone = 0, + PullUp = 1, + PullDown = 2, + OpenDrainDriveLow = 3, + OpenDrainDriveHigh = 4, + OpenDrain = OpenDrainDriveLow, + PushPull = 5, + AnalogMode = 6, + PullDefault = PullNone +} PinMode; + +typedef struct { + en_hsiom_sel_t hsiom : 8; + en_clk_dst_t clock : 8; + PinMode mode : 4; + PinDirection dir : 1; +} PinFunction; + +// Encode pin function. +// Output function +#define CY_PIN_FUNCTION(hsiom, clock, mode, dir) (int)(((dir) << 20) | ((mode) << 16) | ((clock) << 8) | (hsiom)) +#define CY_PIN_OUT_FUNCTION(hsiom, clock) CY_PIN_FUNCTION(hsiom, clock, PushPull, PIN_OUTPUT) +#define CY_PIN_OD_FUNCTION(hsiom, clock) CY_PIN_FUNCTION(hsiom, clock, OpenDrain, PIN_OUTPUT) +#define CY_PIN_IN_FUNCTION(hsiom, clock) CY_PIN_FUNCTION(hsiom, clock, PullDefault, PIN_INPUT) +#define CY_PIN_PULLUP_FUNCTION(hsiom, clock) CY_PIN_FUNCTION(hsiom, clock, PullUp, PIN_INPUT) +#define CY_PIN_ANALOG_FUNCTION(clock) CY_PIN_FUNCTION(HSIOM_SEL_GPIO, clock, AnalogMode, 0) + +// Create unique name to force 32-bit PWM usage on a pin. +#define CY_PIN_FORCE_PWM_32(pin) ((uint32_t)(pin) + 0x8000) + +static inline en_hsiom_sel_t CY_PIN_HSIOM(int function) +{ + return (en_hsiom_sel_t)(function & 0xFF); +} + +static inline en_clk_dst_t CY_PIN_CLOCK(int function) +{ + return (en_clk_dst_t)((function >> 8) & 0xFF); +} + +static inline PinMode CY_PIN_MODE(int function) +{ + return (PinMode)((function >> 16) & 0x0F); +} + +static inline PinDirection CY_PIN_DIRECTION(int function) +{ + return (PinDirection)((function >> 20) & 1); +} + +static inline int CY_PERIPHERAL_BASE(int peripheral) +{ + return peripheral & 0xffff0000; +} + +#endif diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/PortNames.h b/targets/TARGET_Cypress/TARGET_PSOC6/PortNames.h new file mode 100644 index 0000000000..e30039df79 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/PortNames.h @@ -0,0 +1,47 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#ifndef MBED_PORTNAMES_H +#define MBED_PORTNAMES_H + +#ifdef __cplusplus +extern "C" { +#endif + +// Port[15-0] +typedef enum { + Port0 = 0x0, + Port1 = 0x1, + Port2 = 0x2, + Port3 = 0x3, + Port4 = 0x4, + Port5 = 0x5, + Port6 = 0x6, + Port7 = 0x7, + Port8 = 0x8, + Port9 = 0x9, + Port10 = 0xA, + Port11 = 0xB, + Port12 = 0xC, + Port13 = 0xD, + Port14 = 0xE +} PortName; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/PeripheralPins.c b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/PeripheralPins.c new file mode 100644 index 0000000000..0de9f5e995 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/PeripheralPins.c @@ -0,0 +1,364 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#include "PeripheralNames.h" +#include "PeripheralPins.h" +#include "pinmap.h" + +#if DEVICE_SERIAL +//*** SERIAL *** +const PinMap PinMap_UART_RX[] = { + {P0_2, UART_0, CY_PIN_IN_FUNCTION( P0_2_SCB0_UART_RX, PCLK_SCB0_CLOCK)}, + {P1_0, UART_7, CY_PIN_IN_FUNCTION( P1_0_SCB7_UART_RX, PCLK_SCB7_CLOCK)}, + {P5_0, UART_5, CY_PIN_IN_FUNCTION( P5_0_SCB5_UART_RX, PCLK_SCB5_CLOCK)}, + {P6_0, UART_3, CY_PIN_IN_FUNCTION( P6_0_SCB3_UART_RX, PCLK_SCB3_CLOCK)}, + {P6_4, UART_6, CY_PIN_IN_FUNCTION( P6_4_SCB6_UART_RX, PCLK_SCB6_CLOCK)}, + {P7_0, UART_4, CY_PIN_IN_FUNCTION( P7_0_SCB4_UART_RX, PCLK_SCB4_CLOCK)}, + {P8_0, UART_4, CY_PIN_IN_FUNCTION( P8_0_SCB4_UART_RX, PCLK_SCB4_CLOCK)}, + {P9_0, UART_2, CY_PIN_IN_FUNCTION( P9_0_SCB2_UART_RX, PCLK_SCB2_CLOCK)}, + {P10_0, UART_1, CY_PIN_IN_FUNCTION( P10_0_SCB1_UART_RX, PCLK_SCB1_CLOCK)}, + {P11_0, UART_5, CY_PIN_IN_FUNCTION( P11_0_SCB5_UART_RX, PCLK_SCB5_CLOCK)}, + {P12_0, UART_6, CY_PIN_IN_FUNCTION( P12_0_SCB6_UART_RX, PCLK_SCB6_CLOCK)}, + {P13_0, UART_6, CY_PIN_IN_FUNCTION( P13_0_SCB6_UART_RX, PCLK_SCB6_CLOCK)}, + {NC, NC, 0} +}; +const PinMap PinMap_UART_TX[] = { + {P0_3, UART_0, CY_PIN_OUT_FUNCTION( P0_3_SCB0_UART_TX, PCLK_SCB0_CLOCK)}, + {P1_1, UART_7, CY_PIN_OUT_FUNCTION( P1_1_SCB7_UART_TX, PCLK_SCB7_CLOCK)}, + {P5_1, UART_5, CY_PIN_OUT_FUNCTION( P5_1_SCB5_UART_TX, PCLK_SCB5_CLOCK)}, + {P6_1, UART_3, CY_PIN_OUT_FUNCTION( P6_1_SCB3_UART_TX, PCLK_SCB3_CLOCK)}, + {P6_5, UART_6, CY_PIN_OUT_FUNCTION( P6_5_SCB6_UART_TX, PCLK_SCB6_CLOCK)}, + {P7_1, UART_4, CY_PIN_OUT_FUNCTION( P7_1_SCB4_UART_TX, PCLK_SCB4_CLOCK)}, + {P8_1, UART_4, CY_PIN_OUT_FUNCTION( P8_1_SCB4_UART_TX, PCLK_SCB4_CLOCK)}, + {P9_1, UART_2, CY_PIN_OUT_FUNCTION( P9_1_SCB2_UART_TX, PCLK_SCB2_CLOCK)}, + {P10_1, UART_1, CY_PIN_OUT_FUNCTION( P10_1_SCB1_UART_TX, PCLK_SCB1_CLOCK)}, + {P11_1, UART_5, CY_PIN_OUT_FUNCTION( P11_1_SCB5_UART_TX, PCLK_SCB5_CLOCK)}, + {P12_1, UART_6, CY_PIN_OUT_FUNCTION( P12_1_SCB6_UART_TX, PCLK_SCB6_CLOCK)}, + {P13_1, UART_6, CY_PIN_OUT_FUNCTION( P13_1_SCB6_UART_TX, PCLK_SCB6_CLOCK)}, + {NC, NC, 0} +}; +const PinMap PinMap_UART_RTS[] = { + {P0_4, UART_0, CY_PIN_OUT_FUNCTION( P0_4_SCB0_UART_RTS, PCLK_SCB0_CLOCK)}, + {P1_2, UART_7, CY_PIN_OUT_FUNCTION( P1_2_SCB7_UART_RTS, PCLK_SCB7_CLOCK)}, + {P5_2, UART_5, CY_PIN_OUT_FUNCTION( P5_2_SCB5_UART_RTS, PCLK_SCB5_CLOCK)}, + {P6_2, UART_3, CY_PIN_OUT_FUNCTION( P6_2_SCB3_UART_RTS, PCLK_SCB3_CLOCK)}, + {P6_6, UART_6, CY_PIN_OUT_FUNCTION( P6_6_SCB6_UART_RTS, PCLK_SCB6_CLOCK)}, + {P7_2, UART_4, CY_PIN_OUT_FUNCTION( P7_2_SCB4_UART_RTS, PCLK_SCB4_CLOCK)}, + {P8_2, UART_4, CY_PIN_OUT_FUNCTION( P8_2_SCB4_UART_RTS, PCLK_SCB4_CLOCK)}, + {P9_2, UART_2, CY_PIN_OUT_FUNCTION( P9_2_SCB2_UART_RTS, PCLK_SCB2_CLOCK)}, + {P10_2, UART_1, CY_PIN_OUT_FUNCTION( P10_2_SCB1_UART_RTS, PCLK_SCB1_CLOCK)}, + {P11_2, UART_5, CY_PIN_OUT_FUNCTION( P11_2_SCB5_UART_RTS, PCLK_SCB5_CLOCK)}, + {P12_2, UART_6, CY_PIN_OUT_FUNCTION( P12_2_SCB6_UART_RTS, PCLK_SCB6_CLOCK)}, + {NC, NC, 0} +}; +const PinMap PinMap_UART_CTS[] = { + {P0_5, UART_0, CY_PIN_IN_FUNCTION( P0_5_SCB0_UART_CTS, PCLK_SCB0_CLOCK)}, + {P1_3, UART_7, CY_PIN_IN_FUNCTION( P1_3_SCB7_UART_CTS, PCLK_SCB7_CLOCK)}, + {P5_3, UART_5, CY_PIN_IN_FUNCTION( P5_3_SCB5_UART_CTS, PCLK_SCB5_CLOCK)}, + {P6_3, UART_3, CY_PIN_IN_FUNCTION( P6_3_SCB3_UART_CTS, PCLK_SCB3_CLOCK)}, + {P6_7, UART_6, CY_PIN_IN_FUNCTION( P6_7_SCB6_UART_CTS, PCLK_SCB6_CLOCK)}, + {P7_3, UART_4, CY_PIN_IN_FUNCTION( P7_3_SCB4_UART_CTS, PCLK_SCB4_CLOCK)}, + {P8_3, UART_4, CY_PIN_IN_FUNCTION( P8_3_SCB4_UART_CTS, PCLK_SCB4_CLOCK)}, + {P9_3, UART_2, CY_PIN_IN_FUNCTION( P9_3_SCB2_UART_CTS, PCLK_SCB2_CLOCK)}, + {P10_3, UART_1, CY_PIN_IN_FUNCTION( P10_3_SCB1_UART_CTS, PCLK_SCB1_CLOCK)}, + {P11_3, UART_5, CY_PIN_IN_FUNCTION( P11_3_SCB5_UART_CTS, PCLK_SCB5_CLOCK)}, + {P12_3, UART_6, CY_PIN_IN_FUNCTION( P12_3_SCB6_UART_CTS, PCLK_SCB6_CLOCK)}, + {NC, NC, 0} +}; +#endif // DEVICE_SERIAL + + +#if DEVICE_I2C +//*** I2C *** +const PinMap PinMap_I2C_SCL[] = { + {P0_2, I2C_0, CY_PIN_OD_FUNCTION( P0_2_SCB0_I2C_SCL, PCLK_SCB0_CLOCK)}, + {P1_0, I2C_7, CY_PIN_OD_FUNCTION( P1_0_SCB7_I2C_SCL, PCLK_SCB7_CLOCK)}, + {P5_0, I2C_5, CY_PIN_OD_FUNCTION( P5_0_SCB5_I2C_SCL, PCLK_SCB5_CLOCK)}, + {P6_0, I2C_3, CY_PIN_OD_FUNCTION( P6_0_SCB3_I2C_SCL, PCLK_SCB3_CLOCK)}, + {P6_4, I2C_6, CY_PIN_OD_FUNCTION( P6_4_SCB6_I2C_SCL, PCLK_SCB6_CLOCK)}, + {P7_0, I2C_4, CY_PIN_OD_FUNCTION( P7_0_SCB4_I2C_SCL, PCLK_SCB4_CLOCK)}, + {P8_0, I2C_4, CY_PIN_OD_FUNCTION( P8_0_SCB4_I2C_SCL, PCLK_SCB4_CLOCK)}, + {P9_0, I2C_2, CY_PIN_OD_FUNCTION( P9_0_SCB2_I2C_SCL, PCLK_SCB2_CLOCK)}, + {P10_0, I2C_1, CY_PIN_OD_FUNCTION( P10_0_SCB1_I2C_SCL, PCLK_SCB1_CLOCK)}, + {P11_0, I2C_5, CY_PIN_OD_FUNCTION( P11_0_SCB5_I2C_SCL, PCLK_SCB5_CLOCK)}, + {P12_0, I2C_6, CY_PIN_OD_FUNCTION( P12_0_SCB6_I2C_SCL, PCLK_SCB6_CLOCK)}, + {P13_0, I2C_6, CY_PIN_OD_FUNCTION( P13_0_SCB6_I2C_SCL, PCLK_SCB6_CLOCK)}, + {NC, NC, 0} +}; +const PinMap PinMap_I2C_SDA[] = { + {P0_3, I2C_0, CY_PIN_OD_FUNCTION( P0_3_SCB0_I2C_SDA, PCLK_SCB0_CLOCK)}, + {P1_1, I2C_7, CY_PIN_OD_FUNCTION( P1_1_SCB7_I2C_SDA, PCLK_SCB7_CLOCK)}, + {P5_1, I2C_5, CY_PIN_OD_FUNCTION( P5_1_SCB5_I2C_SDA, PCLK_SCB5_CLOCK)}, + {P6_1, I2C_3, CY_PIN_OD_FUNCTION( P6_1_SCB3_I2C_SDA, PCLK_SCB3_CLOCK)}, + {P6_5, I2C_6, CY_PIN_OD_FUNCTION( P6_5_SCB6_I2C_SDA, PCLK_SCB6_CLOCK)}, + {P7_1, I2C_4, CY_PIN_OD_FUNCTION( P7_1_SCB4_I2C_SDA, PCLK_SCB4_CLOCK)}, + {P8_1, I2C_4, CY_PIN_OD_FUNCTION( P8_1_SCB4_I2C_SDA, PCLK_SCB4_CLOCK)}, + {P9_1, I2C_2, CY_PIN_OD_FUNCTION( P9_1_SCB2_I2C_SDA, PCLK_SCB2_CLOCK)}, + {P10_1, I2C_1, CY_PIN_OD_FUNCTION( P10_1_SCB1_I2C_SDA, PCLK_SCB1_CLOCK)}, + {P11_1, I2C_5, CY_PIN_OD_FUNCTION( P11_1_SCB5_I2C_SDA, PCLK_SCB5_CLOCK)}, + {P12_1, I2C_6, CY_PIN_OD_FUNCTION( P12_1_SCB6_I2C_SDA, PCLK_SCB6_CLOCK)}, + {P13_1, I2C_6, CY_PIN_OD_FUNCTION( P13_1_SCB6_I2C_SDA, PCLK_SCB6_CLOCK)}, + {NC, NC, 0} +}; +#endif // DEVICE_I2C + +#if DEVICE_SPI +//*** SPI *** +const PinMap PinMap_SPI_MOSI[] = { + {P0_2, SPI_0, CY_PIN_OUT_FUNCTION( P0_2_SCB0_SPI_MOSI, PCLK_SCB0_CLOCK)}, + {P1_0, SPI_7, CY_PIN_OUT_FUNCTION( P1_0_SCB7_SPI_MOSI, PCLK_SCB7_CLOCK)}, + {P5_0, SPI_5, CY_PIN_OUT_FUNCTION( P5_0_SCB5_SPI_MOSI, PCLK_SCB5_CLOCK)}, + {P6_0, SPI_3, CY_PIN_OUT_FUNCTION( P6_0_SCB3_SPI_MOSI, PCLK_SCB3_CLOCK)}, + {P6_4, SPI_6, CY_PIN_OUT_FUNCTION( P6_4_SCB6_SPI_MOSI, PCLK_SCB6_CLOCK)}, + {P7_0, SPI_4, CY_PIN_OUT_FUNCTION( P7_0_SCB4_SPI_MOSI, PCLK_SCB4_CLOCK)}, + {P8_0, SPI_4, CY_PIN_OUT_FUNCTION( P8_0_SCB4_SPI_MOSI, PCLK_SCB4_CLOCK)}, + {P9_0, SPI_2, CY_PIN_OUT_FUNCTION( P9_0_SCB2_SPI_MOSI, PCLK_SCB2_CLOCK)}, + {P10_0, SPI_1, CY_PIN_OUT_FUNCTION( P10_0_SCB1_SPI_MOSI, PCLK_SCB1_CLOCK)}, + {P11_0, SPI_5, CY_PIN_OUT_FUNCTION( P11_0_SCB5_SPI_MOSI, PCLK_SCB5_CLOCK)}, + {P12_0, SPI_6, CY_PIN_OUT_FUNCTION( P12_0_SCB6_SPI_MOSI, PCLK_SCB6_CLOCK)}, + {P13_0, SPI_6, CY_PIN_OUT_FUNCTION( P13_0_SCB6_SPI_MOSI, PCLK_SCB6_CLOCK)}, + {NC, NC, 0} +}; +const PinMap PinMap_SPI_MISO[] = { + {P0_3, SPI_0, CY_PIN_IN_FUNCTION( P0_3_SCB0_SPI_MISO, PCLK_SCB0_CLOCK)}, + {P1_1, SPI_7, CY_PIN_IN_FUNCTION( P1_1_SCB7_SPI_MISO, PCLK_SCB7_CLOCK)}, + {P5_1, SPI_5, CY_PIN_IN_FUNCTION( P5_1_SCB5_SPI_MISO, PCLK_SCB5_CLOCK)}, + {P6_1, SPI_3, CY_PIN_IN_FUNCTION( P6_1_SCB3_SPI_MISO, PCLK_SCB3_CLOCK)}, + {P6_5, SPI_6, CY_PIN_IN_FUNCTION( P6_5_SCB6_SPI_MISO, PCLK_SCB6_CLOCK)}, + {P7_1, SPI_4, CY_PIN_IN_FUNCTION( P7_1_SCB4_SPI_MISO, PCLK_SCB4_CLOCK)}, + {P8_1, SPI_4, CY_PIN_IN_FUNCTION( P8_1_SCB4_SPI_MISO, PCLK_SCB4_CLOCK)}, + {P9_1, SPI_2, CY_PIN_IN_FUNCTION( P9_1_SCB2_SPI_MISO, PCLK_SCB2_CLOCK)}, + {P10_1, SPI_1, CY_PIN_IN_FUNCTION( P10_1_SCB1_SPI_MISO, PCLK_SCB1_CLOCK)}, + {P11_1, SPI_5, CY_PIN_IN_FUNCTION( P11_1_SCB5_SPI_MISO, PCLK_SCB5_CLOCK)}, + {P12_1, SPI_6, CY_PIN_IN_FUNCTION( P12_1_SCB6_SPI_MISO, PCLK_SCB6_CLOCK)}, + {P13_1, SPI_6, CY_PIN_IN_FUNCTION( P13_1_SCB6_SPI_MISO, PCLK_SCB6_CLOCK)}, + {NC, NC, 0} +}; +const PinMap PinMap_SPI_SCLK[] = { + {P0_4, SPI_0, CY_PIN_OUT_FUNCTION( P0_4_SCB0_SPI_CLK, PCLK_SCB0_CLOCK)}, + {P1_2, SPI_7, CY_PIN_OUT_FUNCTION( P1_2_SCB7_SPI_CLK, PCLK_SCB7_CLOCK)}, + {P5_2, SPI_5, CY_PIN_OUT_FUNCTION( P5_2_SCB5_SPI_CLK, PCLK_SCB5_CLOCK)}, + {P6_2, SPI_3, CY_PIN_OUT_FUNCTION( P6_2_SCB3_SPI_CLK, PCLK_SCB3_CLOCK)}, + {P6_6, SPI_6, CY_PIN_OUT_FUNCTION( P6_6_SCB6_SPI_CLK, PCLK_SCB6_CLOCK)}, + {P7_2, SPI_4, CY_PIN_OUT_FUNCTION( P7_2_SCB4_SPI_CLK, PCLK_SCB4_CLOCK)}, + + {P8_2, SPI_4, CY_PIN_OUT_FUNCTION( P8_2_SCB4_SPI_CLK, PCLK_SCB4_CLOCK)}, + {P9_2, SPI_2, CY_PIN_OUT_FUNCTION( P9_2_SCB2_SPI_CLK, PCLK_SCB2_CLOCK)}, + {P10_2, SPI_1, CY_PIN_OUT_FUNCTION( P10_2_SCB1_SPI_CLK, PCLK_SCB1_CLOCK)}, + {P11_2, SPI_5, CY_PIN_OUT_FUNCTION( P11_2_SCB5_SPI_CLK, PCLK_SCB5_CLOCK)}, + {P12_2, SPI_6, CY_PIN_OUT_FUNCTION( P12_2_SCB6_SPI_CLK, PCLK_SCB6_CLOCK)}, + {NC, NC, 0} +}; +const PinMap PinMap_SPI_SSEL[] = { + {P0_5, SPI_0, CY_PIN_OUT_FUNCTION( P0_5_SCB0_SPI_SELECT0, PCLK_SCB0_CLOCK)}, + {P1_3, SPI_7, CY_PIN_OUT_FUNCTION( P1_3_SCB7_SPI_SELECT0, PCLK_SCB7_CLOCK)}, + {P5_3, SPI_5, CY_PIN_OUT_FUNCTION( P5_3_SCB5_SPI_SELECT0, PCLK_SCB5_CLOCK)}, + {P6_3, SPI_3, CY_PIN_OUT_FUNCTION( P6_3_SCB3_SPI_SELECT0, PCLK_SCB3_CLOCK)}, + {P6_7, SPI_6, CY_PIN_OUT_FUNCTION( P6_7_SCB6_SPI_SELECT0, PCLK_SCB6_CLOCK)}, + {P7_3, SPI_4, CY_PIN_OUT_FUNCTION( P7_3_SCB4_SPI_SELECT0, PCLK_SCB4_CLOCK)}, + {P8_3, SPI_4, CY_PIN_OUT_FUNCTION( P8_3_SCB4_SPI_SELECT0, PCLK_SCB4_CLOCK)}, + {P9_3, SPI_2, CY_PIN_OUT_FUNCTION( P9_3_SCB2_SPI_SELECT0, PCLK_SCB2_CLOCK)}, + {P10_3, SPI_1, CY_PIN_OUT_FUNCTION( P10_3_SCB1_SPI_SELECT0, PCLK_SCB1_CLOCK)}, + {P11_3, SPI_5, CY_PIN_OUT_FUNCTION( P11_3_SCB5_SPI_SELECT0, PCLK_SCB5_CLOCK)}, + {P12_3, SPI_6, CY_PIN_OUT_FUNCTION( P12_3_SCB6_SPI_SELECT0, PCLK_SCB6_CLOCK)}, + {NC, NC, 0} +}; +#endif // DEVICE_SPI + +#if DEVICE_PWMOUT +//*** PWM *** +const PinMap PinMap_PWM_OUT[] = { + // 16-bit PWM outputs + {P0_0, PWM_16b_0, CY_PIN_OUT_FUNCTION(P0_0_TCPWM1_LINE0, PCLK_TCPWM1_CLOCKS0)}, + {P0_2, PWM_16b_1, CY_PIN_OUT_FUNCTION(P0_2_TCPWM1_LINE1, PCLK_TCPWM1_CLOCKS1)}, + {P0_4, PWM_16b_2, CY_PIN_OUT_FUNCTION(P0_4_TCPWM1_LINE2, PCLK_TCPWM1_CLOCKS2)}, + {P1_0, PWM_16b_3, CY_PIN_OUT_FUNCTION(P1_0_TCPWM1_LINE3, PCLK_TCPWM1_CLOCKS3)}, + {P1_2, PWM_16b_12, CY_PIN_OUT_FUNCTION(P1_2_TCPWM1_LINE12, PCLK_TCPWM1_CLOCKS12)}, + {P1_4, PWM_16b_13, CY_PIN_OUT_FUNCTION(P1_4_TCPWM1_LINE13, PCLK_TCPWM1_CLOCKS13)}, + {P5_0, PWM_16b_4, CY_PIN_OUT_FUNCTION(P5_0_TCPWM1_LINE4, PCLK_TCPWM1_CLOCKS4)}, + {P5_2, PWM_16b_5, CY_PIN_OUT_FUNCTION(P5_2_TCPWM1_LINE5, PCLK_TCPWM1_CLOCKS5)}, + {P5_4, PWM_16b_6, CY_PIN_OUT_FUNCTION(P5_4_TCPWM1_LINE6, PCLK_TCPWM1_CLOCKS6)}, + {P5_6, PWM_16b_7, CY_PIN_OUT_FUNCTION(P5_6_TCPWM1_LINE7, PCLK_TCPWM1_CLOCKS7)}, + {P6_0, PWM_16b_8, CY_PIN_OUT_FUNCTION(P6_0_TCPWM1_LINE8, PCLK_TCPWM1_CLOCKS8)}, + {P6_2, PWM_16b_9, CY_PIN_OUT_FUNCTION(P6_2_TCPWM1_LINE9, PCLK_TCPWM1_CLOCKS9)}, + {P6_4, PWM_16b_10, CY_PIN_OUT_FUNCTION(P6_4_TCPWM1_LINE10, PCLK_TCPWM1_CLOCKS10)}, + {P6_6, PWM_16b_11, CY_PIN_OUT_FUNCTION(P6_6_TCPWM1_LINE11, PCLK_TCPWM1_CLOCKS11)}, + {P7_0, PWM_16b_12, CY_PIN_OUT_FUNCTION(P7_0_TCPWM1_LINE12, PCLK_TCPWM1_CLOCKS12)}, + {P7_2, PWM_16b_13, CY_PIN_OUT_FUNCTION(P7_2_TCPWM1_LINE13, PCLK_TCPWM1_CLOCKS13)}, + {P7_4, PWM_16b_14, CY_PIN_OUT_FUNCTION(P7_4_TCPWM1_LINE14, PCLK_TCPWM1_CLOCKS14)}, + {P7_6, PWM_16b_15, CY_PIN_OUT_FUNCTION(P7_6_TCPWM1_LINE15, PCLK_TCPWM1_CLOCKS15)}, + {P8_0, PWM_16b_16, CY_PIN_OUT_FUNCTION(P8_0_TCPWM1_LINE16, PCLK_TCPWM1_CLOCKS16)}, + {P8_2, PWM_16b_17, CY_PIN_OUT_FUNCTION(P8_2_TCPWM1_LINE17, PCLK_TCPWM1_CLOCKS17)}, + {P8_4, PWM_16b_18, CY_PIN_OUT_FUNCTION(P8_4_TCPWM1_LINE18, PCLK_TCPWM1_CLOCKS18)}, + {P8_6, PWM_16b_19, CY_PIN_OUT_FUNCTION(P8_6_TCPWM1_LINE19, PCLK_TCPWM1_CLOCKS19)}, + {P9_0, PWM_16b_20, CY_PIN_OUT_FUNCTION(P9_0_TCPWM1_LINE20, PCLK_TCPWM1_CLOCKS20)}, + {P9_2, PWM_16b_21, CY_PIN_OUT_FUNCTION(P9_2_TCPWM1_LINE21, PCLK_TCPWM1_CLOCKS21)}, + {P9_4, PWM_16b_0, CY_PIN_OUT_FUNCTION(P9_4_TCPWM1_LINE0, PCLK_TCPWM1_CLOCKS0)}, + {P9_6, PWM_16b_1, CY_PIN_OUT_FUNCTION(P9_6_TCPWM1_LINE1, PCLK_TCPWM1_CLOCKS1)}, + {P10_0, PWM_16b_22, CY_PIN_OUT_FUNCTION(P10_0_TCPWM1_LINE22, PCLK_TCPWM1_CLOCKS22)}, + {P10_2, PWM_16b_23, CY_PIN_OUT_FUNCTION(P10_2_TCPWM1_LINE23, PCLK_TCPWM1_CLOCKS23)}, + {P10_4, PWM_16b_0, CY_PIN_OUT_FUNCTION(P10_4_TCPWM1_LINE0, PCLK_TCPWM1_CLOCKS0)}, + {P10_6, PWM_16b_2, CY_PIN_OUT_FUNCTION(P10_6_TCPWM1_LINE2, PCLK_TCPWM1_CLOCKS2)}, + {P11_0, PWM_16b_1, CY_PIN_OUT_FUNCTION(P11_0_TCPWM1_LINE1, PCLK_TCPWM1_CLOCKS1)}, + {P11_2, PWM_16b_2, CY_PIN_OUT_FUNCTION(P11_2_TCPWM1_LINE2, PCLK_TCPWM1_CLOCKS2)}, + {P11_4, PWM_16b_3, CY_PIN_OUT_FUNCTION(P11_4_TCPWM1_LINE3, PCLK_TCPWM1_CLOCKS3)}, + {P12_0, PWM_16b_4, CY_PIN_OUT_FUNCTION(P12_0_TCPWM1_LINE4, PCLK_TCPWM1_CLOCKS4)}, + {P12_2, PWM_16b_5, CY_PIN_OUT_FUNCTION(P12_2_TCPWM1_LINE5, PCLK_TCPWM1_CLOCKS5)}, + {P12_4, PWM_16b_6, CY_PIN_OUT_FUNCTION(P12_4_TCPWM1_LINE6, PCLK_TCPWM1_CLOCKS6)}, + {P12_6, PWM_16b_7, CY_PIN_OUT_FUNCTION(P12_6_TCPWM1_LINE7, PCLK_TCPWM1_CLOCKS7)}, + {P13_0, PWM_16b_8, CY_PIN_OUT_FUNCTION(P13_0_TCPWM1_LINE8, PCLK_TCPWM1_CLOCKS8)}, + {P13_6, PWM_16b_11, CY_PIN_OUT_FUNCTION(P13_6_TCPWM1_LINE11, PCLK_TCPWM1_CLOCKS11)}, + // 16-bit PWM inverted outputs + {P0_1, PWM_16b_0, CY_PIN_OUT_FUNCTION(P0_1_TCPWM1_LINE_COMPL0, PCLK_TCPWM1_CLOCKS0)}, + {P0_3, PWM_16b_1, CY_PIN_OUT_FUNCTION(P0_3_TCPWM1_LINE_COMPL1, PCLK_TCPWM1_CLOCKS1)}, + {P0_5, PWM_16b_2, CY_PIN_OUT_FUNCTION(P0_5_TCPWM1_LINE_COMPL2, PCLK_TCPWM1_CLOCKS2)}, + {P1_1, PWM_16b_3, CY_PIN_OUT_FUNCTION(P1_1_TCPWM1_LINE_COMPL3, PCLK_TCPWM1_CLOCKS3)}, + {P1_3, PWM_16b_12, CY_PIN_OUT_FUNCTION(P1_3_TCPWM1_LINE_COMPL12, PCLK_TCPWM1_CLOCKS12)}, + {P1_5, PWM_16b_14, CY_PIN_OUT_FUNCTION(P1_5_TCPWM1_LINE_COMPL14, PCLK_TCPWM1_CLOCKS14)}, + {P5_1, PWM_16b_4, CY_PIN_OUT_FUNCTION(P5_1_TCPWM1_LINE_COMPL4, PCLK_TCPWM1_CLOCKS4)}, + {P5_3, PWM_16b_5, CY_PIN_OUT_FUNCTION(P5_3_TCPWM1_LINE_COMPL5, PCLK_TCPWM1_CLOCKS5)}, + {P5_5, PWM_16b_6, CY_PIN_OUT_FUNCTION(P5_5_TCPWM1_LINE_COMPL6, PCLK_TCPWM1_CLOCKS6)}, + {P6_1, PWM_16b_8, CY_PIN_OUT_FUNCTION(P6_1_TCPWM1_LINE_COMPL8, PCLK_TCPWM1_CLOCKS8)}, + {P6_3, PWM_16b_9, CY_PIN_OUT_FUNCTION(P6_3_TCPWM1_LINE_COMPL9, PCLK_TCPWM1_CLOCKS9)}, + {P6_5, PWM_16b_10, CY_PIN_OUT_FUNCTION(P6_5_TCPWM1_LINE_COMPL10, PCLK_TCPWM1_CLOCKS10)}, + {P6_7, PWM_16b_11, CY_PIN_OUT_FUNCTION(P6_7_TCPWM1_LINE_COMPL11, PCLK_TCPWM1_CLOCKS11)}, + {P7_1, PWM_16b_12, CY_PIN_OUT_FUNCTION(P7_1_TCPWM1_LINE_COMPL12, PCLK_TCPWM1_CLOCKS12)}, + {P7_3, PWM_16b_13, CY_PIN_OUT_FUNCTION(P7_3_TCPWM1_LINE_COMPL13, PCLK_TCPWM1_CLOCKS13)}, + {P7_5, PWM_16b_14, CY_PIN_OUT_FUNCTION(P7_5_TCPWM1_LINE_COMPL14, PCLK_TCPWM1_CLOCKS14)}, + {P7_7, PWM_16b_15, CY_PIN_OUT_FUNCTION(P7_7_TCPWM1_LINE_COMPL15, PCLK_TCPWM1_CLOCKS15)}, + {P8_1, PWM_16b_16, CY_PIN_OUT_FUNCTION(P8_1_TCPWM1_LINE_COMPL16, PCLK_TCPWM1_CLOCKS16)}, + {P8_3, PWM_16b_17, CY_PIN_OUT_FUNCTION(P8_3_TCPWM1_LINE_COMPL17, PCLK_TCPWM1_CLOCKS17)}, + {P8_5, PWM_16b_18, CY_PIN_OUT_FUNCTION(P8_5_TCPWM1_LINE_COMPL18, PCLK_TCPWM1_CLOCKS18)}, + {P8_7, PWM_16b_19, CY_PIN_OUT_FUNCTION(P8_7_TCPWM1_LINE_COMPL19, PCLK_TCPWM1_CLOCKS19)}, + {P9_1, PWM_16b_20, CY_PIN_OUT_FUNCTION(P9_1_TCPWM1_LINE_COMPL20, PCLK_TCPWM1_CLOCKS20)}, + {P9_3, PWM_16b_21, CY_PIN_OUT_FUNCTION(P9_3_TCPWM1_LINE_COMPL21, PCLK_TCPWM1_CLOCKS21)}, + {P9_5, PWM_16b_0, CY_PIN_OUT_FUNCTION(P9_5_TCPWM1_LINE_COMPL0, PCLK_TCPWM1_CLOCKS0)}, + {P9_7, PWM_16b_1, CY_PIN_OUT_FUNCTION(P9_7_TCPWM1_LINE_COMPL1, PCLK_TCPWM1_CLOCKS1)}, + {P10_1, PWM_16b_22, CY_PIN_OUT_FUNCTION(P10_1_TCPWM1_LINE_COMPL22, PCLK_TCPWM1_CLOCKS22)}, + {P10_3, PWM_16b_23, CY_PIN_OUT_FUNCTION(P10_3_TCPWM1_LINE_COMPL23, PCLK_TCPWM1_CLOCKS23)}, + {P10_5, PWM_16b_0, CY_PIN_OUT_FUNCTION(P10_5_TCPWM1_LINE_COMPL0, PCLK_TCPWM1_CLOCKS0)}, + {P11_1, PWM_16b_1, CY_PIN_OUT_FUNCTION(P11_1_TCPWM1_LINE_COMPL1, PCLK_TCPWM1_CLOCKS1)}, + {P11_3, PWM_16b_2, CY_PIN_OUT_FUNCTION(P11_3_TCPWM1_LINE_COMPL2, PCLK_TCPWM1_CLOCKS2)}, + {P11_5, PWM_16b_3, CY_PIN_OUT_FUNCTION(P11_5_TCPWM1_LINE_COMPL3, PCLK_TCPWM1_CLOCKS3)}, + {P12_1, PWM_16b_4, CY_PIN_OUT_FUNCTION(P12_1_TCPWM1_LINE_COMPL4, PCLK_TCPWM1_CLOCKS4)}, + {P12_3, PWM_16b_5, CY_PIN_OUT_FUNCTION(P12_3_TCPWM1_LINE_COMPL5, PCLK_TCPWM1_CLOCKS5)}, + {P12_5, PWM_16b_6, CY_PIN_OUT_FUNCTION(P12_5_TCPWM1_LINE_COMPL6, PCLK_TCPWM1_CLOCKS6)}, + {P12_7, PWM_16b_7, CY_PIN_OUT_FUNCTION(P12_7_TCPWM1_LINE_COMPL7, PCLK_TCPWM1_CLOCKS7)}, + {P13_1, PWM_16b_8, CY_PIN_OUT_FUNCTION(P13_1_TCPWM1_LINE_COMPL8, PCLK_TCPWM1_CLOCKS8)}, + {P13_7, PWM_16b_11, CY_PIN_OUT_FUNCTION(P13_7_TCPWM1_LINE_COMPL11, PCLK_TCPWM1_CLOCKS11)}, + // 32-bit PWM outputs + {PWM32(P0_0), PWM_32b_0, CY_PIN_OUT_FUNCTION(P0_0_TCPWM0_LINE0, PCLK_TCPWM0_CLOCKS0)}, + {PWM32(P0_2), PWM_32b_1, CY_PIN_OUT_FUNCTION(P0_2_TCPWM0_LINE1, PCLK_TCPWM0_CLOCKS1)}, + {PWM32(P0_4), PWM_32b_2, CY_PIN_OUT_FUNCTION(P0_4_TCPWM0_LINE2, PCLK_TCPWM0_CLOCKS2)}, + {PWM32(P1_0), PWM_32b_3, CY_PIN_OUT_FUNCTION(P1_0_TCPWM0_LINE3, PCLK_TCPWM0_CLOCKS3)}, + {PWM32(P1_2), PWM_32b_4, CY_PIN_OUT_FUNCTION(P1_2_TCPWM0_LINE4, PCLK_TCPWM0_CLOCKS4)}, + {PWM32(P1_4), PWM_32b_5, CY_PIN_OUT_FUNCTION(P1_4_TCPWM0_LINE5, PCLK_TCPWM0_CLOCKS5)}, + {PWM32(P5_0), PWM_32b_4, CY_PIN_OUT_FUNCTION(P5_0_TCPWM0_LINE4, PCLK_TCPWM0_CLOCKS4)}, + {PWM32(P5_2), PWM_32b_5, CY_PIN_OUT_FUNCTION(P5_2_TCPWM0_LINE5, PCLK_TCPWM0_CLOCKS5)}, + {PWM32(P5_4), PWM_32b_6, CY_PIN_OUT_FUNCTION(P5_4_TCPWM0_LINE6, PCLK_TCPWM0_CLOCKS6)}, + {PWM32(P5_6), PWM_32b_7, CY_PIN_OUT_FUNCTION(P5_6_TCPWM0_LINE7, PCLK_TCPWM0_CLOCKS7)}, + {PWM32(P6_0), PWM_32b_0, CY_PIN_OUT_FUNCTION(P6_0_TCPWM0_LINE0, PCLK_TCPWM0_CLOCKS0)}, + {PWM32(P6_2), PWM_32b_1, CY_PIN_OUT_FUNCTION(P6_2_TCPWM0_LINE1, PCLK_TCPWM0_CLOCKS1)}, + {PWM32(P6_4), PWM_32b_2, CY_PIN_OUT_FUNCTION(P6_4_TCPWM0_LINE2, PCLK_TCPWM0_CLOCKS2)}, + {PWM32(P6_6), PWM_32b_3, CY_PIN_OUT_FUNCTION(P6_6_TCPWM0_LINE3, PCLK_TCPWM0_CLOCKS3)}, + {PWM32(P7_0), PWM_32b_4, CY_PIN_OUT_FUNCTION(P7_0_TCPWM0_LINE4, PCLK_TCPWM0_CLOCKS4)}, + {PWM32(P7_2), PWM_32b_5, CY_PIN_OUT_FUNCTION(P7_2_TCPWM0_LINE5, PCLK_TCPWM0_CLOCKS5)}, + {PWM32(P7_4), PWM_32b_6, CY_PIN_OUT_FUNCTION(P7_4_TCPWM0_LINE6, PCLK_TCPWM0_CLOCKS6)}, + {PWM32(P7_6), PWM_32b_7, CY_PIN_OUT_FUNCTION(P7_6_TCPWM0_LINE7, PCLK_TCPWM0_CLOCKS7)}, + {PWM32(P8_0), PWM_32b_0, CY_PIN_OUT_FUNCTION(P8_0_TCPWM0_LINE0, PCLK_TCPWM0_CLOCKS0)}, + {PWM32(P8_2), PWM_32b_1, CY_PIN_OUT_FUNCTION(P8_2_TCPWM0_LINE1, PCLK_TCPWM0_CLOCKS1)}, + {PWM32(P8_4), PWM_32b_2, CY_PIN_OUT_FUNCTION(P8_4_TCPWM0_LINE2, PCLK_TCPWM0_CLOCKS2)}, + {PWM32(P8_6), PWM_32b_3, CY_PIN_OUT_FUNCTION(P8_6_TCPWM0_LINE3, PCLK_TCPWM0_CLOCKS3)}, + {PWM32(P9_0), PWM_32b_4, CY_PIN_OUT_FUNCTION(P9_0_TCPWM0_LINE4, PCLK_TCPWM0_CLOCKS4)}, + {PWM32(P9_2), PWM_32b_5, CY_PIN_OUT_FUNCTION(P9_2_TCPWM0_LINE5, PCLK_TCPWM0_CLOCKS5)}, + {PWM32(P9_4), PWM_32b_7, CY_PIN_OUT_FUNCTION(P9_4_TCPWM0_LINE7, PCLK_TCPWM0_CLOCKS7)}, + {PWM32(P9_6), PWM_32b_0, CY_PIN_OUT_FUNCTION(P9_6_TCPWM0_LINE0, PCLK_TCPWM0_CLOCKS0)}, + {PWM32(P10_0), PWM_32b_6, CY_PIN_OUT_FUNCTION(P10_0_TCPWM0_LINE6, PCLK_TCPWM0_CLOCKS6)}, + {PWM32(P10_2), PWM_32b_7, CY_PIN_OUT_FUNCTION(P10_2_TCPWM0_LINE7, PCLK_TCPWM0_CLOCKS7)}, + {PWM32(P10_4), PWM_32b_0, CY_PIN_OUT_FUNCTION(P10_4_TCPWM0_LINE0, PCLK_TCPWM0_CLOCKS0)}, + {PWM32(P10_6), PWM_32b_1, CY_PIN_OUT_FUNCTION(P10_6_TCPWM0_LINE1, PCLK_TCPWM0_CLOCKS1)}, + {PWM32(P11_0), PWM_32b_1, CY_PIN_OUT_FUNCTION(P11_0_TCPWM0_LINE1, PCLK_TCPWM0_CLOCKS1)}, + {PWM32(P11_2), PWM_32b_2, CY_PIN_OUT_FUNCTION(P11_2_TCPWM0_LINE2, PCLK_TCPWM0_CLOCKS2)}, + {PWM32(P11_4), PWM_32b_3, CY_PIN_OUT_FUNCTION(P11_4_TCPWM0_LINE3, PCLK_TCPWM0_CLOCKS3)}, + {PWM32(P12_0), PWM_32b_4, CY_PIN_OUT_FUNCTION(P12_0_TCPWM0_LINE4, PCLK_TCPWM0_CLOCKS4)}, + {PWM32(P12_2), PWM_32b_5, CY_PIN_OUT_FUNCTION(P12_2_TCPWM0_LINE5, PCLK_TCPWM0_CLOCKS5)}, + {PWM32(P12_4), PWM_32b_6, CY_PIN_OUT_FUNCTION(P12_4_TCPWM0_LINE6, PCLK_TCPWM0_CLOCKS6)}, + {PWM32(P12_6), PWM_32b_7, CY_PIN_OUT_FUNCTION(P12_6_TCPWM0_LINE7, PCLK_TCPWM0_CLOCKS7)}, + {PWM32(P13_0), PWM_32b_0, CY_PIN_OUT_FUNCTION(P13_0_TCPWM0_LINE0, PCLK_TCPWM0_CLOCKS0)}, + {PWM32(P13_6), PWM_32b_3, CY_PIN_OUT_FUNCTION(P13_6_TCPWM0_LINE3, PCLK_TCPWM0_CLOCKS3)}, + // 32-bit PWM inverted outputs + {PWM32(P0_1), PWM_32b_0, CY_PIN_OUT_FUNCTION(P0_1_TCPWM0_LINE_COMPL0, PCLK_TCPWM0_CLOCKS0)}, + {PWM32(P0_3), PWM_32b_1, CY_PIN_OUT_FUNCTION(P0_3_TCPWM0_LINE_COMPL1, PCLK_TCPWM0_CLOCKS1)}, + {PWM32(P0_5), PWM_32b_2, CY_PIN_OUT_FUNCTION(P0_5_TCPWM0_LINE_COMPL2, PCLK_TCPWM0_CLOCKS2)}, + {PWM32(P1_1), PWM_32b_3, CY_PIN_OUT_FUNCTION(P1_1_TCPWM0_LINE_COMPL3, PCLK_TCPWM0_CLOCKS3)}, + {PWM32(P1_3), PWM_32b_4, CY_PIN_OUT_FUNCTION(P1_3_TCPWM0_LINE_COMPL4, PCLK_TCPWM0_CLOCKS4)}, + {PWM32(P1_5), PWM_32b_5, CY_PIN_OUT_FUNCTION(P1_5_TCPWM0_LINE_COMPL5, PCLK_TCPWM0_CLOCKS5)}, + {PWM32(P5_1), PWM_32b_4, CY_PIN_OUT_FUNCTION(P5_1_TCPWM0_LINE_COMPL4, PCLK_TCPWM0_CLOCKS4)}, + {PWM32(P5_3), PWM_32b_5, CY_PIN_OUT_FUNCTION(P5_3_TCPWM0_LINE_COMPL5, PCLK_TCPWM0_CLOCKS5)}, + {PWM32(P5_5), PWM_32b_6, CY_PIN_OUT_FUNCTION(P5_5_TCPWM0_LINE_COMPL6, PCLK_TCPWM0_CLOCKS6)}, + {PWM32(P6_1), PWM_32b_0, CY_PIN_OUT_FUNCTION(P6_1_TCPWM0_LINE_COMPL0, PCLK_TCPWM0_CLOCKS0)}, + {PWM32(P6_3), PWM_32b_1, CY_PIN_OUT_FUNCTION(P6_3_TCPWM0_LINE_COMPL1, PCLK_TCPWM0_CLOCKS1)}, + {PWM32(P6_5), PWM_32b_2, CY_PIN_OUT_FUNCTION(P6_5_TCPWM0_LINE_COMPL2, PCLK_TCPWM0_CLOCKS2)}, + {PWM32(P6_7), PWM_32b_3, CY_PIN_OUT_FUNCTION(P6_7_TCPWM0_LINE_COMPL3, PCLK_TCPWM0_CLOCKS3)}, + {PWM32(P7_1), PWM_32b_4, CY_PIN_OUT_FUNCTION(P7_1_TCPWM0_LINE_COMPL4, PCLK_TCPWM0_CLOCKS4)}, + {PWM32(P7_3), PWM_32b_5, CY_PIN_OUT_FUNCTION(P7_3_TCPWM0_LINE_COMPL5, PCLK_TCPWM0_CLOCKS5)}, + {PWM32(P7_5), PWM_32b_6, CY_PIN_OUT_FUNCTION(P7_5_TCPWM0_LINE_COMPL6, PCLK_TCPWM0_CLOCKS6)}, + {PWM32(P7_7), PWM_32b_7, CY_PIN_OUT_FUNCTION(P7_7_TCPWM0_LINE_COMPL7, PCLK_TCPWM0_CLOCKS7)}, + {PWM32(P8_1), PWM_32b_0, CY_PIN_OUT_FUNCTION(P8_1_TCPWM0_LINE_COMPL0, PCLK_TCPWM0_CLOCKS0)}, + {PWM32(P8_3), PWM_32b_1, CY_PIN_OUT_FUNCTION(P8_3_TCPWM0_LINE_COMPL1, PCLK_TCPWM0_CLOCKS1)}, + {PWM32(P8_5), PWM_32b_2, CY_PIN_OUT_FUNCTION(P8_5_TCPWM0_LINE_COMPL2, PCLK_TCPWM0_CLOCKS2)}, + {PWM32(P8_7), PWM_32b_3, CY_PIN_OUT_FUNCTION(P8_7_TCPWM0_LINE_COMPL3, PCLK_TCPWM0_CLOCKS3)}, + {PWM32(P9_1), PWM_32b_4, CY_PIN_OUT_FUNCTION(P9_1_TCPWM0_LINE_COMPL4, PCLK_TCPWM0_CLOCKS4)}, + {PWM32(P9_3), PWM_32b_5, CY_PIN_OUT_FUNCTION(P9_3_TCPWM0_LINE_COMPL5, PCLK_TCPWM0_CLOCKS5)}, + {PWM32(P9_5), PWM_32b_7, CY_PIN_OUT_FUNCTION(P9_5_TCPWM0_LINE_COMPL7, PCLK_TCPWM0_CLOCKS7)}, + {PWM32(P9_7), PWM_32b_0, CY_PIN_OUT_FUNCTION(P9_7_TCPWM0_LINE_COMPL0, PCLK_TCPWM0_CLOCKS0)}, + {PWM32(P10_1), PWM_32b_6, CY_PIN_OUT_FUNCTION(P10_1_TCPWM0_LINE_COMPL6, PCLK_TCPWM0_CLOCKS6)}, + {PWM32(P10_3), PWM_32b_7, CY_PIN_OUT_FUNCTION(P10_3_TCPWM0_LINE_COMPL7, PCLK_TCPWM0_CLOCKS7)}, + {PWM32(P10_5), PWM_32b_0, CY_PIN_OUT_FUNCTION(P10_5_TCPWM0_LINE_COMPL0, PCLK_TCPWM0_CLOCKS0)}, + {PWM32(P11_1), PWM_32b_1, CY_PIN_OUT_FUNCTION(P11_1_TCPWM0_LINE_COMPL1, PCLK_TCPWM0_CLOCKS1)}, + {PWM32(P11_3), PWM_32b_2, CY_PIN_OUT_FUNCTION(P11_3_TCPWM0_LINE_COMPL2, PCLK_TCPWM0_CLOCKS2)}, + {PWM32(P11_5), PWM_32b_3, CY_PIN_OUT_FUNCTION(P11_5_TCPWM0_LINE_COMPL3, PCLK_TCPWM0_CLOCKS3)}, + {PWM32(P12_1), PWM_32b_4, CY_PIN_OUT_FUNCTION(P12_1_TCPWM0_LINE_COMPL4, PCLK_TCPWM0_CLOCKS4)}, + {PWM32(P12_3), PWM_32b_5, CY_PIN_OUT_FUNCTION(P12_3_TCPWM0_LINE_COMPL5, PCLK_TCPWM0_CLOCKS5)}, + {PWM32(P12_5), PWM_32b_6, CY_PIN_OUT_FUNCTION(P12_5_TCPWM0_LINE_COMPL6, PCLK_TCPWM0_CLOCKS6)}, + {PWM32(P12_7), PWM_32b_7, CY_PIN_OUT_FUNCTION(P12_7_TCPWM0_LINE_COMPL7, PCLK_TCPWM0_CLOCKS7)}, + {PWM32(P13_1), PWM_32b_0, CY_PIN_OUT_FUNCTION(P13_1_TCPWM0_LINE_COMPL0, PCLK_TCPWM0_CLOCKS0)}, + {PWM32(P13_7), PWM_32b_3, CY_PIN_OUT_FUNCTION(P13_7_TCPWM0_LINE_COMPL3, PCLK_TCPWM0_CLOCKS3)}, + {NC, NC, 0} +}; +#endif // DEVICE_PWMOUT + +#if DEVICE_ANALOGIN +const PinMap PinMap_ADC[] = { + {P10_0, ADC_0, CY_PIN_ANALOG_FUNCTION(PCLK_PASS_CLOCK_SAR)}, + {P10_1, ADC_0, CY_PIN_ANALOG_FUNCTION(PCLK_PASS_CLOCK_SAR)}, + {P10_2, ADC_0, CY_PIN_ANALOG_FUNCTION(PCLK_PASS_CLOCK_SAR)}, + {P10_3, ADC_0, CY_PIN_ANALOG_FUNCTION(PCLK_PASS_CLOCK_SAR)}, + {P10_4, ADC_0, CY_PIN_ANALOG_FUNCTION(PCLK_PASS_CLOCK_SAR)}, + {P10_5, ADC_0, CY_PIN_ANALOG_FUNCTION(PCLK_PASS_CLOCK_SAR)}, + {P10_6, ADC_0, CY_PIN_ANALOG_FUNCTION(PCLK_PASS_CLOCK_SAR)}, + {P10_7, ADC_0, CY_PIN_ANALOG_FUNCTION(PCLK_PASS_CLOCK_SAR)}, + {NC, NC, 0} +}; +#endif // DEVICE_ANALOGIN + +#if DEVICE_ANALOGOUT +const PinMap PinMap_DAC[] = { + {P9_6, DAC_0, CY_PIN_ANALOG_FUNCTION(PCLK_PASS_CLOCK_CTDAC)}, + {NC, NC, 0} +}; +#endif // DEVICE_ANALOGIN diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/PDL_Version.txt b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/PDL_Version.txt new file mode 100644 index 0000000000..9cac515901 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/PDL_Version.txt @@ -0,0 +1,2 @@ +version 3.0.1 + diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/README.md b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/README.md new file mode 100644 index 0000000000..c1a197bfb5 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/README.md @@ -0,0 +1,5 @@ +README for Cypress Peripheral Driver Library +============================================ + +This folder tree contains parts (binary-only libraries and M0/M4 core specific files) of Cypress Peripheral Driver Library (PDL) necessary to support PSoC 6 MCUs. Library names have been changed (vs. standard PDL version) by prepending a "lib" prefix to fit Mbed OS build system conventions. +See [Cypress PDL page](http://www.cypress.com/documentation/software-and-drivers/peripheral-driver-library-pdl) for details. diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_ARM_STD/cy8c6xx7_cm0plus.sct b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_ARM_STD/cy8c6xx7_cm0plus.sct new file mode 100644 index 0000000000..603c453ebd --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_ARM_STD/cy8c6xx7_cm0plus.sct @@ -0,0 +1,207 @@ +#! armcc -E +; The first line specifies a preprocessor command that the linker invokes +; to pass a scatter file through a C preprocessor. + +;******************************************************************************* +;* \file cy8c6xx7_cm0plus.scat +;* \version 2.10 +;* +;* Linker file for the ARMCC. +;* +;* The main purpose of the linker script is to describe how the sections in the +;* input files should be mapped into the output file, and to control the memory +;* layout of the output file. +;* +;* \note The entry point location is fixed and starts at 0x10000000. The valid +;* application image should be placed there. +;* +;* \note The linker files included with the PDL template projects must be +;* generic and handle all common use cases. Your project may not use every +;* section defined in the linker files. In that case you may see the warnings +;* during the build process: L6314W (no section matches pattern) and/or L6329W +;* (pattern only matches removed unused sections). In your project, you can +;* suppress the warning by passing the "--diag_suppress=L6314W,L6329W" option to +;* the linker, simply comment out or remove the relevant code in the linker +;* file. +;* +;******************************************************************************* +;* \copyright +;* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +;* SPDX-License-Identifier: Apache-2.0 +;******************************************************************************/ + +; The defines below describe the location and size of blocks of memory in the target. +; Use these defines to specify the memory regions available for allocation. + +; The following defines control RAM and flash memory allocation for the CM0+ core. +; You can change the memory allocation by editing the RAM and Flash defines. +; Your changes must be aligned with the corresponding defines for the CM4 core in 'xx_cm4_dual.scat', +; where 'xx' is the device group; for example, 'cy8c6xx7_cm4_dual.scat'. +; RAM +; RAM +#define RAM_START 0x08000000 +#define RAM_SIZE 0x00010000 +; Flash +; Flash +#define FLASH_START 0x10000000 +#define FLASH_SIZE 0x00078000 + +; The following defines describe a 32K flash region used for EEPROM emulation. +; This region can also be used as the general purpose flash. +; You can assign sections to this memory region for only one of the cores. +; Note some middleware (e.g. BLE, Emulated EEPROM) can place their data into this memory region. +; Therefore, repurposing this memory region will prevent such middleware from operation. +#define EM_EEPROM_START 0x14000000 +#define EM_EEPROM_SIZE 0x8000 + +; The following defines describe device specific memory regions and must not be changed. +; Supervisory flash: User data +#define SFLASH_USER_DATA_START 0x16000800 +#define SFLASH_USER_DATA_SIZE 0x00000800 + +; Supervisory flash: Normal Access Restrictions (NAR) +#define SFLASH_NAR_START 0x16001A00 +#define SFLASH_NAR_SIZE 0x00000200 + +; Supervisory flash: Public Key +#define SFLASH_PUBLIC_KEY_START 0x16005A00 +#define SFLASH_PUBLIC_KEY_SIZE 0x00000C00 + +; Supervisory flash: Table of Content # 2 +#define SFLASH_TOC_2_START 0x16007C00 +#define SFLASH_TOC_2_SIZE 0x00000200 + +; Supervisory flash: Table of Content # 2 Copy +#define SFLASH_RTOC_2_START 0x16007E00 +#define SFLASH_RTOC_2_SIZE 0x00000200 + +; External memory +#define XIP_START 0x18000000 +#define XIP_SIZE 0x08000000 + +; eFuse +#define EFUSE_START 0x90700000 +#define EFUSE_SIZE 0x100000 + + +LR_IROM1 FLASH_START FLASH_SIZE +{ + .cy_app_header +0 + { + * (.cy_app_header) + } + + ER_FLASH_VECTORS +0 + { + * (RESET, +FIRST) + } + + ER_FLASH_CODE +0 FIXED + { + * (InRoot$$Sections) + * (+RO) + } + + ER_RAM_VECTORS RAM_START UNINIT + { + * (RESET_RAM, +FIRST) + } + + RW_RAM_DATA +0 + { + * (.cy_ramfunc) + .ANY (+RW, +ZI) + } + + ; Place variables in the section that should not be initialized during the + ; device startup. + RW_IRAM1 +0 UNINIT + { + * (.noinit) + } +} + + +; Emulated EEPROM Flash area +LR_EM_EEPROM EM_EEPROM_START EM_EEPROM_SIZE +{ + .cy_em_eeprom +0 + { + * (.cy_em_eeprom) + } +} + +; Supervisory flash: User data +LR_SFLASH_USER_DATA SFLASH_USER_DATA_START SFLASH_USER_DATA_SIZE +{ + .cy_sflash_user_data +0 + { + * (.cy_sflash_user_data) + } +} + +; Supervisory flash: Normal Access Restrictions (NAR) +LR_SFLASH_NAR SFLASH_NAR_START SFLASH_NAR_SIZE +{ + .cy_sflash_nar +0 + { + * (.cy_sflash_nar) + } +} + +; Supervisory flash: Public Key +LR_SFLASH_PUBLIC_KEY SFLASH_PUBLIC_KEY_START SFLASH_PUBLIC_KEY_SIZE +{ + .cy_sflash_public_key +0 + { + * (.cy_sflash_public_key) + } +} + +; Supervisory flash: Table of Content # 2 +LR_SFLASH_TOC_2 SFLASH_TOC_2_START SFLASH_TOC_2_SIZE +{ + .cy_toc_part2 +0 + { + * (.cy_toc_part2) + } +} + +; Supervisory flash: Table of Content # 2 Copy +LR_SFLASH_RTOC_2 SFLASH_RTOC_2_START SFLASH_RTOC_2_SIZE +{ + .cy_rtoc_part2 +0 + { + * (.cy_rtoc_part2) + } +} + + +; Places the code in the Execute in Place (XIP) section. See the smif driver documentation for details. +LR_EROM XIP_START XIP_SIZE +{ + .cy_xip +0 + { + * (.cy_xip) + } +} + + +; eFuse +LR_EFUSE EFUSE_START EFUSE_SIZE +{ + .cy_efuse +0 + { + * (.cy_efuse) + } +} + + +; The section is used for additional metadata (silicon revision, Silicon/JTAG ID, etc.) storage. +CYMETA 0x90500000 +{ + .cymeta +0 { * (.cymeta) } +} + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_ARM_STD/startup_psoc63_cm0plus.S b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_ARM_STD/startup_psoc63_cm0plus.S new file mode 100644 index 0000000000..53ac4e4a1d --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_ARM_STD/startup_psoc63_cm0plus.S @@ -0,0 +1,279 @@ +;/**************************************************************************//** +; * @file startup_psoc63_cm0plus.s +; * @brief CMSIS Core Device Startup File for +; * ARMCM0plus Device Series +; * @version V5.00 +; * @date 02. March 2016 +; ******************************************************************************/ +;/* +; * Copyright (c) 2009-2016 ARM Limited. All rights reserved. +; * +; * 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 +; * +; * 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. +; */ + +;/* +;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------ +;*/ + +__initial_sp EQU 0x08010000 + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + + DCD 0x0000000D ; NMI Handler located at ROM code + DCD HardFault_Handler ; Hard Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + + ; External interrupts Description + DCD NvicMux0_IRQHandler ; CM0 + NVIC Mux input 0 + DCD NvicMux1_IRQHandler ; CM0 + NVIC Mux input 1 + DCD NvicMux2_IRQHandler ; CM0 + NVIC Mux input 2 + DCD NvicMux3_IRQHandler ; CM0 + NVIC Mux input 3 + DCD NvicMux4_IRQHandler ; CM0 + NVIC Mux input 4 + DCD NvicMux5_IRQHandler ; CM0 + NVIC Mux input 5 + DCD NvicMux6_IRQHandler ; CM0 + NVIC Mux input 6 + DCD NvicMux7_IRQHandler ; CM0 + NVIC Mux input 7 + DCD NvicMux8_IRQHandler ; CM0 + NVIC Mux input 8 + DCD NvicMux9_IRQHandler ; CM0 + NVIC Mux input 9 + DCD NvicMux10_IRQHandler ; CM0 + NVIC Mux input 10 + DCD NvicMux11_IRQHandler ; CM0 + NVIC Mux input 11 + DCD NvicMux12_IRQHandler ; CM0 + NVIC Mux input 12 + DCD NvicMux13_IRQHandler ; CM0 + NVIC Mux input 13 + DCD NvicMux14_IRQHandler ; CM0 + NVIC Mux input 14 + DCD NvicMux15_IRQHandler ; CM0 + NVIC Mux input 15 + DCD NvicMux16_IRQHandler ; CM0 + NVIC Mux input 16 + DCD NvicMux17_IRQHandler ; CM0 + NVIC Mux input 17 + DCD NvicMux18_IRQHandler ; CM0 + NVIC Mux input 18 + DCD NvicMux19_IRQHandler ; CM0 + NVIC Mux input 19 + DCD NvicMux20_IRQHandler ; CM0 + NVIC Mux input 20 + DCD NvicMux21_IRQHandler ; CM0 + NVIC Mux input 21 + DCD NvicMux22_IRQHandler ; CM0 + NVIC Mux input 22 + DCD NvicMux23_IRQHandler ; CM0 + NVIC Mux input 23 + DCD NvicMux24_IRQHandler ; CM0 + NVIC Mux input 24 + DCD NvicMux25_IRQHandler ; CM0 + NVIC Mux input 25 + DCD NvicMux26_IRQHandler ; CM0 + NVIC Mux input 26 + DCD NvicMux27_IRQHandler ; CM0 + NVIC Mux input 27 + DCD NvicMux28_IRQHandler ; CM0 + NVIC Mux input 28 + DCD NvicMux29_IRQHandler ; CM0 + NVIC Mux input 29 + DCD NvicMux30_IRQHandler ; CM0 + NVIC Mux input 30 + DCD NvicMux31_IRQHandler ; CM0 + NVIC Mux input 31 + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + EXPORT __ramVectors + AREA RESET_RAM, READWRITE, NOINIT +__ramVectors SPACE __Vectors_Size + + + AREA |.text|, CODE, READONLY + + +; Saves and disables the interrupts +Cy_SaveIRQ PROC + EXPORT Cy_SaveIRQ + MRS r0, PRIMASK + CPSID I + BX LR + ENDP + + +; Restores the interrupts +Cy_RestoreIRQ PROC + EXPORT Cy_RestoreIRQ + MSR PRIMASK, r0 + BX LR + ENDP + + +; Weak function for startup customization +Cy_OnResetUser PROC + EXPORT Cy_OnResetUser [WEAK] + BX LR + ENDP + +; Reset Handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + + ; Define strong function for startup customization + BL Cy_OnResetUser + + ; Copy vectors from ROM to RAM + LDR r1, =__Vectors + LDR r0, =__ramVectors + LDR r2, =__Vectors_Size +Vectors_Copy + LDR r3, [r1] + STR r3, [r0] + ADDS r0, r0, #4 + ADDS r1, r1, #4 + SUBS r2, r2, #1 + CMP r2, #0 + BNE Vectors_Copy + + ; Update Vector Table Offset Register. */ + LDR r0, =__ramVectors + LDR r1, =0xE000ED08 + STR r0, [r1] + dsb 0xF + + LDR R0, =__main + BLX R0 + + ; Should never get here + B . + + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP + +Cy_SysLib_FaultHandler PROC + EXPORT Cy_SysLib_FaultHandler [WEAK] + B . + ENDP + +HardFault_Handler PROC + EXPORT HardFault_Handler [WEAK] + movs r0, #4 + mov r1, LR + tst r0, r1 + beq L_MSP + mrs r0, PSP + bl L_API_call +L_MSP + mrs r0, MSP +L_API_call + bl Cy_SysLib_FaultHandler + ENDP + +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + EXPORT Default_Handler [WEAK] + EXPORT NvicMux0_IRQHandler [WEAK] + EXPORT NvicMux1_IRQHandler [WEAK] + EXPORT NvicMux2_IRQHandler [WEAK] + EXPORT NvicMux3_IRQHandler [WEAK] + EXPORT NvicMux4_IRQHandler [WEAK] + EXPORT NvicMux5_IRQHandler [WEAK] + EXPORT NvicMux6_IRQHandler [WEAK] + EXPORT NvicMux7_IRQHandler [WEAK] + EXPORT NvicMux8_IRQHandler [WEAK] + EXPORT NvicMux9_IRQHandler [WEAK] + EXPORT NvicMux10_IRQHandler [WEAK] + EXPORT NvicMux11_IRQHandler [WEAK] + EXPORT NvicMux12_IRQHandler [WEAK] + EXPORT NvicMux13_IRQHandler [WEAK] + EXPORT NvicMux14_IRQHandler [WEAK] + EXPORT NvicMux15_IRQHandler [WEAK] + EXPORT NvicMux16_IRQHandler [WEAK] + EXPORT NvicMux17_IRQHandler [WEAK] + EXPORT NvicMux18_IRQHandler [WEAK] + EXPORT NvicMux19_IRQHandler [WEAK] + EXPORT NvicMux20_IRQHandler [WEAK] + EXPORT NvicMux21_IRQHandler [WEAK] + EXPORT NvicMux22_IRQHandler [WEAK] + EXPORT NvicMux23_IRQHandler [WEAK] + EXPORT NvicMux24_IRQHandler [WEAK] + EXPORT NvicMux25_IRQHandler [WEAK] + EXPORT NvicMux26_IRQHandler [WEAK] + EXPORT NvicMux27_IRQHandler [WEAK] + EXPORT NvicMux28_IRQHandler [WEAK] + EXPORT NvicMux29_IRQHandler [WEAK] + EXPORT NvicMux30_IRQHandler [WEAK] + EXPORT NvicMux31_IRQHandler [WEAK] + +NvicMux0_IRQHandler +NvicMux1_IRQHandler +NvicMux2_IRQHandler +NvicMux3_IRQHandler +NvicMux4_IRQHandler +NvicMux5_IRQHandler +NvicMux6_IRQHandler +NvicMux7_IRQHandler +NvicMux8_IRQHandler +NvicMux9_IRQHandler +NvicMux10_IRQHandler +NvicMux11_IRQHandler +NvicMux12_IRQHandler +NvicMux13_IRQHandler +NvicMux14_IRQHandler +NvicMux15_IRQHandler +NvicMux16_IRQHandler +NvicMux17_IRQHandler +NvicMux18_IRQHandler +NvicMux19_IRQHandler +NvicMux20_IRQHandler +NvicMux21_IRQHandler +NvicMux22_IRQHandler +NvicMux23_IRQHandler +NvicMux24_IRQHandler +NvicMux25_IRQHandler +NvicMux26_IRQHandler +NvicMux27_IRQHandler +NvicMux28_IRQHandler +NvicMux29_IRQHandler +NvicMux30_IRQHandler +NvicMux31_IRQHandler + + B . + ENDP + + ALIGN + + END + + +; [] END OF FILE diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_GCC_ARM/cy8c6xx7_cm0plus.ld b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_GCC_ARM/cy8c6xx7_cm0plus.ld new file mode 100644 index 0000000000..d7a54e4af2 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_GCC_ARM/cy8c6xx7_cm0plus.ld @@ -0,0 +1,393 @@ +/***************************************************************************//** +* \file cy8c6xx7_cm0plus.ld +* \version 2.10 +* +* Linker file for the GNU C compiler. +* +* The main purpose of the linker script is to describe how the sections in the +* input files should be mapped into the output file, and to control the memory +* layout of the output file. +* +* \note The entry point location is fixed and starts at 0x10000000. The valid +* application image should be placed there. +* +* \note The linker files included with the PDL template projects must be generic +* and handle all common use cases. Your project may not use every section +* defined in the linker files. In that case you may see warnings during the +* build process. In your project, you can simply comment out or remove the +* relevant code in the linker file. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) +ENTRY(Reset_Handler) + + +/* Force symbol to be entered in the output file as an undefined symbol. Doing +* this may, for example, trigger linking of additional modules from standard +* libraries. You may list several symbols for each EXTERN, and you may use +* EXTERN multiple times. This command has the same effect as the -u command-line +* option. +*/ +EXTERN(Reset_Handler) + +/* The MEMORY section below describes the location and size of blocks of memory in the target. +* Use this section to specify the memory regions available for allocation. +*/ +MEMORY +{ + /* The ram and flash regions control RAM and flash memory allocation for the CM0+ core. + * You can change the memory allocation by editing the 'ram' and 'flash' regions. + * Your changes must be aligned with the corresponding memory regions for the CM4 core in 'xx_cm4_dual.ld', + * where 'xx' is the device group; for example, 'cy8c6xx7_cm4_dual.ld'. + */ + ram (rwx) : ORIGIN = 0x08000000, LENGTH = 0x10000 + flash (rx) : ORIGIN = 0x10000000, LENGTH = 0x78000 + + /* This is a 32K flash region used for EEPROM emulation. This region can also be used as the general purpose flash. + * You can assign sections to this memory region for only one of the cores. + * Note some middleware (e.g. BLE, Emulated EEPROM) can place their data into this memory region. + * Therefore, repurposing this memory region will prevent such middleware from operation. + */ + em_eeprom (rx) : ORIGIN = 0x14000000, LENGTH = 0x8000 /* 32 KB */ + + /* The following regions define device specific memory regions and must not be changed. */ + sflash_user_data (rx) : ORIGIN = 0x16000800, LENGTH = 0x800 /* Supervisory flash: User data */ + sflash_nar (rx) : ORIGIN = 0x16001A00, LENGTH = 0x200 /* Supervisory flash: Normal Access Restrictions (NAR) */ + sflash_public_key (rx) : ORIGIN = 0x16005A00, LENGTH = 0xC00 /* Supervisory flash: Public Key */ + sflash_toc_2 (rx) : ORIGIN = 0x16007C00, LENGTH = 0x200 /* Supervisory flash: Table of Content # 2 */ + sflash_rtoc_2 (rx) : ORIGIN = 0x16007E00, LENGTH = 0x200 /* Supervisory flash: Table of Content # 2 Copy */ + xip (rx) : ORIGIN = 0x18000000, LENGTH = 0x8000000 /* 128 MB */ + efuse (r) : ORIGIN = 0x90700000, LENGTH = 0x100000 /* 1 MB */ +} + +/* Library configurations */ +GROUP(libgcc.a libc.a libm.a libnosys.a) + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + * __Vectors_End + * __Vectors_Size + */ + + +SECTIONS +{ + .cy_app_header : + { + KEEP(*(.cy_app_header)) + } > flash + + .text : + { + . = ALIGN(4); + __Vectors = . ; + KEEP(*(.vectors)) + . = ALIGN(4); + __Vectors_End = .; + __Vectors_Size = __Vectors_End - __Vectors; + __end__ = .; + + . = ALIGN(4); + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + /* Read-only code (constants). */ + *(.rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + + KEEP(*(.eh_frame*)) + + /* To copy multiple ROM to RAM sections, + * uncomment copy table section and, + * define __STARTUP_COPY_MULTIPLE in startup_psoc63_cm4.S */ + . = ALIGN(4); + __copy_table_start__ = .; + + /* Copy interrupt vectors from flash to RAM */ + LONG (__Vectors) /* From */ + LONG (__ram_vectors_start__) /* To */ + LONG (__Vectors_End - __Vectors) /* Size */ + + /* Copy data section to RAM */ + LONG (__etext) /* From */ + LONG (__data_start__) /* To */ + LONG (__data_end__ - __data_start__) /* Size */ + + __copy_table_end__ = .; + + /* To clear multiple BSS sections, + * uncomment zero table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_psoc63_cm4.S */ + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + __zero_table_end__ = .; + + } > flash + + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > flash + + __exidx_start = .; + + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > flash + __exidx_end = .; + + __etext = . ; + + + .ramVectors (NOLOAD) : ALIGN(8) + { + __ram_vectors_start__ = .; + KEEP(*(.ram_vectors)) + __ram_vectors_end__ = .; + } > ram + + + .data __ram_vectors_end__ : AT (__etext) + { + __data_start__ = .; + + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + + KEEP(*(.cy_ramfunc*)) + . = ALIGN(4); + + __data_end__ = .; + + } > ram + + + /* Place variables in the section that should not be initialized during the + * device startup. + */ + .noinit (NOLOAD) : ALIGN(8) + { + KEEP(*(.noinit)) + } > ram + + + /* The uninitialized global or static variables are placed in this section. + * + * The NOLOAD attribute tells linker that .bss section does not consume + * any space in the image. The NOLOAD attribute changes the .bss type to + * NOBITS, and that makes linker to A) not allocate section in memory, and + * A) put information to clear the section with all zeros during application + * loading. + * + * Without the NOLOAD attribute, the .bss section might get PROGBITS type. + * This makes linker to A) allocate zeroed section in memory, and B) copy + * this section to RAM during application loading. + */ + .bss (NOLOAD): + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > ram + + + .heap (NOLOAD): + { + __HeapBase = .; + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + __HeapLimit = .; + } > ram + + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > ram + + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(ram) + LENGTH(ram); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + + + /* Emulated EEPROM Flash area */ + .cy_em_eeprom : + { + KEEP(*(.cy_em_eeprom)) + } > em_eeprom + + + /* Supervisory Flash: User data */ + .cy_sflash_user_data : + { + KEEP(*(.cy_sflash_user_data)) + } > sflash_user_data + + + /* Supervisory Flash: Normal Access Restrictions (NAR) */ + .cy_sflash_nar : + { + KEEP(*(.cy_sflash_nar)) + } > sflash_nar + + + /* Supervisory Flash: Public Key */ + .cy_sflash_public_key : + { + KEEP(*(.cy_sflash_public_key)) + } > sflash_public_key + + + /* Supervisory Flash: Table of Content # 2 */ + .cy_toc_part2 : + { + KEEP(*(.cy_toc_part2)) + } > sflash_toc_2 + + + /* Supervisory Flash: Table of Content # 2 Copy */ + .cy_rtoc_part2 : + { + KEEP(*(.cy_rtoc_part2)) + } > sflash_rtoc_2 + + + /* Places the code in the Execute in Place (XIP) section. See the smif driver + * documentation for details. + */ + .cy_xip : + { + KEEP(*(.cy_xip)) + } > xip + + + /* eFuse */ + .cy_efuse : + { + KEEP(*(.cy_efuse)) + } > efuse + + + /* These sections are used for additional metadata (silicon revision, + * Silicon/JTAG ID, etc.) storage. + */ + .cymeta 0x90500000 : { KEEP(*(.cymeta)) } :NONE +} + + +/* The following symbols used by the cymcuelftool. */ +/* Flash */ +__cy_memory_0_start = 0x10000000; +__cy_memory_0_length = 0x00100000; +__cy_memory_0_row_size = 0x200; + +/* Emulated EEPROM Flash area */ +__cy_memory_1_start = 0x14000000; +__cy_memory_1_length = 0x8000; +__cy_memory_1_row_size = 0x200; + +/* Supervisory Flash */ +__cy_memory_2_start = 0x16000000; +__cy_memory_2_length = 0x8000; +__cy_memory_2_row_size = 0x200; + +/* XIP */ +__cy_memory_3_start = 0x18000000; +__cy_memory_3_length = 0x08000000; +__cy_memory_3_row_size = 0x200; + +/* eFuse */ +__cy_memory_4_start = 0x90700000; +__cy_memory_4_length = 0x100000; +__cy_memory_4_row_size = 1; + +/* EOF */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_GCC_ARM/startup_psoc63_cm0plus.S b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_GCC_ARM/startup_psoc63_cm0plus.S new file mode 100644 index 0000000000..00178a1aad --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_GCC_ARM/startup_psoc63_cm0plus.S @@ -0,0 +1,415 @@ +/**************************************************************************//** + * @file startup_psoc63_cm0plus.s + * @brief CMSIS Core Device Startup File for + * ARMCM0plus Device Series + * @version V5.00 + * @date 02. March 2016 + ******************************************************************************/ +/* + * Copyright (c) 2009-2016 ARM Limited. All rights reserved. + * + * 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 + * + * 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. + */ + + /* Address of the NMI handler */ + #define CY_NMI_HANLDER_ADDR 0x0000000D + + /* The CPU VTOR register */ + #define CY_CPU_VTOR_ADDR 0xE000ED08 + + /* Copy flash vectors and data section to RAM */ + #define __STARTUP_COPY_MULTIPLE + + /* Clear single BSS section */ + #define __STARTUP_CLEAR_BSS + + .syntax unified + .arch armv6-m + + .section .stack + .align 3 +#ifdef __STACK_SIZE + .equ Stack_Size, __STACK_SIZE +#else + .equ Stack_Size, 0x00001000 +#endif + .globl __StackTop + .globl __StackLimit +__StackLimit: + .space Stack_Size + .size __StackLimit, . - __StackLimit +__StackTop: + .size __StackTop, . - __StackTop + + .section .heap + .align 3 +#ifdef __HEAP_SIZE + .equ Heap_Size, __HEAP_SIZE +#else + .equ Heap_Size, 0x00000400 +#endif + .globl __HeapBase + .globl __HeapLimit +__HeapBase: + .if Heap_Size + .space Heap_Size + .endif + .size __HeapBase, . - __HeapBase +__HeapLimit: + .size __HeapLimit, . - __HeapLimit + + .section .vectors + .align 2 + .globl __Vectors +__Vectors: + .long __StackTop /* Top of Stack */ + .long Reset_Handler /* Reset Handler */ + .long CY_NMI_HANLDER_ADDR /* NMI Handler */ + .long HardFault_Handler /* Hard Fault Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long SVC_Handler /* SVCall Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long PendSV_Handler /* PendSV Handler */ + .long SysTick_Handler /* SysTick Handler */ + + /* External interrupts Description */ + .long NvicMux0_IRQHandler /* CM0 + NVIC Mux input 0 */ + .long NvicMux1_IRQHandler /* CM0 + NVIC Mux input 1 */ + .long NvicMux2_IRQHandler /* CM0 + NVIC Mux input 2 */ + .long NvicMux3_IRQHandler /* CM0 + NVIC Mux input 3 */ + .long NvicMux4_IRQHandler /* CM0 + NVIC Mux input 4 */ + .long NvicMux5_IRQHandler /* CM0 + NVIC Mux input 5 */ + .long NvicMux6_IRQHandler /* CM0 + NVIC Mux input 6 */ + .long NvicMux7_IRQHandler /* CM0 + NVIC Mux input 7 */ + .long NvicMux8_IRQHandler /* CM0 + NVIC Mux input 8 */ + .long NvicMux9_IRQHandler /* CM0 + NVIC Mux input 9 */ + .long NvicMux10_IRQHandler /* CM0 + NVIC Mux input 10 */ + .long NvicMux11_IRQHandler /* CM0 + NVIC Mux input 11 */ + .long NvicMux12_IRQHandler /* CM0 + NVIC Mux input 12 */ + .long NvicMux13_IRQHandler /* CM0 + NVIC Mux input 13 */ + .long NvicMux14_IRQHandler /* CM0 + NVIC Mux input 14 */ + .long NvicMux15_IRQHandler /* CM0 + NVIC Mux input 15 */ + .long NvicMux16_IRQHandler /* CM0 + NVIC Mux input 16 */ + .long NvicMux17_IRQHandler /* CM0 + NVIC Mux input 17 */ + .long NvicMux18_IRQHandler /* CM0 + NVIC Mux input 18 */ + .long NvicMux19_IRQHandler /* CM0 + NVIC Mux input 19 */ + .long NvicMux20_IRQHandler /* CM0 + NVIC Mux input 20 */ + .long NvicMux21_IRQHandler /* CM0 + NVIC Mux input 21 */ + .long NvicMux22_IRQHandler /* CM0 + NVIC Mux input 22 */ + .long NvicMux23_IRQHandler /* CM0 + NVIC Mux input 23 */ + .long NvicMux24_IRQHandler /* CM0 + NVIC Mux input 24 */ + .long NvicMux25_IRQHandler /* CM0 + NVIC Mux input 25 */ + .long NvicMux26_IRQHandler /* CM0 + NVIC Mux input 26 */ + .long NvicMux27_IRQHandler /* CM0 + NVIC Mux input 27 */ + .long NvicMux28_IRQHandler /* CM0 + NVIC Mux input 28 */ + .long NvicMux29_IRQHandler /* CM0 + NVIC Mux input 29 */ + .long NvicMux30_IRQHandler /* CM0 + NVIC Mux input 30 */ + .long NvicMux31_IRQHandler /* CM0 + NVIC Mux input 31 */ + + .size __Vectors, . - __Vectors + .equ __VectorsSize, . - __Vectors + + .section .ram_vectors + .align 2 + .globl __ramVectors +__ramVectors: + .space __VectorsSize + .size __ramVectors, . - __ramVectors + + + .text + .thumb + .thumb_func + .align 2 + + /* Device startup customization */ + .weak Cy_OnResetUser + .func Cy_OnResetUser, Cy_OnResetUser + .type Cy_OnResetUser, %function +Cy_OnResetUser: + + bx lr + .size Cy_OnResetUser, . - Cy_OnResetUser + .endfunc + + /* Saves and disables the interrupts */ + .global Cy_SaveIRQ + .func Cy_SaveIRQ, Cy_SaveIRQ + .type Cy_SaveIRQ, %function +Cy_SaveIRQ: + mrs r0, PRIMASK + cpsid i + bx lr + .size Cy_SaveIRQ, . - Cy_SaveIRQ + .endfunc + + /* Restores the interrupts */ + .global Cy_RestoreIRQ + .func Cy_RestoreIRQ, Cy_RestoreIRQ + .type Cy_RestoreIRQ, %function +Cy_RestoreIRQ: + msr PRIMASK, r0 + bx lr + .size Cy_RestoreIRQ, . - Cy_RestoreIRQ + .endfunc + + /* Reset handler */ + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + + bl Cy_OnResetUser + +/* Firstly it copies data from read only memory to RAM. There are two schemes + * to copy. One can copy more than one sections. Another can only copy + * one section. The former scheme needs more instructions and read-only + * data to implement than the latter. + * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */ + +#ifdef __STARTUP_COPY_MULTIPLE +/* Multiple sections scheme. + * + * Between symbol address __copy_table_start__ and __copy_table_end__, + * there are array of triplets, each of which specify: + * offset 0: LMA of start of a section to copy from + * offset 4: VMA of start of a section to copy to + * offset 8: size of the section to copy. Must be multiply of 4 + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r4, =__copy_table_start__ + ldr r5, =__copy_table_end__ + +.L_loop0: + cmp r4, r5 + bge .L_loop0_done + ldr r1, [r4] + ldr r2, [r4, #4] + ldr r3, [r4, #8] + +.L_loop0_0: + subs r3, #4 + blt .L_loop0_0_done + ldr r0, [r1, r3] + str r0, [r2, r3] + b .L_loop0_0 + +.L_loop0_0_done: + adds r4, #12 + b .L_loop0 + +.L_loop0_done: +#else +/* Single section scheme. + * + * The ranges of copy from/to are specified by following symbols + * __etext: LMA of start of the section to copy from. Usually end of text + * __data_start__: VMA of start of the section to copy to + * __data_end__: VMA of end of the section to copy to + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__etext + ldr r2, =__data_start__ + ldr r3, =__data_end__ + + subs r3, r2 + ble .L_loop1_done + +.L_loop1: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt .L_loop1 + +.L_loop1_done: +#endif /*__STARTUP_COPY_MULTIPLE */ + +/* This part of work usually is done in C library startup code. Otherwise, + * define this macro to enable it in this startup. + * + * There are two schemes too. One can clear multiple BSS sections. Another + * can only clear one section. The former is more size expensive than the + * latter. + * + * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former. + * Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later. + */ +#ifdef __STARTUP_CLEAR_BSS_MULTIPLE +/* Multiple sections scheme. + * + * Between symbol address __copy_table_start__ and __copy_table_end__, + * there are array of tuples specifying: + * offset 0: Start of a BSS section + * offset 4: Size of this BSS section. Must be multiply of 4 + */ + ldr r3, =__zero_table_start__ + ldr r4, =__zero_table_end__ + +.L_loop2: + cmp r3, r4 + bge .L_loop2_done + ldr r1, [r3] + ldr r2, [r3, #4] + movs r0, 0 + +.L_loop2_0: + subs r2, #4 + blt .L_loop2_0_done + str r0, [r1, r2] + b .L_loop2_0 +.L_loop2_0_done: + + adds r3, #8 + b .L_loop2 +.L_loop2_done: +#elif defined (__STARTUP_CLEAR_BSS) +/* Single BSS section scheme. + * + * The BSS section is specified by following symbols + * __bss_start__: start of the BSS section. + * __bss_end__: end of the BSS section. + * + * Both addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__bss_start__ + ldr r2, =__bss_end__ + + movs r0, 0 + + subs r2, r1 + ble .L_loop3_done + +.L_loop3: + subs r2, #4 + str r0, [r1, r2] + bgt .L_loop3 +.L_loop3_done: +#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */ + + /* Update Vector Table Offset Register. */ + ldr r0, =__ramVectors + ldr r1, =CY_CPU_VTOR_ADDR + str r0, [r1] + dsb 0xF + + bl _start + + /* Should never get here */ + b . + + .pool + .size Reset_Handler, . - Reset_Handler + + .align 1 + .thumb_func + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + + .weak Cy_SysLib_FaultHandler + .type Cy_SysLib_FaultHandler, %function +Cy_SysLib_FaultHandler: + b . + .size Cy_SysLib_FaultHandler, . - Cy_SysLib_FaultHandler + + + .type Fault_Handler, %function +Fault_Handler: + /* Storing LR content for Creator call stack trace */ + push {LR} + movs r0, #4 + mov r1, LR + tst r0, r1 + beq .L_MSP + mrs r0, PSP + b .L_API_call +.L_MSP: + mrs r0, MSP +.L_API_call: + /* Compensation of stack pointer address due to pushing 4 bytes of LR */ + adds r0, r0, #4 + bl Cy_SysLib_FaultHandler + b . + .size Fault_Handler, . - Fault_Handler + +.macro def_fault_Handler fault_handler_name + .weak \fault_handler_name + .set \fault_handler_name, Fault_Handler + .endm + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler NMI_Handler + + def_fault_Handler HardFault_Handler + + def_irq_handler SVC_Handler + def_irq_handler PendSV_Handler + def_irq_handler SysTick_Handler + + def_irq_handler NvicMux0_IRQHandler /* CM0 + NVIC Mux input 0 */ + def_irq_handler NvicMux1_IRQHandler /* CM0 + NVIC Mux input 1 */ + def_irq_handler NvicMux2_IRQHandler /* CM0 + NVIC Mux input 2 */ + def_irq_handler NvicMux3_IRQHandler /* CM0 + NVIC Mux input 3 */ + def_irq_handler NvicMux4_IRQHandler /* CM0 + NVIC Mux input 4 */ + def_irq_handler NvicMux5_IRQHandler /* CM0 + NVIC Mux input 5 */ + def_irq_handler NvicMux6_IRQHandler /* CM0 + NVIC Mux input 6 */ + def_irq_handler NvicMux7_IRQHandler /* CM0 + NVIC Mux input 7 */ + def_irq_handler NvicMux8_IRQHandler /* CM0 + NVIC Mux input 8 */ + def_irq_handler NvicMux9_IRQHandler /* CM0 + NVIC Mux input 9 */ + def_irq_handler NvicMux10_IRQHandler /* CM0 + NVIC Mux input 10 */ + def_irq_handler NvicMux11_IRQHandler /* CM0 + NVIC Mux input 11 */ + def_irq_handler NvicMux12_IRQHandler /* CM0 + NVIC Mux input 12 */ + def_irq_handler NvicMux13_IRQHandler /* CM0 + NVIC Mux input 13 */ + def_irq_handler NvicMux14_IRQHandler /* CM0 + NVIC Mux input 14 */ + def_irq_handler NvicMux15_IRQHandler /* CM0 + NVIC Mux input 15 */ + def_irq_handler NvicMux16_IRQHandler /* CM0 + NVIC Mux input 16 */ + def_irq_handler NvicMux17_IRQHandler /* CM0 + NVIC Mux input 17 */ + def_irq_handler NvicMux18_IRQHandler /* CM0 + NVIC Mux input 18 */ + def_irq_handler NvicMux19_IRQHandler /* CM0 + NVIC Mux input 19 */ + def_irq_handler NvicMux20_IRQHandler /* CM0 + NVIC Mux input 20 */ + def_irq_handler NvicMux21_IRQHandler /* CM0 + NVIC Mux input 21 */ + def_irq_handler NvicMux22_IRQHandler /* CM0 + NVIC Mux input 22 */ + def_irq_handler NvicMux23_IRQHandler /* CM0 + NVIC Mux input 23 */ + def_irq_handler NvicMux24_IRQHandler /* CM0 + NVIC Mux input 24 */ + def_irq_handler NvicMux25_IRQHandler /* CM0 + NVIC Mux input 25 */ + def_irq_handler NvicMux26_IRQHandler /* CM0 + NVIC Mux input 26 */ + def_irq_handler NvicMux27_IRQHandler /* CM0 + NVIC Mux input 27 */ + def_irq_handler NvicMux28_IRQHandler /* CM0 + NVIC Mux input 28 */ + def_irq_handler NvicMux29_IRQHandler /* CM0 + NVIC Mux input 29 */ + def_irq_handler NvicMux30_IRQHandler /* CM0 + NVIC Mux input 30 */ + def_irq_handler NvicMux31_IRQHandler /* CM0 + NVIC Mux input 31 */ + + .end + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_IAR/cy8c6xx7_cm0plus.icf b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_IAR/cy8c6xx7_cm0plus.icf new file mode 100644 index 0000000000..f37c1d9718 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_IAR/cy8c6xx7_cm0plus.icf @@ -0,0 +1,216 @@ +/***************************************************************************//** +* \file cy8c6xx7_cm0plus.icf +* \version 2.10 +* +* Linker file for the IAR compiler. +* +* The main purpose of the linker script is to describe how the sections in the +* input files should be mapped into the output file, and to control the memory +* layout of the output file. +* +* \note The entry point is fixed and starts at 0x10000000. The valid application +* image should be placed there. +* +* \note The linker files included with the PDL template projects must be generic +* and handle all common use cases. Your project may not use every section +* defined in the linker files. In that case you may see warnings during the +* build process. In your project, you can simply comment out or remove the +* relevant code in the linker file. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_4.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x00000000; + +/* The symbols below define the location and size of blocks of memory in the target. + * Use these symbols to specify the memory regions available for allocation. + */ + +/* The following symbols control RAM and flash memory allocation for the CM0+ core. + * You can change the memory allocation by editing RAM and Flash symbols. + * Your changes must be aligned with the corresponding symbols for CM4 core in 'xx_cm4_dual.icf', + * where 'xx' is the device group; for example, 'cy8c6xx7_cm4_dual.icf'. + */ +/* RAM */ +define symbol __ICFEDIT_region_IRAM1_start__ = 0x08000000; +define symbol __ICFEDIT_region_IRAM1_end__ = 0x08010000; +/* Flash */ +define symbol __ICFEDIT_region_IROM1_start__ = 0x10000000; +define symbol __ICFEDIT_region_IROM1_end__ = 0x10078000; + +/* The following symbols define a 32K flash region used for EEPROM emulation. + * This region can also be used as the general purpose flash. + * You can assign sections to this memory region for only one of the cores. + * Note some middleware (e.g. BLE, Emulated EEPROM) can place their data into this memory region. + * Therefore, repurposing this memory region will prevent such middleware from operation. + */ +define symbol __ICFEDIT_region_IROM2_start__ = 0x14000000; +define symbol __ICFEDIT_region_IROM2_end__ = 0x14007FFF; + +/* The following symbols define device specific memory regions and must not be changed. */ +/* Supervisory FLASH - User Data */ +define symbol __ICFEDIT_region_IROM3_start__ = 0x16000800; +define symbol __ICFEDIT_region_IROM3_end__ = 0x160007FF; + +/* Supervisory FLASH - Normal Access Restrictions (NAR) */ +define symbol __ICFEDIT_region_IROM4_start__ = 0x16001A00; +define symbol __ICFEDIT_region_IROM4_end__ = 0x16001BFF; + +/* Supervisory FLASH - Public Key */ +define symbol __ICFEDIT_region_IROM5_start__ = 0x16005A00; +define symbol __ICFEDIT_region_IROM5_end__ = 0x160065FF; + +/* Supervisory FLASH - Table of Content # 2 */ +define symbol __ICFEDIT_region_IROM6_start__ = 0x16007C00; +define symbol __ICFEDIT_region_IROM6_end__ = 0x16007DFF; + +/* Supervisory FLASH - Table of Content # 2 Copy */ +define symbol __ICFEDIT_region_IROM7_start__ = 0x16007E00; +define symbol __ICFEDIT_region_IROM7_end__ = 0x16007FFF; + +/* eFuse */ +define symbol __ICFEDIT_region_IROM8_start__ = 0x90700000; +define symbol __ICFEDIT_region_IROM8_end__ = 0x907FFFFF; + +/* XIP */ +define symbol __ICFEDIT_region_EROM1_start__ = 0x18000000; +define symbol __ICFEDIT_region_EROM1_end__ = 0x1FFFFFFF; + +define symbol __ICFEDIT_region_EROM2_start__ = 0x0; +define symbol __ICFEDIT_region_EROM2_end__ = 0x0; +define symbol __ICFEDIT_region_EROM3_start__ = 0x0; +define symbol __ICFEDIT_region_EROM3_end__ = 0x0; + + +define symbol __ICFEDIT_region_IRAM2_start__ = 0x0; +define symbol __ICFEDIT_region_IRAM2_end__ = 0x0; +define symbol __ICFEDIT_region_ERAM1_start__ = 0x0; +define symbol __ICFEDIT_region_ERAM1_end__ = 0x0; +define symbol __ICFEDIT_region_ERAM2_start__ = 0x0; +define symbol __ICFEDIT_region_ERAM2_end__ = 0x0; +define symbol __ICFEDIT_region_ERAM3_start__ = 0x0; +define symbol __ICFEDIT_region_ERAM3_end__ = 0x0; +/*-Sizes-*/ +if (!isdefinedsymbol(__STACK_SIZE)) { + define symbol __ICFEDIT_size_cstack__ = 0x1000; +} else { + define symbol __ICFEDIT_size_cstack__ = __STACK_SIZE; +} +define symbol __ICFEDIT_size_proc_stack__ = 0x0; +if (!isdefinedsymbol(__HEAP_SIZE)) { + define symbol __ICFEDIT_size_heap__ = 0x4000; +} else { + define symbol __ICFEDIT_size_heap__ = __HEAP_SIZE; +} +/**** End of ICF editor section. ###ICF###*/ + + +define memory mem with size = 4G; +define region IROM1_region = mem:[from __ICFEDIT_region_IROM1_start__ to __ICFEDIT_region_IROM1_end__]; +define region IROM2_region = mem:[from __ICFEDIT_region_IROM2_start__ to __ICFEDIT_region_IROM2_end__]; +define region IROM3_region = mem:[from __ICFEDIT_region_IROM3_start__ to __ICFEDIT_region_IROM3_end__]; +define region IROM4_region = mem:[from __ICFEDIT_region_IROM4_start__ to __ICFEDIT_region_IROM4_end__]; +define region IROM5_region = mem:[from __ICFEDIT_region_IROM5_start__ to __ICFEDIT_region_IROM5_end__]; +define region IROM6_region = mem:[from __ICFEDIT_region_IROM6_start__ to __ICFEDIT_region_IROM6_end__]; +define region IROM7_region = mem:[from __ICFEDIT_region_IROM7_start__ to __ICFEDIT_region_IROM7_end__]; +define region IROM8_region = mem:[from __ICFEDIT_region_IROM8_start__ to __ICFEDIT_region_IROM8_end__]; +define region EROM1_region = mem:[from __ICFEDIT_region_EROM1_start__ to __ICFEDIT_region_EROM1_end__]; +define region IRAM1_region = mem:[from __ICFEDIT_region_IRAM1_start__ to __ICFEDIT_region_IRAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block PROC_STACK with alignment = 8, size = __ICFEDIT_size_proc_stack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; +define block HSTACK {block HEAP, block PROC_STACK, last block CSTACK}; +define block RO {first section .intvec, readonly}; + +/*-Initializations-*/ +initialize by copy { readwrite }; +do not initialize { section .noinit, section .intvec_ram }; + + +/*-Placement-*/ + +/* Flash */ +".cy_app_header" : place at start of IROM1_region { section .cy_app_header }; +place in IROM1_region { block RO }; + +/* Emulated EEPROM Flash area */ +".cy_em_eeprom" : place at start of IROM2_region { section .cy_em_eeprom }; + +/* Supervisory Flash - User Data */ +".cy_sflash_user_data" : place at start of IROM3_region { section .cy_sflash_user_data }; + +/* Supervisory Flash - NAR */ +".cy_sflash_nar" : place at start of IROM4_region { section .cy_sflash_nar }; + +/* Supervisory Flash - Public Key */ +".cy_sflash_public_key" : place at start of IROM5_region { section .cy_sflash_public_key }; + +/* Supervisory Flash - TOC2 */ +".cy_toc_part2" : place at start of IROM6_region { section .cy_toc_part2 }; + +/* Supervisory Flash - RTOC2 */ +".cy_rtoc_part2" : place at start of IROM7_region { section .cy_rtoc_part2 }; + +/* eFuse */ +".cy_efuse" : place at start of IROM8_region { section .cy_efuse }; + +/* Execute in Place (XIP). See the smif driver documentation for details. */ +".cy_xip" : place at start of EROM1_region { section .cy_xip }; + +/* RAM */ +place at start of IRAM1_region { readwrite section .intvec_ram}; +place in IRAM1_region { readwrite }; +place at end of IRAM1_region { block HSTACK }; + +/* These sections are used for additional metadata (silicon revision, Silicon/JTAG ID, etc.) storage. */ +".cymeta" : place at address mem : 0x90500000 { readonly section .cymeta }; + + +keep { section .cy_app_header, + section .cy_em_eeprom, + section .cy_sflash_user_data, + section .cy_sflash_nar, + section .cy_sflash_public_key, + section .cy_toc_part2, + section .cy_rtoc_part2, + section .cy_efuse, + section .cy_xip, + section .cymeta, + }; + + +/* The following symbols used by the cymcuelftool. */ +/* Flash */ +define exported symbol __cy_memory_0_start = 0x10000000; +define exported symbol __cy_memory_0_length = 0x00100000; +define exported symbol __cy_memory_0_row_size = 0x200; + +/* Emulated EEPROM Flash area */ +define exported symbol __cy_memory_1_start = 0x14000000; +define exported symbol __cy_memory_1_length = 0x8000; +define exported symbol __cy_memory_1_row_size = 0x200; + +/* Supervisory Flash */ +define exported symbol __cy_memory_2_start = 0x16000000; +define exported symbol __cy_memory_2_length = 0x8000; +define exported symbol __cy_memory_2_row_size = 0x200; + +/* XIP */ +define exported symbol __cy_memory_3_start = 0x18000000; +define exported symbol __cy_memory_3_length = 0x08000000; +define exported symbol __cy_memory_3_row_size = 0x200; + +/* eFuse */ +define exported symbol __cy_memory_4_start = 0x90700000; +define exported symbol __cy_memory_4_length = 0x100000; +define exported symbol __cy_memory_4_row_size = 1; + +/* EOF */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_IAR/startup_psoc63_cm0plus.S b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_IAR/startup_psoc63_cm0plus.S new file mode 100644 index 0000000000..34ad737a3a --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/device/TOOLCHAIN_IAR/startup_psoc63_cm0plus.S @@ -0,0 +1,417 @@ +;/**************************************************************************//** +; * @file startup_psoc63_cm0plus.s +; * @brief CMSIS Core Device Startup File for +; * ARMCM0plus Device Series +; * @version V5.00 +; * @date 08. March 2016 +; ******************************************************************************/ +;/* +; * Copyright (c) 2009-2016 ARM Limited. All rights reserved. +; * +; * 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 +; * +; * 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. +; */ + +; +; The modules in this file are included in the libraries, and may be replaced +; by any user-defined modules that define the PUBLIC symbol _program_start or +; a user defined start symbol. +; To override the cstartup defined in the library, simply add your modified +; version to the workbench project. +; +; The vector table is normally located at address 0. +; When debugging in RAM, it can be located in RAM, aligned to at least 2^6. +; The name "__vector_table" has special meaning for C-SPY: +; it is where the SP start value is found, and the NVIC vector +; table register (VTOR) is initialized to this address if != 0. +; +; Cortex-M version +; + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + SECTION .intvec_ram:DATA:NOROOT(2) + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + PUBLIC __vector_table + PUBLIC __vector_table_0x1c + PUBLIC __Vectors + PUBLIC __Vectors_End + PUBLIC __Vectors_Size + PUBLIC __ramVectors + + DATA + +__vector_table + DCD sfe(CSTACK) + DCD Reset_Handler + + DCD 0x0000000D ; NMI_Handler is defined in ROM code + DCD HardFault_Handler + DCD 0 + DCD 0 + DCD 0 +__vector_table_0x1c + DCD 0 + DCD 0 + DCD 0 + DCD 0 + DCD SVC_Handler + DCD 0 + DCD 0 + DCD PendSV_Handler + DCD SysTick_Handler + + ; External interrupts Power Mode Description + DCD NvicMux0_IRQHandler ; CM0 + NVIC Mux input 0 + DCD NvicMux1_IRQHandler ; CM0 + NVIC Mux input 1 + DCD NvicMux2_IRQHandler ; CM0 + NVIC Mux input 2 + DCD NvicMux3_IRQHandler ; CM0 + NVIC Mux input 3 + DCD NvicMux4_IRQHandler ; CM0 + NVIC Mux input 4 + DCD NvicMux5_IRQHandler ; CM0 + NVIC Mux input 5 + DCD NvicMux6_IRQHandler ; CM0 + NVIC Mux input 6 + DCD NvicMux7_IRQHandler ; CM0 + NVIC Mux input 7 + DCD NvicMux8_IRQHandler ; CM0 + NVIC Mux input 8 + DCD NvicMux9_IRQHandler ; CM0 + NVIC Mux input 9 + DCD NvicMux10_IRQHandler ; CM0 + NVIC Mux input 10 + DCD NvicMux11_IRQHandler ; CM0 + NVIC Mux input 11 + DCD NvicMux12_IRQHandler ; CM0 + NVIC Mux input 12 + DCD NvicMux13_IRQHandler ; CM0 + NVIC Mux input 13 + DCD NvicMux14_IRQHandler ; CM0 + NVIC Mux input 14 + DCD NvicMux15_IRQHandler ; CM0 + NVIC Mux input 15 + DCD NvicMux16_IRQHandler ; CM0 + NVIC Mux input 16 + DCD NvicMux17_IRQHandler ; CM0 + NVIC Mux input 17 + DCD NvicMux18_IRQHandler ; CM0 + NVIC Mux input 18 + DCD NvicMux19_IRQHandler ; CM0 + NVIC Mux input 19 + DCD NvicMux20_IRQHandler ; CM0 + NVIC Mux input 20 + DCD NvicMux21_IRQHandler ; CM0 + NVIC Mux input 21 + DCD NvicMux22_IRQHandler ; CM0 + NVIC Mux input 22 + DCD NvicMux23_IRQHandler ; CM0 + NVIC Mux input 23 + DCD NvicMux24_IRQHandler ; CM0 + NVIC Mux input 24 + DCD NvicMux25_IRQHandler ; CM0 + NVIC Mux input 25 + DCD NvicMux26_IRQHandler ; CM0 + NVIC Mux input 26 + DCD NvicMux27_IRQHandler ; CM0 + NVIC Mux input 27 + DCD NvicMux28_IRQHandler ; CM0 + NVIC Mux input 28 + DCD NvicMux29_IRQHandler ; CM0 + NVIC Mux input 29 + DCD NvicMux30_IRQHandler ; CM0 + NVIC Mux input 30 + DCD NvicMux31_IRQHandler ; CM0 + NVIC Mux input 31 + +__Vectors_End + +__Vectors EQU __vector_table +__Vectors_Size EQU __Vectors_End - __Vectors + + SECTION .intvec_ram:DATA:REORDER:NOROOT(2) +__ramVectors + DS32 __Vectors_Size + + + THUMB + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default handlers +;; + PUBWEAK Default_Handler + SECTION .text:CODE:REORDER:NOROOT(2) +Default_Handler + B Default_Handler + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Saves and disables the interrupts +;; + PUBLIC Cy_SaveIRQ + SECTION .text:CODE:REORDER:NOROOT(2) +Cy_SaveIRQ + MRS r0, PRIMASK + CPSID I + BX LR + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Restores the interrupts +;; + PUBLIC Cy_RestoreIRQ + SECTION .text:CODE:REORDER:NOROOT(2) +Cy_RestoreIRQ + MSR PRIMASK, r0 + BX LR + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Weak function for startup customization +;; + PUBWEAK Cy_OnResetUser + SECTION .text:CODE:REORDER:NOROOT(2) +Cy_OnResetUser + BX LR + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + PUBWEAK Reset_Handler + SECTION .text:CODE:REORDER:NOROOT(2) +Reset_Handler + + ; Define strong function for startup customization + LDR R0, =Cy_OnResetUser + BLX R0 + + ; Copy vectors from ROM to RAM + LDR r1, =__vector_table + LDR r0, =__ramVectors + LDR r2, =__Vectors_Size +intvec_copy + LDR r3, [r1] + STR r3, [r0] + ADDS r0, r0, #4 + ADDS r1, r1, #4 + SUBS r2, r2, #1 + CMP r2, #0 + BNE intvec_copy + + ; Update Vector Table Offset Register + LDR r0, =__ramVectors + LDR r1, =0xE000ED08 + STR r0, [r1] + dsb + + LDR R0, =__iar_program_start + BLX R0 + +; Should never get here +Cy_Main_Exited + B Cy_Main_Exited + + + PUBWEAK NMI_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +NMI_Handler + B NMI_Handler + + + PUBWEAK Cy_SysLib_FaultHandler + SECTION .text:CODE:REORDER:NOROOT(1) +Cy_SysLib_FaultHandler + B Cy_SysLib_FaultHandler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +HardFault_Handler + IMPORT Cy_SysLib_FaultHandler + movs r0, #4 + mov r1, LR + tst r0, r1 + beq L_MSP + mrs r0, PSP + b L_API_call +L_MSP + mrs r0, MSP +L_API_call + ; Storing LR content for Creator call stack trace + push {LR} + bl Cy_SysLib_FaultHandler + + + PUBWEAK SVC_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +SVC_Handler + B SVC_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +SysTick_Handler + B SysTick_Handler + + + ; External interrupts + PUBWEAK NvicMux0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux0_IRQHandler + B NvicMux0_IRQHandler + + PUBWEAK NvicMux1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux1_IRQHandler + B NvicMux1_IRQHandler + + PUBWEAK NvicMux2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux2_IRQHandler + B NvicMux2_IRQHandler + + PUBWEAK NvicMux3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux3_IRQHandler + B NvicMux3_IRQHandler + + PUBWEAK NvicMux4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux4_IRQHandler + B NvicMux4_IRQHandler + + PUBWEAK NvicMux5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux5_IRQHandler + B NvicMux5_IRQHandler + + PUBWEAK NvicMux6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux6_IRQHandler + B NvicMux6_IRQHandler + + PUBWEAK NvicMux7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux7_IRQHandler + B NvicMux7_IRQHandler + + PUBWEAK NvicMux8_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux8_IRQHandler + B NvicMux8_IRQHandler + + PUBWEAK NvicMux9_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux9_IRQHandler + B NvicMux9_IRQHandler + + PUBWEAK NvicMux10_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux10_IRQHandler + B NvicMux10_IRQHandler + + PUBWEAK NvicMux11_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux11_IRQHandler + B NvicMux11_IRQHandler + + PUBWEAK NvicMux12_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux12_IRQHandler + B NvicMux12_IRQHandler + + PUBWEAK NvicMux13_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux13_IRQHandler + B NvicMux13_IRQHandler + + PUBWEAK NvicMux14_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux14_IRQHandler + B NvicMux14_IRQHandler + + PUBWEAK NvicMux15_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux15_IRQHandler + B NvicMux15_IRQHandler + + PUBWEAK NvicMux16_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux16_IRQHandler + B NvicMux16_IRQHandler + + PUBWEAK NvicMux17_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux17_IRQHandler + B NvicMux17_IRQHandler + + PUBWEAK NvicMux18_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux18_IRQHandler + B NvicMux18_IRQHandler + + PUBWEAK NvicMux19_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux19_IRQHandler + B NvicMux19_IRQHandler + + PUBWEAK NvicMux20_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux20_IRQHandler + B NvicMux20_IRQHandler + + PUBWEAK NvicMux21_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux21_IRQHandler + B NvicMux21_IRQHandler + + PUBWEAK NvicMux22_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux22_IRQHandler + B NvicMux22_IRQHandler + + PUBWEAK NvicMux23_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux23_IRQHandler + B NvicMux23_IRQHandler + + PUBWEAK NvicMux24_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux24_IRQHandler + B NvicMux24_IRQHandler + + PUBWEAK NvicMux25_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux25_IRQHandler + B NvicMux25_IRQHandler + + PUBWEAK NvicMux26_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux26_IRQHandler + B NvicMux26_IRQHandler + + PUBWEAK NvicMux27_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux27_IRQHandler + B NvicMux27_IRQHandler + + PUBWEAK NvicMux28_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux28_IRQHandler + B NvicMux28_IRQHandler + + PUBWEAK NvicMux29_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux29_IRQHandler + B NvicMux29_IRQHandler + + PUBWEAK NvicMux30_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux30_IRQHandler + B NvicMux30_IRQHandler + + PUBWEAK NvicMux31_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +NvicMux31_IRQHandler + B NvicMux31_IRQHandler + + + END + + +; [] END OF FILE diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/ipc_rpc_m0.c b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/ipc_rpc_m0.c new file mode 100644 index 0000000000..5757ab5cd6 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/ipc_rpc_m0.c @@ -0,0 +1,38 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#include "psoc6_utils.h" +#include "ipc_rpc.h" +#include "rpc_defs.h" +#include "cy_ipc_config.h" +#include "ipc/cy_ipc_pipe.h" + +#define RPC_GEN RPC_GEN_IMPLEMENTATION +#include "rpc_api.h" +#undef RPC_GEN + + +void ipcrpc_init(void) +{ + uint32_t rpc_counter = 0; + +#define RPC_GEN RPC_GEN_INITIALIZATION +#include "rpc_api.h" +#undef RPC_GEN +} + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/system_psoc63_cm0plus.c b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/system_psoc63_cm0plus.c new file mode 100644 index 0000000000..ee1d0b227f --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M0/system_psoc63_cm0plus.c @@ -0,0 +1,636 @@ +/***************************************************************************//** +* \file system_psoc63_cm0plus.c +* \version 2.10 +* +* The device system-source file. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* Copyright 2017-2018, Future Electronics +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include +#include +#include "device.h" +#include "system_psoc63.h" +#include "cy_device_headers.h" +#include "ipc_rpc.h" +#include "psoc6_utils.h" + +#if defined(CY_DEVICE_PSOC6ABLE2) + #if !defined(CY_PSOC6ABLE2_REV_0A_SUPPORT_DISABLE) + #include "syslib/cy_syslib.h" + #endif /* !defined(CY_PSOC6ABLE2_REV_0A_SUPPORT_DISABLE) */ + #if !defined(CY_IPC_DEFAULT_CFG_DISABLE) + #include "ipc/cy_ipc_drv.h" + #include "flash/cy_flash.h" + #endif /* !defined(CY_IPC_DEFAULT_CFG_DISABLE) */ +#endif /* defined(CY_DEVICE_PSOC6ABLE2) */ + + +/******************************************************************************* +* SystemCoreClockUpdate() +*******************************************************************************/ + +/** Default HFClk frequency in Hz */ +#define CY_CLK_HFCLK0_FREQ_HZ_DEFAULT CY_CLK_HFCLK0_FREQ_HZ + +/** Default PeriClk frequency in Hz */ +#define CY_CLK_PERICLK_FREQ_HZ_DEFAULT CY_CLK_PERICLK_FREQ_HZ + +/** Default SlowClk system core frequency in Hz */ +#define CY_CLK_SYSTEM_FREQ_HZ_DEFAULT CY_CLK_SLOWCLK_FREQ_HZ + +/** +* Holds the SlowClk (Cortex-M0+) or FastClk (Cortex-M4) system core clock, +* which is the system clock frequency supplied to the SysTick timer and the +* processor core clock. +* This variable implements CMSIS Core global variable. +* Refer to the [CMSIS documentation] +* (http://www.keil.com/pack/doc/CMSIS/Core/html/group__system__init__gr.html "System and Clock Configuration") +* for more details. +* This variable can be used by debuggers to query the frequency +* of the debug timer or to configure the trace clock speed. +* +* \attention Compilers must be configured to avoid removing this variable in case +* the application program is not using it. Debugging systems require the variable +* to be physically present in memory so that it can be examined to configure the debugger. */ +uint32_t SystemCoreClock = CY_CLK_SYSTEM_FREQ_HZ_DEFAULT; + +/** Holds the HFClk0 clock frequency. Updated by \ref SystemCoreClockUpdate(). */ +uint32_t cy_Hfclk0FreqHz = CY_CLK_HFCLK0_FREQ_HZ_DEFAULT; + +/** Holds the PeriClk clock frequency. Updated by \ref SystemCoreClockUpdate(). */ +uint32_t cy_PeriClkFreqHz = CY_CLK_PERICLK_FREQ_HZ_DEFAULT; + +/** Holds the Alternate high frequency clock in Hz. Updated by \ref SystemCoreClockUpdate(). */ +#if defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) + uint32_t cy_BleEcoClockFreqHz = CY_CLK_ALTHF_FREQ_HZ; +#endif /* defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) */ + + +/******************************************************************************* +* SystemInit() +*******************************************************************************/ +/* WDT lock bits */ +#define CY_WDT_LOCK_BIT0 ((uint32_t)0x01u << 30u) +#define CY_WDT_LOCK_BIT1 ((uint32_t)0x01u << 31u) + +/* CLK_FLL_CONFIG default values */ +#define CY_FB_CLK_FLL_CONFIG_VALUE (0x01000000u) +#define CY_FB_CLK_FLL_CONFIG2_VALUE (0x00020001u) +#define CY_FB_CLK_FLL_CONFIG3_VALUE (0x00002800u) +#define CY_FB_CLK_FLL_CONFIG4_VALUE (0x000000FFu) + + +/******************************************************************************* +* SystemCoreClockUpdate (void) +*******************************************************************************/ +/* Do not use these definitions directly in your application */ +#define CY_DELAY_MS_OVERFLOW_THRESHOLD (0x8000u) +#define CY_DELAY_1K_THRESHOLD (1000u) +#define CY_DELAY_1K_MINUS_1_THRESHOLD (CY_DELAY_1K_THRESHOLD - 1u) +#define CY_DELAY_1M_THRESHOLD (1000000u) +#define CY_DELAY_1M_MINUS_1_THRESHOLD (CY_DELAY_1M_THRESHOLD - 1u) +uint32_t cy_delayFreqHz = CY_CLK_SYSTEM_FREQ_HZ_DEFAULT; + +uint32_t cy_delayFreqKhz = (CY_CLK_SYSTEM_FREQ_HZ_DEFAULT + CY_DELAY_1K_MINUS_1_THRESHOLD) / + CY_DELAY_1K_THRESHOLD; + +uint8_t cy_delayFreqMhz = (uint8_t)((CY_CLK_SYSTEM_FREQ_HZ_DEFAULT + CY_DELAY_1M_MINUS_1_THRESHOLD) / + CY_DELAY_1M_THRESHOLD); + +uint32_t cy_delay32kMs = CY_DELAY_MS_OVERFLOW_THRESHOLD * + ((CY_CLK_SYSTEM_FREQ_HZ_DEFAULT + CY_DELAY_1K_MINUS_1_THRESHOLD) / CY_DELAY_1K_THRESHOLD); + +#define CY_ROOT_PATH_SRC_IMO (0UL) +#define CY_ROOT_PATH_SRC_EXT (1UL) +#if (SRSS_ECO_PRESENT == 1U) + #define CY_ROOT_PATH_SRC_ECO (2UL) +#endif /* (SRSS_ECO_PRESENT == 1U) */ +#if (SRSS_ALTHF_PRESENT == 1U) + #define CY_ROOT_PATH_SRC_ALTHF (3UL) +#endif /* (SRSS_ALTHF_PRESENT == 1U) */ +#define CY_ROOT_PATH_SRC_DSI_MUX (4UL) +#define CY_ROOT_PATH_SRC_DSI_MUX_HVILO (16UL) +#define CY_ROOT_PATH_SRC_DSI_MUX_WCO (17UL) +#if (SRSS_ALTLF_PRESENT == 1U) + #define CY_ROOT_PATH_SRC_DSI_MUX_ALTLF (18UL) +#endif /* (SRSS_ALTLF_PRESENT == 1U) */ +#if (SRSS_PILO_PRESENT == 1U) + #define CY_ROOT_PATH_SRC_DSI_MUX_PILO (19UL) +#endif /* (SRSS_PILO_PRESENT == 1U) */ + + +/******************************************************************************* +* Cy_SysEnableCM4(), Cy_SysRetainCM4(), and Cy_SysResetCM4() +*******************************************************************************/ +#define CY_SYS_CM4_PWR_CTL_KEY_OPEN (0x05FAUL) +#define CY_SYS_CM4_PWR_CTL_KEY_CLOSE (0xFA05UL) + + +/******************************************************************************* +* Function Name: mbed_sdk_init +****************************************************************************//** +* +* Mbed's post-memory-initialization function. +* Used here to initialize common parts of the Cypress libraries. +* +*******************************************************************************/ +void mbed_sdk_init(void) +{ + /* Initialize shared resource manager */ + cy_srm_initialize(); + /* Initialize system and clocks. */ + /* Placed here as it must be done after proper LIBC initialization. */ + SystemInit(); + /* Allocate and initialize semaphores for the system operations. */ + Cy_IPC_SystemSemaInit(); + Cy_IPC_SystemPipeInit(); + Cy_Flash_Init(); + ipcrpc_init(); +} + + +/******************************************************************************* +* Function Name: SystemInit +****************************************************************************//** +* +* Initializes the system: +* - Restores FLL registers to the default state. +* - Unlocks and disables WDT. +* - Calls the Cy_SystemInit() function, if compiled from PSoC Creator. +* - Calls \ref SystemCoreClockUpdate(). +* +*******************************************************************************/ +void SystemInit(void) +{ + /* Restore FLL registers to the default state as they are not restored by the ROM code */ + uint32_t copy = SRSS->CLK_FLL_CONFIG; + copy &= ~SRSS_CLK_FLL_CONFIG_FLL_ENABLE_Msk; + SRSS->CLK_FLL_CONFIG = copy; + + copy = SRSS->CLK_ROOT_SELECT[0u]; + copy &= ~SRSS_CLK_ROOT_SELECT_ROOT_DIV_Msk; /* Set ROOT_DIV = 0*/ + SRSS->CLK_ROOT_SELECT[0u] = copy; + + SRSS->CLK_FLL_CONFIG = CY_FB_CLK_FLL_CONFIG_VALUE; + SRSS->CLK_FLL_CONFIG2 = CY_FB_CLK_FLL_CONFIG2_VALUE; + SRSS->CLK_FLL_CONFIG3 = CY_FB_CLK_FLL_CONFIG3_VALUE; + SRSS->CLK_FLL_CONFIG4 = CY_FB_CLK_FLL_CONFIG4_VALUE; + + /* Unlock and disable WDT */ + SRSS->WDT_CTL = ((SRSS->WDT_CTL & (uint32_t)(~SRSS_WDT_CTL_WDT_LOCK_Msk)) | CY_WDT_LOCK_BIT0); + SRSS->WDT_CTL = (SRSS->WDT_CTL | CY_WDT_LOCK_BIT1); + SRSS->WDT_CTL &= (~ (uint32_t) SRSS_WDT_CTL_WDT_EN_Msk); + + Cy_SystemInit(); + SystemCoreClockUpdate(); + +#if defined(CY_DEVICE_PSOC6ABLE2) + #if !defined(CY_IPC_DEFAULT_CFG_DISABLE) + /* Allocate and initialize semaphores for the system operations. */ + Cy_IPC_SystemSemaInit(); + Cy_IPC_SystemPipeInit(); + Cy_Flash_Init(); + #endif /* CY_IPC_DEFAULT_CFG_DISABLE */ + + #if !defined(CY_PSOC6ABLE2_REV_0A_SUPPORT_DISABLE) + if (CY_SYSLIB_DEVICE_REV_0A == Cy_SysLib_GetDeviceRevision()) + { + /* Clear data register of IPC structure #7, reserved for the Deep-Sleep operations. */ + IPC_STRUCT7->DATA = 0UL; + /* Release IPC structure #7 to avoid deadlocks in case of SW or WDT reset during Deep-Sleep entering. */ + IPC_STRUCT7->RELEASE = 0UL; + } + #endif /* !defined(CY_PSOC6ABLE2_REV_0A_SUPPORT_DISABLE) */ +#endif /* CY_DEVICE_PSOC6ABLE2 */ +} + + +/******************************************************************************* +* Function Name: Cy_SystemInit +****************************************************************************//** +* +* The function is called during device startup. Once project compiled as part of +* the PSoC Creator project, the Cy_SystemInit() function is generated by the +* PSoC Creator. +* +* The function generated by PSoC Creator performs all of the necessary device +* configuration based on the design settings. This includes settings from the +* Design Wide Resources (DWR) such as Clocks and Pins as well as any component +* configuration that is necessary. +* +*******************************************************************************/ +__WEAK void Cy_SystemInit(void) +{ + /* Empty weak function. The actual implementation to be in the PSoC Creator + * generated strong function. + */ +} + + +/******************************************************************************* +* Function Name: SystemCoreClockUpdate +****************************************************************************//** +* +* Gets core clock frequency and updates \ref SystemCoreClock, \ref +* cy_Hfclk0FreqHz, and \ref cy_PeriClkFreqHz. +* +* Updates global variables used by the \ref Cy_SysLib_Delay(), \ref +* Cy_SysLib_DelayUs(), and \ref Cy_SysLib_DelayCycles(). +* +*******************************************************************************/ +void SystemCoreClockUpdate (void) +{ + uint32_t srcFreqHz; + uint32_t pathFreqHz; + uint32_t slowClkDiv; + uint32_t periClkDiv; + uint32_t rootPath; + uint32_t srcClk; + + /* Get root path clock for the high-frequency clock # 0 */ + rootPath = _FLD2VAL(SRSS_CLK_ROOT_SELECT_ROOT_MUX, SRSS->CLK_ROOT_SELECT[0u]); + + /* Get source of the root path clock */ + srcClk = _FLD2VAL(SRSS_CLK_PATH_SELECT_PATH_MUX, SRSS->CLK_PATH_SELECT[rootPath]); + + /* Get frequency of the source */ + switch (srcClk) + { + case CY_ROOT_PATH_SRC_IMO: + srcFreqHz = CY_CLK_IMO_FREQ_HZ; + break; + + case CY_ROOT_PATH_SRC_EXT: + srcFreqHz = CY_CLK_EXT_FREQ_HZ; + break; + + #if (SRSS_ECO_PRESENT == 1U) + case CY_ROOT_PATH_SRC_ECO: + srcFreqHz = CY_CLK_ECO_FREQ_HZ; + break; + #endif /* (SRSS_ECO_PRESENT == 1U) */ + +#if defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) && (SRSS_ALTHF_PRESENT == 1U) + case CY_ROOT_PATH_SRC_ALTHF: + srcFreqHz = cy_BleEcoClockFreqHz; + break; +#endif /* defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) && (SRSS_ALTHF_PRESENT == 1U) */ + + case CY_ROOT_PATH_SRC_DSI_MUX: + { + uint32_t dsi_src; + dsi_src = _FLD2VAL(SRSS_CLK_DSI_SELECT_DSI_MUX, SRSS->CLK_DSI_SELECT[rootPath]); + switch (dsi_src) + { + case CY_ROOT_PATH_SRC_DSI_MUX_HVILO: + srcFreqHz = CY_CLK_HVILO_FREQ_HZ; + break; + + case CY_ROOT_PATH_SRC_DSI_MUX_WCO: + srcFreqHz = CY_CLK_WCO_FREQ_HZ; + break; + + #if (SRSS_ALTLF_PRESENT == 1U) + case CY_ROOT_PATH_SRC_DSI_MUX_ALTLF: + srcFreqHz = CY_CLK_ALTLF_FREQ_HZ; + break; + #endif /* (SRSS_ALTLF_PRESENT == 1U) */ + + #if (SRSS_PILO_PRESENT == 1U) + case CY_ROOT_PATH_SRC_DSI_MUX_PILO: + srcFreqHz = CY_CLK_PILO_FREQ_HZ; + break; + #endif /* (SRSS_PILO_PRESENT == 1U) */ + + default: + srcFreqHz = CY_CLK_HVILO_FREQ_HZ; + break; + } + } + break; + + default: + srcFreqHz = CY_CLK_EXT_FREQ_HZ; + break; + } + + if (rootPath == 0UL) + { + /* FLL */ + bool fllLocked = ( 0UL != _FLD2VAL(SRSS_CLK_FLL_STATUS_LOCKED, SRSS->CLK_FLL_STATUS)); + bool fllOutputOutput = ( 3UL == _FLD2VAL(SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, SRSS->CLK_FLL_CONFIG3)); + bool fllOutputAuto = ((0UL == _FLD2VAL(SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, SRSS->CLK_FLL_CONFIG3)) || + (1UL == _FLD2VAL(SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, SRSS->CLK_FLL_CONFIG3))); + if ((fllOutputAuto && fllLocked) || fllOutputOutput) + { + uint32_t fllMult; + uint32_t refDiv; + uint32_t outputDiv; + + fllMult = _FLD2VAL(SRSS_CLK_FLL_CONFIG_FLL_MULT, SRSS->CLK_FLL_CONFIG); + refDiv = _FLD2VAL(SRSS_CLK_FLL_CONFIG2_FLL_REF_DIV, SRSS->CLK_FLL_CONFIG2); + outputDiv = _FLD2VAL(SRSS_CLK_FLL_CONFIG_FLL_OUTPUT_DIV, SRSS->CLK_FLL_CONFIG) + 1UL; + + pathFreqHz = ((srcFreqHz / refDiv) * fllMult) / outputDiv; + } + else + { + pathFreqHz = srcFreqHz; + } + } + else if (rootPath == 1UL) + { + /* PLL */ + bool pllLocked = ( 0UL != _FLD2VAL(SRSS_CLK_PLL_STATUS_LOCKED, SRSS->CLK_PLL_STATUS[0UL])); + bool pllOutputOutput = ( 3UL == _FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, SRSS->CLK_PLL_CONFIG[0UL])); + bool pllOutputAuto = ((0UL == _FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, SRSS->CLK_PLL_CONFIG[0UL])) || + (1UL == _FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, SRSS->CLK_PLL_CONFIG[0UL]))); + if ((pllOutputAuto && pllLocked) || pllOutputOutput) + { + uint32_t feedbackDiv; + uint32_t referenceDiv; + uint32_t outputDiv; + + feedbackDiv = _FLD2VAL(SRSS_CLK_PLL_CONFIG_FEEDBACK_DIV, SRSS->CLK_PLL_CONFIG[0UL]); + referenceDiv = _FLD2VAL(SRSS_CLK_PLL_CONFIG_REFERENCE_DIV, SRSS->CLK_PLL_CONFIG[0UL]); + outputDiv = _FLD2VAL(SRSS_CLK_PLL_CONFIG_OUTPUT_DIV, SRSS->CLK_PLL_CONFIG[0UL]); + + pathFreqHz = ((srcFreqHz * feedbackDiv) / referenceDiv) / outputDiv; + + } + else + { + pathFreqHz = srcFreqHz; + } + } + else + { + /* Direct */ + pathFreqHz = srcFreqHz; + } + + /* Get frequency after hf_clk pre-divider */ + pathFreqHz = pathFreqHz >> _FLD2VAL(SRSS_CLK_ROOT_SELECT_ROOT_DIV, SRSS->CLK_ROOT_SELECT[0u]); + cy_Hfclk0FreqHz = pathFreqHz; + + /* Slow Clock Divider */ + slowClkDiv = 1u + _FLD2VAL(CPUSS_CM0_CLOCK_CTL_SLOW_INT_DIV, CPUSS->CM0_CLOCK_CTL); + + /* Peripheral Clock Divider */ + periClkDiv = 1u + _FLD2VAL(CPUSS_CM0_CLOCK_CTL_PERI_INT_DIV, CPUSS->CM0_CLOCK_CTL); + + pathFreqHz = pathFreqHz / periClkDiv; + cy_PeriClkFreqHz = pathFreqHz; + pathFreqHz = pathFreqHz / slowClkDiv; + SystemCoreClock = pathFreqHz; + + /* Sets clock frequency for Delay API */ + cy_delayFreqHz = SystemCoreClock; + cy_delayFreqMhz = (uint8_t)((cy_delayFreqHz + CY_DELAY_1M_MINUS_1_THRESHOLD) / CY_DELAY_1M_THRESHOLD); + cy_delayFreqKhz = (cy_delayFreqHz + CY_DELAY_1K_MINUS_1_THRESHOLD) / CY_DELAY_1K_THRESHOLD; + cy_delay32kMs = CY_DELAY_MS_OVERFLOW_THRESHOLD * cy_delayFreqKhz; +} + + +#if (CY_SYSTEM_CPU_CM0P == 1UL) || defined(CY_DOXYGEN) +/******************************************************************************* +* Function Name: Cy_SysGetCM4Status +****************************************************************************//** +* +* Returns the Cortex-M4 core power mode. +* +* \return \ref group_system_config_cm4_status_macro +* +*******************************************************************************/ +uint32_t Cy_SysGetCM4Status(void) +{ + uint32_t regValue; + + /* Get current power mode */ + regValue = CPUSS->CM4_PWR_CTL & CPUSS_CM4_PWR_CTL_PWR_MODE_Msk; + + return (regValue); +} + + +/******************************************************************************* +* Function Name: Cy_SysEnableCM4 +****************************************************************************//** +* +* Sets vector table base address and enables the Cortex-M4 core. +* +* \note If the CPU is already enabled, it is reset and then enabled. +* +* \param vectorTableOffset The offset of the vector table base address from +* memory address 0x00000000. The offset should be multiple to 1024 bytes. +* +*******************************************************************************/ +void Cy_SysEnableCM4(uint32_t vectorTableOffset) +{ + uint32_t regValue; + uint32_t interruptState; + uint32_t cpuState; + + interruptState = Cy_SaveIRQ(); + + cpuState = Cy_SysGetCM4Status(); + if (CY_SYS_CM4_STATUS_ENABLED == cpuState) + { + Cy_SysResetCM4(); + } + + CPUSS->CM4_VECTOR_TABLE_BASE = vectorTableOffset; + + regValue = CPUSS->CM4_PWR_CTL & ~(CPUSS_CM4_PWR_CTL_VECTKEYSTAT_Msk | CPUSS_CM4_PWR_CTL_PWR_MODE_Msk); + regValue |= _VAL2FLD(CPUSS_CM4_PWR_CTL_VECTKEYSTAT, CY_SYS_CM4_PWR_CTL_KEY_OPEN); + regValue |= CY_SYS_CM4_STATUS_ENABLED; + CPUSS->CM4_PWR_CTL = regValue; + + while((CPUSS->CM4_STATUS & CPUSS_CM4_STATUS_PWR_DONE_Msk) == 0UL) + { + /* Wait for the power mode to take effect */ + } + + Cy_RestoreIRQ(interruptState); +} + + +/******************************************************************************* +* Function Name: Cy_SysDisableCM4 +****************************************************************************//** +* +* Disables the Cortex-M4 core and waits for the mode to take the effect. +* +* \warning Do not call the function while the Cortex-M4 is executing because +* such a call may corrupt/abort a pending bus-transaction by the CPU and cause +* unexpected behavior in the system including a deadlock. Call the function +* while the Cortex-M4 core is in the Sleep or Deep Sleep low-power mode. Use +* the \ref group_syspm Power Management (syspm) API to put the CPU into the +* low-power modes. Use the \ref Cy_SysPm_ReadStatus() to get a status of the +* CPU. +* +*******************************************************************************/ +void Cy_SysDisableCM4(void) +{ + uint32_t interruptState; + uint32_t regValue; + + interruptState = Cy_SaveIRQ(); + + regValue = CPUSS->CM4_PWR_CTL & ~(CPUSS_CM4_PWR_CTL_VECTKEYSTAT_Msk | CPUSS_CM4_PWR_CTL_PWR_MODE_Msk); + regValue |= _VAL2FLD(CPUSS_CM4_PWR_CTL_VECTKEYSTAT, CY_SYS_CM4_PWR_CTL_KEY_OPEN); + regValue |= CY_SYS_CM4_STATUS_DISABLED; + CPUSS->CM4_PWR_CTL = regValue; + + while((CPUSS->CM4_STATUS & CPUSS_CM4_STATUS_PWR_DONE_Msk) == 0UL) + { + /* Wait for the power mode to take effect */ + } + + Cy_RestoreIRQ(interruptState); +} + + +/******************************************************************************* +* Function Name: Cy_SysRetainCM4 +****************************************************************************//** +* +* Retains the Cortex-M4 core and exists without waiting for the mode to take +* effect. +* +* \note The retained mode can be entered only from the enabled mode. +* +* \warning Do not call the function while the Cortex-M4 is executing because +* such a call may corrupt/abort a pending bus-transaction by the CPU and cause +* unexpected behavior in the system including a deadlock. Call the function +* while the Cortex-M4 core is in the Sleep or Deep Sleep low-power mode. Use +* the \ref group_syspm Power Management (syspm) API to put the CPU into the +* low-power modes. Use the \ref Cy_SysPm_ReadStatus() to get a status of the CPU. +* +*******************************************************************************/ +void Cy_SysRetainCM4(void) +{ + uint32_t interruptState; + uint32_t regValue; + + interruptState = Cy_SaveIRQ(); + + regValue = CPUSS->CM4_PWR_CTL & ~(CPUSS_CM4_PWR_CTL_VECTKEYSTAT_Msk | CPUSS_CM4_PWR_CTL_PWR_MODE_Msk); + regValue |= _VAL2FLD(CPUSS_CM4_PWR_CTL_VECTKEYSTAT, CY_SYS_CM4_PWR_CTL_KEY_OPEN); + regValue |= CY_SYS_CM4_STATUS_RETAINED; + CPUSS->CM4_PWR_CTL = regValue; + + Cy_RestoreIRQ(interruptState); +} + + +/******************************************************************************* +* Function Name: Cy_SysResetCM4 +****************************************************************************//** +* +* Resets the Cortex-M4 core and waits for the mode to take the effect. +* +* \note The reset mode can not be entered from the retained mode. +* +* \warning Do not call the function while the Cortex-M4 is executing because +* such a call may corrupt/abort a pending bus-transaction by the CPU and cause +* unexpected behavior in the system including a deadlock. Call the function +* while the Cortex-M4 core is in the Sleep or Deep Sleep low-power mode. Use +* the \ref group_syspm Power Management (syspm) API to put the CPU into the +* low-power modes. Use the \ref Cy_SysPm_ReadStatus() to get a status of the CPU. +* +*******************************************************************************/ +void Cy_SysResetCM4(void) +{ + uint32_t interruptState; + uint32_t regValue; + + interruptState = Cy_SaveIRQ(); + + regValue = CPUSS->CM4_PWR_CTL & ~(CPUSS_CM4_PWR_CTL_VECTKEYSTAT_Msk | CPUSS_CM4_PWR_CTL_PWR_MODE_Msk); + regValue |= _VAL2FLD(CPUSS_CM4_PWR_CTL_VECTKEYSTAT, CY_SYS_CM4_PWR_CTL_KEY_OPEN); + regValue |= CY_SYS_CM4_STATUS_RESET; + CPUSS->CM4_PWR_CTL = regValue; + + while((CPUSS->CM4_STATUS & CPUSS_CM4_STATUS_PWR_DONE_Msk) == 0UL) + { + /* Wait for the power mode to take effect */ + } + + Cy_RestoreIRQ(interruptState); +} +#endif /* #if (CY_SYSTEM_CPU_CM0P == 1UL) || defined(CY_DOXYGEN) */ + + +/******************************************************************************* +* Function Name: Cy_MemorySymbols +****************************************************************************//** +* +* The intention of the function is to declare boundaries of the memories for the +* MDK compilers. For the rest of the supported compilers, this is done using +* linker configuration files. The following symbols used by the cymcuelftool. +* +*******************************************************************************/ +#if defined (__ARMCC_VERSION) +__asm void Cy_MemorySymbols(void) +{ + /* Flash */ + EXPORT __cy_memory_0_start + EXPORT __cy_memory_0_length + EXPORT __cy_memory_0_row_size + + /* Working Flash */ + EXPORT __cy_memory_1_start + EXPORT __cy_memory_1_length + EXPORT __cy_memory_1_row_size + + /* Supervisory Flash */ + EXPORT __cy_memory_2_start + EXPORT __cy_memory_2_length + EXPORT __cy_memory_2_row_size + + /* XIP */ + EXPORT __cy_memory_3_start + EXPORT __cy_memory_3_length + EXPORT __cy_memory_3_row_size + + /* eFuse */ + EXPORT __cy_memory_4_start + EXPORT __cy_memory_4_length + EXPORT __cy_memory_4_row_size + + + /* Flash */ +__cy_memory_0_start EQU __cpp(CY_FLASH_BASE) +__cy_memory_0_length EQU __cpp(CY_FLASH_SIZE) +__cy_memory_0_row_size EQU 0x200 + + /* Flash region for EEPROM emulation */ +__cy_memory_1_start EQU __cpp(CY_EM_EEPROM_BASE) +__cy_memory_1_length EQU __cpp(CY_EM_EEPROM_SIZE) +__cy_memory_1_row_size EQU 0x200 + + /* Supervisory Flash */ +__cy_memory_2_start EQU __cpp(CY_SFLASH_BASE) +__cy_memory_2_length EQU __cpp(CY_SFLASH_SIZE) +__cy_memory_2_row_size EQU 0x200 + + /* XIP */ +__cy_memory_3_start EQU __cpp(CY_XIP_BASE) +__cy_memory_3_length EQU __cpp(CY_XIP_SIZE) +__cy_memory_3_row_size EQU 0x200 + + /* eFuse */ +__cy_memory_4_start EQU __cpp(0x90700000) +__cy_memory_4_length EQU __cpp(0x100000) +__cy_memory_4_row_size EQU __cpp(1) +} +#endif /* defined (__ARMCC_VERSION) */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/PDL_Version.txt b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/PDL_Version.txt new file mode 100644 index 0000000000..9cac515901 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/PDL_Version.txt @@ -0,0 +1,2 @@ +version 3.0.1 + diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/README.md b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/README.md new file mode 100644 index 0000000000..c1a197bfb5 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/README.md @@ -0,0 +1,5 @@ +README for Cypress Peripheral Driver Library +============================================ + +This folder tree contains parts (binary-only libraries and M0/M4 core specific files) of Cypress Peripheral Driver Library (PDL) necessary to support PSoC 6 MCUs. Library names have been changed (vs. standard PDL version) by prepending a "lib" prefix to fit Mbed OS build system conventions. +See [Cypress PDL page](http://www.cypress.com/documentation/software-and-drivers/peripheral-driver-library-pdl) for details. diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_ARM_STD/cy8c6xx7_cm4_dual.sct b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_ARM_STD/cy8c6xx7_cm4_dual.sct new file mode 100644 index 0000000000..5316a1df7e --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_ARM_STD/cy8c6xx7_cm4_dual.sct @@ -0,0 +1,212 @@ +#! armcc -E +; The first line specifies a preprocessor command that the linker invokes +; to pass a scatter file through a C preprocessor. + +;******************************************************************************* +;* \file cy8c6xx7_cm4_dual.scat +;* \version 2.10 +;* +;* Linker file for the ARMCC. +;* +;* The main purpose of the linker script is to describe how the sections in the +;* input files should be mapped into the output file, and to control the memory +;* layout of the output file. +;* +;* \note The entry point location is fixed and starts at 0x10000000. The valid +;* application image should be placed there. +;* +;* \note The linker files included with the PDL template projects must be +;* generic and handle all common use cases. Your project may not use every +;* section defined in the linker files. In that case you may see the warnings +;* during the build process: L6314W (no section matches pattern) and/or L6329W +;* (pattern only matches removed unused sections). In your project, you can +;* suppress the warning by passing the "--diag_suppress=L6314W,L6329W" option to +;* the linker, simply comment out or remove the relevant code in the linker +;* file. +;* +;******************************************************************************* +;* \copyright +;* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +;* SPDX-License-Identifier: Apache-2.0 +;******************************************************************************/ + +; The defines below describe the location and size of blocks of memory in the target. +; Use these defines to specify the memory regions available for allocation. + +; The following defines control RAM and flash memory allocation for the CM4 core. +; You can change the memory allocation by editing RAM and Flash defines. +; Note that 2 KB of RAM (at the end of the RAM section) are reserved for system use. +; Using this memory region for other purposes will lead to unexpected behavior. +; Your changes must be aligned with the corresponding defines for CM0+ core in 'xx_cm0plus.scat', +; where 'xx' is the device group; for example, 'cy8c6xx7_cm0plus.scat'. +; RAM +; RAM +#define RAM_START 0x08010000 +#define RAM_SIZE 0x00037800 +; Flash +; Flash +#define FLASH_START 0x10080000 +#define FLASH_SIZE 0x00078000 + +; The following defines describe a 32K flash region used for EEPROM emulation. +; This region can also be used as the general purpose flash. +; You can assign sections to this memory region for only one of the cores. +; Note some middleware (e.g. BLE, Emulated EEPROM) can place their data into this memory region. +; Therefore, repurposing this memory region will prevent such middleware from operation. +#define EM_EEPROM_START 0x14000000 +#define EM_EEPROM_SIZE 0x8000 + +; The following defines describe device specific memory regions and must not be changed. +; Supervisory flash: User data +#define SFLASH_USER_DATA_START 0x16000800 +#define SFLASH_USER_DATA_SIZE 0x00000800 + +; Supervisory flash: Normal Access Restrictions (NAR) +#define SFLASH_NAR_START 0x16001A00 +#define SFLASH_NAR_SIZE 0x00000200 + +; Supervisory flash: Public Key +#define SFLASH_PUBLIC_KEY_START 0x16005A00 +#define SFLASH_PUBLIC_KEY_SIZE 0x00000C00 + +; Supervisory flash: Table of Content # 2 +#define SFLASH_TOC_2_START 0x16007C00 +#define SFLASH_TOC_2_SIZE 0x00000200 + +; Supervisory flash: Table of Content # 2 Copy +#define SFLASH_RTOC_2_START 0x16007E00 +#define SFLASH_RTOC_2_SIZE 0x00000200 + +; External memory +#define XIP_START 0x18000000 +#define XIP_SIZE 0x08000000 + +; eFuse +#define EFUSE_START 0x90700000 +#define EFUSE_SIZE 0x100000 + + +LR_IROM1 FLASH_START FLASH_SIZE +{ + ER_FLASH_VECTORS +0 + { + * (RESET, +FIRST) + } + + ER_FLASH_CODE +0 FIXED + { + * (InRoot$$Sections) + * (+RO) + } + + ER_RAM_VECTORS RAM_START UNINIT + { + * (RESET_RAM, +FIRST) + } + + RW_RAM_DATA +0 + { + * (.cy_ramfunc) + .ANY (+RW, +ZI) + } + + ; Place variables in the section that should not be initialized during the + ; device startup. + RW_IRAM1 +0 UNINIT + { + * (.noinit) + } + + ; Used for the digital signature of the secure application and the + ; Bootloader SDK appication. The size of the section depends on the required + ; data size. + .cy_app_signature (FLASH_START + FLASH_SIZE - 256) 256 + { + * (.cy_app_signature) + } +} + + +; Emulated EEPROM Flash area +LR_EM_EEPROM EM_EEPROM_START EM_EEPROM_SIZE +{ + .cy_em_eeprom +0 + { + * (.cy_em_eeprom) + } +} + +; Supervisory flash: User data +LR_SFLASH_USER_DATA SFLASH_USER_DATA_START SFLASH_USER_DATA_SIZE +{ + .cy_sflash_user_data +0 + { + * (.cy_sflash_user_data) + } +} + +; Supervisory flash: Normal Access Restrictions (NAR) +LR_SFLASH_NAR SFLASH_NAR_START SFLASH_NAR_SIZE +{ + .cy_sflash_nar +0 + { + * (.cy_sflash_nar) + } +} + +; Supervisory flash: Public Key +LR_SFLASH_PUBLIC_KEY SFLASH_PUBLIC_KEY_START SFLASH_PUBLIC_KEY_SIZE +{ + .cy_sflash_public_key +0 + { + * (.cy_sflash_public_key) + } +} + +; Supervisory flash: Table of Content # 2 +LR_SFLASH_TOC_2 SFLASH_TOC_2_START SFLASH_TOC_2_SIZE +{ + .cy_toc_part2 +0 + { + * (.cy_toc_part2) + } +} + +; Supervisory flash: Table of Content # 2 Copy +LR_SFLASH_RTOC_2 SFLASH_RTOC_2_START SFLASH_RTOC_2_SIZE +{ + .cy_rtoc_part2 +0 + { + * (.cy_rtoc_part2) + } +} + + +; Places the code in the Execute in Place (XIP) section. See the smif driver documentation for details. +LR_EROM XIP_START XIP_SIZE +{ + .cy_xip +0 + { + * (.cy_xip) + } +} + + +; eFuse +LR_EFUSE EFUSE_START EFUSE_SIZE +{ + .cy_efuse +0 + { + * (.cy_efuse) + } +} + + +; The section is used for additional metadata (silicon revision, Silicon/JTAG ID, etc.) storage. +CYMETA 0x90500000 +{ + .cymeta +0 { * (.cymeta) } +} + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_ARM_STD/startup_psoc63_cm4.S b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_ARM_STD/startup_psoc63_cm4.S new file mode 100644 index 0000000000..c31adadbef --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_ARM_STD/startup_psoc63_cm4.S @@ -0,0 +1,654 @@ +;/**************************************************************************//** +; * @file startup_psoc63_cm4.s +; * @brief CMSIS Core Device Startup File for +; * ARMCM4 Device Series +; * @version V5.00 +; * @date 02. March 2016 +; ******************************************************************************/ +;/* +; * Copyright (c) 2009-2016 ARM Limited. All rights reserved. +; * +; * 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 +; * +; * 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. +; */ + +;/* +;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------ +;*/ + + +__initial_sp EQU 0x08047800 + + PRESERVE8 + THUMB + +; Vector Table Mapped to Address 0 at Reset + + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + + DCD 0x0000000D ; NMI Handler located at ROM code + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External interrupts Power Mode Description + DCD ioss_interrupts_gpio_0_IRQHandler ; GPIO Port Interrupt #0 + DCD ioss_interrupts_gpio_1_IRQHandler ; GPIO Port Interrupt #1 + DCD ioss_interrupts_gpio_2_IRQHandler ; GPIO Port Interrupt #2 + DCD ioss_interrupts_gpio_3_IRQHandler ; GPIO Port Interrupt #3 + DCD ioss_interrupts_gpio_4_IRQHandler ; GPIO Port Interrupt #4 + DCD ioss_interrupts_gpio_5_IRQHandler ; GPIO Port Interrupt #5 + DCD ioss_interrupts_gpio_6_IRQHandler ; GPIO Port Interrupt #6 + DCD ioss_interrupts_gpio_7_IRQHandler ; GPIO Port Interrupt #7 + DCD ioss_interrupts_gpio_8_IRQHandler ; GPIO Port Interrupt #8 + DCD ioss_interrupts_gpio_9_IRQHandler ; GPIO Port Interrupt #9 + DCD ioss_interrupts_gpio_10_IRQHandler ; GPIO Port Interrupt #10 + DCD ioss_interrupts_gpio_11_IRQHandler ; GPIO Port Interrupt #11 + DCD ioss_interrupts_gpio_12_IRQHandler ; GPIO Port Interrupt #12 + DCD ioss_interrupts_gpio_13_IRQHandler ; GPIO Port Interrupt #13 + DCD ioss_interrupts_gpio_14_IRQHandler ; GPIO Port Interrupt #14 + DCD ioss_interrupt_gpio_IRQHandler ; GPIO All Ports + DCD ioss_interrupt_vdd_IRQHandler ; GPIO Supply Detect Interrupt + DCD lpcomp_interrupt_IRQHandler ; Low Power Comparator Interrupt + DCD scb_8_interrupt_IRQHandler ; Serial Communication Block #8 (DeepSleep capable) + DCD srss_interrupt_mcwdt_0_IRQHandler ; Multi Counter Watchdog Timer interrupt + DCD srss_interrupt_mcwdt_1_IRQHandler ; Multi Counter Watchdog Timer interrupt + DCD srss_interrupt_backup_IRQHandler ; Backup domain interrupt + DCD srss_interrupt_IRQHandler ; Other combined Interrupts for SRSS (LVD, WDT, CLKCAL) + DCD pass_interrupt_ctbs_IRQHandler ; CTBm Interrupt (all CTBms) + DCD bless_interrupt_IRQHandler ; Bluetooth Radio interrupt + DCD cpuss_interrupts_ipc_0_IRQHandler ; CPUSS Inter Process Communication Interrupt #0 + DCD cpuss_interrupts_ipc_1_IRQHandler ; CPUSS Inter Process Communication Interrupt #1 + DCD cpuss_interrupts_ipc_2_IRQHandler ; CPUSS Inter Process Communication Interrupt #2 + DCD cpuss_interrupts_ipc_3_IRQHandler ; CPUSS Inter Process Communication Interrupt #3 + DCD cpuss_interrupts_ipc_4_IRQHandler ; CPUSS Inter Process Communication Interrupt #4 + DCD cpuss_interrupts_ipc_5_IRQHandler ; CPUSS Inter Process Communication Interrupt #5 + DCD cpuss_interrupts_ipc_6_IRQHandler ; CPUSS Inter Process Communication Interrupt #6 + DCD cpuss_interrupts_ipc_7_IRQHandler ; CPUSS Inter Process Communication Interrupt #7 + DCD cpuss_interrupts_ipc_8_IRQHandler ; CPUSS Inter Process Communication Interrupt #8 + DCD cpuss_interrupts_ipc_9_IRQHandler ; CPUSS Inter Process Communication Interrupt #9 + DCD cpuss_interrupts_ipc_10_IRQHandler ; CPUSS Inter Process Communication Interrupt #10 + DCD cpuss_interrupts_ipc_11_IRQHandler ; CPUSS Inter Process Communication Interrupt #11 + DCD cpuss_interrupts_ipc_12_IRQHandler ; CPUSS Inter Process Communication Interrupt #12 + DCD cpuss_interrupts_ipc_13_IRQHandler ; CPUSS Inter Process Communication Interrupt #13 + DCD cpuss_interrupts_ipc_14_IRQHandler ; CPUSS Inter Process Communication Interrupt #14 + DCD cpuss_interrupts_ipc_15_IRQHandler ; CPUSS Inter Process Communication Interrupt #15 + DCD scb_0_interrupt_IRQHandler ; Serial Communication Block #0 + DCD scb_1_interrupt_IRQHandler ; Serial Communication Block #1 + DCD scb_2_interrupt_IRQHandler ; Serial Communication Block #2 + DCD scb_3_interrupt_IRQHandler ; Serial Communication Block #3 + DCD scb_4_interrupt_IRQHandler ; Serial Communication Block #4 + DCD scb_5_interrupt_IRQHandler ; Serial Communication Block #5 + DCD scb_6_interrupt_IRQHandler ; Serial Communication Block #6 + DCD scb_7_interrupt_IRQHandler ; Serial Communication Block #7 + DCD csd_interrupt_IRQHandler ; CSD (Capsense) interrupt + DCD cpuss_interrupts_dw0_0_IRQHandler ; CPUSS DataWire #0, Channel #0 + DCD cpuss_interrupts_dw0_1_IRQHandler ; CPUSS DataWire #0, Channel #1 + DCD cpuss_interrupts_dw0_2_IRQHandler ; CPUSS DataWire #0, Channel #2 + DCD cpuss_interrupts_dw0_3_IRQHandler ; CPUSS DataWire #0, Channel #3 + DCD cpuss_interrupts_dw0_4_IRQHandler ; CPUSS DataWire #0, Channel #4 + DCD cpuss_interrupts_dw0_5_IRQHandler ; CPUSS DataWire #0, Channel #5 + DCD cpuss_interrupts_dw0_6_IRQHandler ; CPUSS DataWire #0, Channel #6 + DCD cpuss_interrupts_dw0_7_IRQHandler ; CPUSS DataWire #0, Channel #7 + DCD cpuss_interrupts_dw0_8_IRQHandler ; CPUSS DataWire #0, Channel #8 + DCD cpuss_interrupts_dw0_9_IRQHandler ; CPUSS DataWire #0, Channel #9 + DCD cpuss_interrupts_dw0_10_IRQHandler ; CPUSS DataWire #0, Channel #10 + DCD cpuss_interrupts_dw0_11_IRQHandler ; CPUSS DataWire #0, Channel #11 + DCD cpuss_interrupts_dw0_12_IRQHandler ; CPUSS DataWire #0, Channel #12 + DCD cpuss_interrupts_dw0_13_IRQHandler ; CPUSS DataWire #0, Channel #13 + DCD cpuss_interrupts_dw0_14_IRQHandler ; CPUSS DataWire #0, Channel #14 + DCD cpuss_interrupts_dw0_15_IRQHandler ; CPUSS DataWire #0, Channel #15 + DCD cpuss_interrupts_dw1_0_IRQHandler ; CPUSS DataWire #1, Channel #0 + DCD cpuss_interrupts_dw1_1_IRQHandler ; CPUSS DataWire #1, Channel #1 + DCD cpuss_interrupts_dw1_2_IRQHandler ; CPUSS DataWire #1, Channel #2 + DCD cpuss_interrupts_dw1_3_IRQHandler ; CPUSS DataWire #1, Channel #3 + DCD cpuss_interrupts_dw1_4_IRQHandler ; CPUSS DataWire #1, Channel #4 + DCD cpuss_interrupts_dw1_5_IRQHandler ; CPUSS DataWire #1, Channel #5 + DCD cpuss_interrupts_dw1_6_IRQHandler ; CPUSS DataWire #1, Channel #6 + DCD cpuss_interrupts_dw1_7_IRQHandler ; CPUSS DataWire #1, Channel #7 + DCD cpuss_interrupts_dw1_8_IRQHandler ; CPUSS DataWire #1, Channel #8 + DCD cpuss_interrupts_dw1_9_IRQHandler ; CPUSS DataWire #1, Channel #9 + DCD cpuss_interrupts_dw1_10_IRQHandler ; CPUSS DataWire #1, Channel #10 + DCD cpuss_interrupts_dw1_11_IRQHandler ; CPUSS DataWire #1, Channel #11 + DCD cpuss_interrupts_dw1_12_IRQHandler ; CPUSS DataWire #1, Channel #12 + DCD cpuss_interrupts_dw1_13_IRQHandler ; CPUSS DataWire #1, Channel #13 + DCD cpuss_interrupts_dw1_14_IRQHandler ; CPUSS DataWire #1, Channel #14 + DCD cpuss_interrupts_dw1_15_IRQHandler ; CPUSS DataWire #1, Channel #15 + DCD cpuss_interrupts_fault_0_IRQHandler ; CPUSS Fault Structure Interrupt #0 + DCD cpuss_interrupts_fault_1_IRQHandler ; CPUSS Fault Structure Interrupt #1 + DCD cpuss_interrupt_crypto_IRQHandler ; CRYPTO Accelerator Interrupt + DCD cpuss_interrupt_fm_IRQHandler ; FLASH Macro Interrupt + DCD cpuss_interrupts_cm0_cti_0_IRQHandler ; CM0+ CTI #0 + DCD cpuss_interrupts_cm0_cti_1_IRQHandler ; CM0+ CTI #1 + DCD cpuss_interrupts_cm4_cti_0_IRQHandler ; CM4 CTI #0 + DCD cpuss_interrupts_cm4_cti_1_IRQHandler ; CM4 CTI #1 + DCD tcpwm_0_interrupts_0_IRQHandler ; TCPWM #0, Counter #0 + DCD tcpwm_0_interrupts_1_IRQHandler ; TCPWM #0, Counter #1 + DCD tcpwm_0_interrupts_2_IRQHandler ; TCPWM #0, Counter #2 + DCD tcpwm_0_interrupts_3_IRQHandler ; TCPWM #0, Counter #3 + DCD tcpwm_0_interrupts_4_IRQHandler ; TCPWM #0, Counter #4 + DCD tcpwm_0_interrupts_5_IRQHandler ; TCPWM #0, Counter #5 + DCD tcpwm_0_interrupts_6_IRQHandler ; TCPWM #0, Counter #6 + DCD tcpwm_0_interrupts_7_IRQHandler ; TCPWM #0, Counter #7 + DCD tcpwm_1_interrupts_0_IRQHandler ; TCPWM #1, Counter #0 + DCD tcpwm_1_interrupts_1_IRQHandler ; TCPWM #1, Counter #1 + DCD tcpwm_1_interrupts_2_IRQHandler ; TCPWM #1, Counter #2 + DCD tcpwm_1_interrupts_3_IRQHandler ; TCPWM #1, Counter #3 + DCD tcpwm_1_interrupts_4_IRQHandler ; TCPWM #1, Counter #4 + DCD tcpwm_1_interrupts_5_IRQHandler ; TCPWM #1, Counter #5 + DCD tcpwm_1_interrupts_6_IRQHandler ; TCPWM #1, Counter #6 + DCD tcpwm_1_interrupts_7_IRQHandler ; TCPWM #1, Counter #7 + DCD tcpwm_1_interrupts_8_IRQHandler ; TCPWM #1, Counter #8 + DCD tcpwm_1_interrupts_9_IRQHandler ; TCPWM #1, Counter #9 + DCD tcpwm_1_interrupts_10_IRQHandler ; TCPWM #1, Counter #10 + DCD tcpwm_1_interrupts_11_IRQHandler ; TCPWM #1, Counter #11 + DCD tcpwm_1_interrupts_12_IRQHandler ; TCPWM #1, Counter #12 + DCD tcpwm_1_interrupts_13_IRQHandler ; TCPWM #1, Counter #13 + DCD tcpwm_1_interrupts_14_IRQHandler ; TCPWM #1, Counter #14 + DCD tcpwm_1_interrupts_15_IRQHandler ; TCPWM #1, Counter #15 + DCD tcpwm_1_interrupts_16_IRQHandler ; TCPWM #1, Counter #16 + DCD tcpwm_1_interrupts_17_IRQHandler ; TCPWM #1, Counter #17 + DCD tcpwm_1_interrupts_18_IRQHandler ; TCPWM #1, Counter #18 + DCD tcpwm_1_interrupts_19_IRQHandler ; TCPWM #1, Counter #19 + DCD tcpwm_1_interrupts_20_IRQHandler ; TCPWM #1, Counter #20 + DCD tcpwm_1_interrupts_21_IRQHandler ; TCPWM #1, Counter #21 + DCD tcpwm_1_interrupts_22_IRQHandler ; TCPWM #1, Counter #22 + DCD tcpwm_1_interrupts_23_IRQHandler ; TCPWM #1, Counter #23 + DCD udb_interrupts_0_IRQHandler ; UDB Interrupt #0 + DCD udb_interrupts_1_IRQHandler ; UDB Interrupt #1 + DCD udb_interrupts_2_IRQHandler ; UDB Interrupt #2 + DCD udb_interrupts_3_IRQHandler ; UDB Interrupt #3 + DCD udb_interrupts_4_IRQHandler ; UDB Interrupt #4 + DCD udb_interrupts_5_IRQHandler ; UDB Interrupt #5 + DCD udb_interrupts_6_IRQHandler ; UDB Interrupt #6 + DCD udb_interrupts_7_IRQHandler ; UDB Interrupt #7 + DCD udb_interrupts_8_IRQHandler ; UDB Interrupt #8 + DCD udb_interrupts_9_IRQHandler ; UDB Interrupt #9 + DCD udb_interrupts_10_IRQHandler ; UDB Interrupt #10 + DCD udb_interrupts_11_IRQHandler ; UDB Interrupt #11 + DCD udb_interrupts_12_IRQHandler ; UDB Interrupt #12 + DCD udb_interrupts_13_IRQHandler ; UDB Interrupt #13 + DCD udb_interrupts_14_IRQHandler ; UDB Interrupt #14 + DCD udb_interrupts_15_IRQHandler ; UDB Interrupt #15 + DCD pass_interrupt_sar_IRQHandler ; SAR ADC interrupt + DCD audioss_interrupt_i2s_IRQHandler ; I2S Audio interrupt + DCD audioss_interrupt_pdm_IRQHandler ; PDM/PCM Audio interrupt + DCD profile_interrupt_IRQHandler ; Energy Profiler interrupt + DCD smif_interrupt_IRQHandler ; Serial Memory Interface interrupt + DCD usb_interrupt_hi_IRQHandler ; USB Interrupt + DCD usb_interrupt_med_IRQHandler ; USB Interrupt + DCD usb_interrupt_lo_IRQHandler ; USB Interrupt + DCD pass_interrupt_dacs_IRQHandler ; Consolidated interrrupt for all DACs + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + EXPORT __ramVectors + AREA RESET_RAM, READWRITE, NOINIT +__ramVectors SPACE __Vectors_Size + + + AREA |.text|, CODE, READONLY + + +; Saves and disables the interrupts +Cy_SaveIRQ PROC + EXPORT Cy_SaveIRQ + MRS r0, PRIMASK + CPSID I + BX LR + ENDP + + +; Restores the interrupts +Cy_RestoreIRQ PROC + EXPORT Cy_RestoreIRQ + MSR PRIMASK, r0 + BX LR + ENDP + + +; Weak function for startup customization +Cy_OnResetUser PROC + EXPORT Cy_OnResetUser [WEAK] + BX LR + ENDP + + +; Reset Handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT Cy_SystemInitFpuEnable + IMPORT __main + + ; Define strong function for startup customization + BL Cy_OnResetUser + + ; Copy vectors from ROM to RAM + LDR r1, =__Vectors + LDR r0, =__ramVectors + LDR r2, =__Vectors_Size +Vectors_Copy + LDR r3, [r1] + STR r3, [r0] + ADDS r0, r0, #4 + ADDS r1, r1, #4 + SUBS r2, r2, #1 + CMP r2, #0 + BNE Vectors_Copy + + ; Update Vector Table Offset Register. */ + LDR r0, =__ramVectors + LDR r1, =0xE000ED08 + STR r0, [r1] + dsb 0xF + + ; Enable the FPU if used + LDR R0, =Cy_SystemInitFpuEnable + BLX R0 + + LDR R0, =__main + BLX R0 + + ; Should never get here + B . + + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP + +Cy_SysLib_FaultHandler PROC + EXPORT Cy_SysLib_FaultHandler [WEAK] + B . + ENDP +HardFault_Wrapper\ + PROC + EXPORT HardFault_Wrapper [WEAK] + movs r0, #4 + mov r1, LR + tst r0, r1 + beq L_MSP + mrs r0, PSP + bl L_API_call +L_MSP + mrs r0, MSP +L_API_call + bl Cy_SysLib_FaultHandler + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B HardFault_Wrapper + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B HardFault_Wrapper + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B HardFault_Wrapper + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B HardFault_Wrapper + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + EXPORT Default_Handler [WEAK] + EXPORT ioss_interrupts_gpio_0_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_1_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_2_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_3_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_4_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_5_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_6_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_7_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_8_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_9_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_10_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_11_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_12_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_13_IRQHandler [WEAK] + EXPORT ioss_interrupts_gpio_14_IRQHandler [WEAK] + EXPORT ioss_interrupt_gpio_IRQHandler [WEAK] + EXPORT ioss_interrupt_vdd_IRQHandler [WEAK] + EXPORT lpcomp_interrupt_IRQHandler [WEAK] + EXPORT scb_8_interrupt_IRQHandler [WEAK] + EXPORT srss_interrupt_mcwdt_0_IRQHandler [WEAK] + EXPORT srss_interrupt_mcwdt_1_IRQHandler [WEAK] + EXPORT srss_interrupt_backup_IRQHandler [WEAK] + EXPORT srss_interrupt_IRQHandler [WEAK] + EXPORT pass_interrupt_ctbs_IRQHandler [WEAK] + EXPORT bless_interrupt_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_0_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_1_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_2_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_3_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_4_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_5_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_6_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_7_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_8_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_9_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_10_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_11_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_12_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_13_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_14_IRQHandler [WEAK] + EXPORT cpuss_interrupts_ipc_15_IRQHandler [WEAK] + EXPORT scb_0_interrupt_IRQHandler [WEAK] + EXPORT scb_1_interrupt_IRQHandler [WEAK] + EXPORT scb_2_interrupt_IRQHandler [WEAK] + EXPORT scb_3_interrupt_IRQHandler [WEAK] + EXPORT scb_4_interrupt_IRQHandler [WEAK] + EXPORT scb_5_interrupt_IRQHandler [WEAK] + EXPORT scb_6_interrupt_IRQHandler [WEAK] + EXPORT scb_7_interrupt_IRQHandler [WEAK] + EXPORT csd_interrupt_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_0_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_1_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_2_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_3_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_4_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_5_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_6_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_7_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_8_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_9_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_10_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_11_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_12_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_13_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_14_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw0_15_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_0_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_1_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_2_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_3_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_4_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_5_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_6_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_7_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_8_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_9_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_10_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_11_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_12_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_13_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_14_IRQHandler [WEAK] + EXPORT cpuss_interrupts_dw1_15_IRQHandler [WEAK] + EXPORT cpuss_interrupts_fault_0_IRQHandler [WEAK] + EXPORT cpuss_interrupts_fault_1_IRQHandler [WEAK] + EXPORT cpuss_interrupt_crypto_IRQHandler [WEAK] + EXPORT cpuss_interrupt_fm_IRQHandler [WEAK] + EXPORT cpuss_interrupts_cm0_cti_0_IRQHandler [WEAK] + EXPORT cpuss_interrupts_cm0_cti_1_IRQHandler [WEAK] + EXPORT cpuss_interrupts_cm4_cti_0_IRQHandler [WEAK] + EXPORT cpuss_interrupts_cm4_cti_1_IRQHandler [WEAK] + EXPORT tcpwm_0_interrupts_0_IRQHandler [WEAK] + EXPORT tcpwm_0_interrupts_1_IRQHandler [WEAK] + EXPORT tcpwm_0_interrupts_2_IRQHandler [WEAK] + EXPORT tcpwm_0_interrupts_3_IRQHandler [WEAK] + EXPORT tcpwm_0_interrupts_4_IRQHandler [WEAK] + EXPORT tcpwm_0_interrupts_5_IRQHandler [WEAK] + EXPORT tcpwm_0_interrupts_6_IRQHandler [WEAK] + EXPORT tcpwm_0_interrupts_7_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_0_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_1_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_2_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_3_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_4_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_5_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_6_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_7_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_8_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_9_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_10_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_11_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_12_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_13_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_14_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_15_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_16_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_17_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_18_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_19_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_20_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_21_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_22_IRQHandler [WEAK] + EXPORT tcpwm_1_interrupts_23_IRQHandler [WEAK] + EXPORT udb_interrupts_0_IRQHandler [WEAK] + EXPORT udb_interrupts_1_IRQHandler [WEAK] + EXPORT udb_interrupts_2_IRQHandler [WEAK] + EXPORT udb_interrupts_3_IRQHandler [WEAK] + EXPORT udb_interrupts_4_IRQHandler [WEAK] + EXPORT udb_interrupts_5_IRQHandler [WEAK] + EXPORT udb_interrupts_6_IRQHandler [WEAK] + EXPORT udb_interrupts_7_IRQHandler [WEAK] + EXPORT udb_interrupts_8_IRQHandler [WEAK] + EXPORT udb_interrupts_9_IRQHandler [WEAK] + EXPORT udb_interrupts_10_IRQHandler [WEAK] + EXPORT udb_interrupts_11_IRQHandler [WEAK] + EXPORT udb_interrupts_12_IRQHandler [WEAK] + EXPORT udb_interrupts_13_IRQHandler [WEAK] + EXPORT udb_interrupts_14_IRQHandler [WEAK] + EXPORT udb_interrupts_15_IRQHandler [WEAK] + EXPORT pass_interrupt_sar_IRQHandler [WEAK] + EXPORT audioss_interrupt_i2s_IRQHandler [WEAK] + EXPORT audioss_interrupt_pdm_IRQHandler [WEAK] + EXPORT profile_interrupt_IRQHandler [WEAK] + EXPORT smif_interrupt_IRQHandler [WEAK] + EXPORT usb_interrupt_hi_IRQHandler [WEAK] + EXPORT usb_interrupt_med_IRQHandler [WEAK] + EXPORT usb_interrupt_lo_IRQHandler [WEAK] + EXPORT pass_interrupt_dacs_IRQHandler [WEAK] + +ioss_interrupts_gpio_0_IRQHandler +ioss_interrupts_gpio_1_IRQHandler +ioss_interrupts_gpio_2_IRQHandler +ioss_interrupts_gpio_3_IRQHandler +ioss_interrupts_gpio_4_IRQHandler +ioss_interrupts_gpio_5_IRQHandler +ioss_interrupts_gpio_6_IRQHandler +ioss_interrupts_gpio_7_IRQHandler +ioss_interrupts_gpio_8_IRQHandler +ioss_interrupts_gpio_9_IRQHandler +ioss_interrupts_gpio_10_IRQHandler +ioss_interrupts_gpio_11_IRQHandler +ioss_interrupts_gpio_12_IRQHandler +ioss_interrupts_gpio_13_IRQHandler +ioss_interrupts_gpio_14_IRQHandler +ioss_interrupt_gpio_IRQHandler +ioss_interrupt_vdd_IRQHandler +lpcomp_interrupt_IRQHandler +scb_8_interrupt_IRQHandler +srss_interrupt_mcwdt_0_IRQHandler +srss_interrupt_mcwdt_1_IRQHandler +srss_interrupt_backup_IRQHandler +srss_interrupt_IRQHandler +pass_interrupt_ctbs_IRQHandler +bless_interrupt_IRQHandler +cpuss_interrupts_ipc_0_IRQHandler +cpuss_interrupts_ipc_1_IRQHandler +cpuss_interrupts_ipc_2_IRQHandler +cpuss_interrupts_ipc_3_IRQHandler +cpuss_interrupts_ipc_4_IRQHandler +cpuss_interrupts_ipc_5_IRQHandler +cpuss_interrupts_ipc_6_IRQHandler +cpuss_interrupts_ipc_7_IRQHandler +cpuss_interrupts_ipc_8_IRQHandler +cpuss_interrupts_ipc_9_IRQHandler +cpuss_interrupts_ipc_10_IRQHandler +cpuss_interrupts_ipc_11_IRQHandler +cpuss_interrupts_ipc_12_IRQHandler +cpuss_interrupts_ipc_13_IRQHandler +cpuss_interrupts_ipc_14_IRQHandler +cpuss_interrupts_ipc_15_IRQHandler +scb_0_interrupt_IRQHandler +scb_1_interrupt_IRQHandler +scb_2_interrupt_IRQHandler +scb_3_interrupt_IRQHandler +scb_4_interrupt_IRQHandler +scb_5_interrupt_IRQHandler +scb_6_interrupt_IRQHandler +scb_7_interrupt_IRQHandler +csd_interrupt_IRQHandler +cpuss_interrupts_dw0_0_IRQHandler +cpuss_interrupts_dw0_1_IRQHandler +cpuss_interrupts_dw0_2_IRQHandler +cpuss_interrupts_dw0_3_IRQHandler +cpuss_interrupts_dw0_4_IRQHandler +cpuss_interrupts_dw0_5_IRQHandler +cpuss_interrupts_dw0_6_IRQHandler +cpuss_interrupts_dw0_7_IRQHandler +cpuss_interrupts_dw0_8_IRQHandler +cpuss_interrupts_dw0_9_IRQHandler +cpuss_interrupts_dw0_10_IRQHandler +cpuss_interrupts_dw0_11_IRQHandler +cpuss_interrupts_dw0_12_IRQHandler +cpuss_interrupts_dw0_13_IRQHandler +cpuss_interrupts_dw0_14_IRQHandler +cpuss_interrupts_dw0_15_IRQHandler +cpuss_interrupts_dw1_0_IRQHandler +cpuss_interrupts_dw1_1_IRQHandler +cpuss_interrupts_dw1_2_IRQHandler +cpuss_interrupts_dw1_3_IRQHandler +cpuss_interrupts_dw1_4_IRQHandler +cpuss_interrupts_dw1_5_IRQHandler +cpuss_interrupts_dw1_6_IRQHandler +cpuss_interrupts_dw1_7_IRQHandler +cpuss_interrupts_dw1_8_IRQHandler +cpuss_interrupts_dw1_9_IRQHandler +cpuss_interrupts_dw1_10_IRQHandler +cpuss_interrupts_dw1_11_IRQHandler +cpuss_interrupts_dw1_12_IRQHandler +cpuss_interrupts_dw1_13_IRQHandler +cpuss_interrupts_dw1_14_IRQHandler +cpuss_interrupts_dw1_15_IRQHandler +cpuss_interrupts_fault_0_IRQHandler +cpuss_interrupts_fault_1_IRQHandler +cpuss_interrupt_crypto_IRQHandler +cpuss_interrupt_fm_IRQHandler +cpuss_interrupts_cm0_cti_0_IRQHandler +cpuss_interrupts_cm0_cti_1_IRQHandler +cpuss_interrupts_cm4_cti_0_IRQHandler +cpuss_interrupts_cm4_cti_1_IRQHandler +tcpwm_0_interrupts_0_IRQHandler +tcpwm_0_interrupts_1_IRQHandler +tcpwm_0_interrupts_2_IRQHandler +tcpwm_0_interrupts_3_IRQHandler +tcpwm_0_interrupts_4_IRQHandler +tcpwm_0_interrupts_5_IRQHandler +tcpwm_0_interrupts_6_IRQHandler +tcpwm_0_interrupts_7_IRQHandler +tcpwm_1_interrupts_0_IRQHandler +tcpwm_1_interrupts_1_IRQHandler +tcpwm_1_interrupts_2_IRQHandler +tcpwm_1_interrupts_3_IRQHandler +tcpwm_1_interrupts_4_IRQHandler +tcpwm_1_interrupts_5_IRQHandler +tcpwm_1_interrupts_6_IRQHandler +tcpwm_1_interrupts_7_IRQHandler +tcpwm_1_interrupts_8_IRQHandler +tcpwm_1_interrupts_9_IRQHandler +tcpwm_1_interrupts_10_IRQHandler +tcpwm_1_interrupts_11_IRQHandler +tcpwm_1_interrupts_12_IRQHandler +tcpwm_1_interrupts_13_IRQHandler +tcpwm_1_interrupts_14_IRQHandler +tcpwm_1_interrupts_15_IRQHandler +tcpwm_1_interrupts_16_IRQHandler +tcpwm_1_interrupts_17_IRQHandler +tcpwm_1_interrupts_18_IRQHandler +tcpwm_1_interrupts_19_IRQHandler +tcpwm_1_interrupts_20_IRQHandler +tcpwm_1_interrupts_21_IRQHandler +tcpwm_1_interrupts_22_IRQHandler +tcpwm_1_interrupts_23_IRQHandler +udb_interrupts_0_IRQHandler +udb_interrupts_1_IRQHandler +udb_interrupts_2_IRQHandler +udb_interrupts_3_IRQHandler +udb_interrupts_4_IRQHandler +udb_interrupts_5_IRQHandler +udb_interrupts_6_IRQHandler +udb_interrupts_7_IRQHandler +udb_interrupts_8_IRQHandler +udb_interrupts_9_IRQHandler +udb_interrupts_10_IRQHandler +udb_interrupts_11_IRQHandler +udb_interrupts_12_IRQHandler +udb_interrupts_13_IRQHandler +udb_interrupts_14_IRQHandler +udb_interrupts_15_IRQHandler +pass_interrupt_sar_IRQHandler +audioss_interrupt_i2s_IRQHandler +audioss_interrupt_pdm_IRQHandler +profile_interrupt_IRQHandler +smif_interrupt_IRQHandler +usb_interrupt_hi_IRQHandler +usb_interrupt_med_IRQHandler +usb_interrupt_lo_IRQHandler +pass_interrupt_dacs_IRQHandler + + B . + ENDP + + ALIGN + + END + + +; [] END OF FILE diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_GCC_ARM/cy8c6xx7_cm4_dual.ld b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_GCC_ARM/cy8c6xx7_cm4_dual.ld new file mode 100644 index 0000000000..0ecc9d77ce --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_GCC_ARM/cy8c6xx7_cm4_dual.ld @@ -0,0 +1,399 @@ +/***************************************************************************//** +* \file cy8c6xx7_cm4_dual.ld +* \version 2.10 +* +* Linker file for the GNU C compiler. +* +* The main purpose of the linker script is to describe how the sections in the +* input files should be mapped into the output file, and to control the memory +* layout of the output file. +* +* \note The entry point location is fixed and starts at 0x10000000. The valid +* application image should be placed there. +* +* \note The linker files included with the PDL template projects must be generic +* and handle all common use cases. Your project may not use every section +* defined in the linker files. In that case you may see warnings during the +* build process. In your project, you can simply comment out or remove the +* relevant code in the linker file. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) +ENTRY(Reset_Handler) + + +/* Force symbol to be entered in the output file as an undefined symbol. Doing +* this may, for example, trigger linking of additional modules from standard +* libraries. You may list several symbols for each EXTERN, and you may use +* EXTERN multiple times. This command has the same effect as the -u command-line +* option. +*/ +EXTERN(Reset_Handler) + +/* The MEMORY section below describes the location and size of blocks of memory in the target. +* Use this section to specify the memory regions available for allocation. +*/ +MEMORY +{ + /* The ram and flash regions control RAM and flash memory allocation for the CM4 core. + * You can change the memory allocation by editing the 'ram' and 'flash' regions. + * Note that 2 KB of RAM (at the end of the RAM section) are reserved for system use. + * Using this memory region for other purposes will lead to unexpected behavior. + * Your changes must be aligned with the corresponding memory regions for CM0+ core in 'xx_cm0plus.ld', + * where 'xx' is the device group; for example, 'cy8c6xx7_cm0plus.ld'. + */ + ram (rwx) : ORIGIN = 0x08010000, LENGTH = 0x37800 + flash (rx) : ORIGIN = 0x10080000, LENGTH = 0x78000 + + /* This is a 32K flash region used for EEPROM emulation. This region can also be used as the general purpose flash. + * You can assign sections to this memory region for only one of the cores. + * Note some middleware (e.g. BLE, Emulated EEPROM) can place their data into this memory region. + * Therefore, repurposing this memory region will prevent such middleware from operation. + */ + em_eeprom (rx) : ORIGIN = 0x14000000, LENGTH = 0x8000 /* 32 KB */ + + /* The following regions define device specific memory regions and must not be changed. */ + sflash_user_data (rx) : ORIGIN = 0x16000800, LENGTH = 0x800 /* Supervisory flash: User data */ + sflash_nar (rx) : ORIGIN = 0x16001A00, LENGTH = 0x200 /* Supervisory flash: Normal Access Restrictions (NAR) */ + sflash_public_key (rx) : ORIGIN = 0x16005A00, LENGTH = 0xC00 /* Supervisory flash: Public Key */ + sflash_toc_2 (rx) : ORIGIN = 0x16007C00, LENGTH = 0x200 /* Supervisory flash: Table of Content # 2 */ + sflash_rtoc_2 (rx) : ORIGIN = 0x16007E00, LENGTH = 0x200 /* Supervisory flash: Table of Content # 2 Copy */ + xip (rx) : ORIGIN = 0x18000000, LENGTH = 0x8000000 /* 128 MB */ + efuse (r) : ORIGIN = 0x90700000, LENGTH = 0x100000 /* 1 MB */ +} + +/* Library configurations */ +GROUP(libgcc.a libc.a libm.a libnosys.a) + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + * __Vectors_End + * __Vectors_Size + */ + + +SECTIONS +{ + .text : + { + . = ALIGN(4); + __Vectors = . ; + KEEP(*(.vectors)) + . = ALIGN(4); + __Vectors_End = .; + __Vectors_Size = __Vectors_End - __Vectors; + __end__ = .; + + . = ALIGN(4); + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + /* Read-only code (constants). */ + *(.rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + + KEEP(*(.eh_frame*)) + + /* To copy multiple ROM to RAM sections, + * uncomment copy table section and, + * define __STARTUP_COPY_MULTIPLE in startup_psoc63_cm4.S */ + . = ALIGN(4); + __copy_table_start__ = .; + + /* Copy interrupt vectors from flash to RAM */ + LONG (__Vectors) /* From */ + LONG (__ram_vectors_start__) /* To */ + LONG (__Vectors_End - __Vectors) /* Size */ + + /* Copy data section to RAM */ + LONG (__etext) /* From */ + LONG (__data_start__) /* To */ + LONG (__data_end__ - __data_start__) /* Size */ + + __copy_table_end__ = .; + + /* To clear multiple BSS sections, + * uncomment zero table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_psoc63_cm4.S */ + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + __zero_table_end__ = .; + + } > flash + + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > flash + + __exidx_start = .; + + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > flash + __exidx_end = .; + + __etext = . ; + + + .ramVectors (NOLOAD) : ALIGN(8) + { + __ram_vectors_start__ = .; + KEEP(*(.ram_vectors)) + __ram_vectors_end__ = .; + } > ram + + + .data __ram_vectors_end__ : AT (__etext) + { + __data_start__ = .; + + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + + KEEP(*(.cy_ramfunc*)) + . = ALIGN(4); + + __data_end__ = .; + + } > ram + + + /* Place variables in the section that should not be initialized during the + * device startup. + */ + .noinit (NOLOAD) : ALIGN(8) + { + KEEP(*(.noinit)) + } > ram + + + /* The uninitialized global or static variables are placed in this section. + * + * The NOLOAD attribute tells linker that .bss section does not consume + * any space in the image. The NOLOAD attribute changes the .bss type to + * NOBITS, and that makes linker to A) not allocate section in memory, and + * A) put information to clear the section with all zeros during application + * loading. + * + * Without the NOLOAD attribute, the .bss section might get PROGBITS type. + * This makes linker to A) allocate zeroed section in memory, and B) copy + * this section to RAM during application loading. + */ + .bss (NOLOAD): + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > ram + + + .heap (NOLOAD): + { + __HeapBase = .; + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + __HeapLimit = .; + } > ram + + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > ram + + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(ram) + LENGTH(ram); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + + + /* Used for the digital signature of the secure application and the Bootloader SDK appication. + * The size of the section depends on the required data size. */ + .cy_app_signature ORIGIN(flash) + LENGTH(flash) - 256 : + { + KEEP(*(.cy_app_signature)) + } > flash + + + /* Emulated EEPROM Flash area */ + .cy_em_eeprom : + { + KEEP(*(.cy_em_eeprom)) + } > em_eeprom + + + /* Supervisory Flash: User data */ + .cy_sflash_user_data : + { + KEEP(*(.cy_sflash_user_data)) + } > sflash_user_data + + + /* Supervisory Flash: Normal Access Restrictions (NAR) */ + .cy_sflash_nar : + { + KEEP(*(.cy_sflash_nar)) + } > sflash_nar + + + /* Supervisory Flash: Public Key */ + .cy_sflash_public_key : + { + KEEP(*(.cy_sflash_public_key)) + } > sflash_public_key + + + /* Supervisory Flash: Table of Content # 2 */ + .cy_toc_part2 : + { + KEEP(*(.cy_toc_part2)) + } > sflash_toc_2 + + + /* Supervisory Flash: Table of Content # 2 Copy */ + .cy_rtoc_part2 : + { + KEEP(*(.cy_rtoc_part2)) + } > sflash_rtoc_2 + + + /* Places the code in the Execute in Place (XIP) section. See the smif driver + * documentation for details. + */ + .cy_xip : + { + KEEP(*(.cy_xip)) + } > xip + + + /* eFuse */ + .cy_efuse : + { + KEEP(*(.cy_efuse)) + } > efuse + + + /* These sections are used for additional metadata (silicon revision, + * Silicon/JTAG ID, etc.) storage. + */ + .cymeta 0x90500000 : { KEEP(*(.cymeta)) } :NONE +} + + +/* The following symbols used by the cymcuelftool. */ +/* Flash */ +__cy_memory_0_start = 0x10000000; +__cy_memory_0_length = 0x00100000; +__cy_memory_0_row_size = 0x200; + +/* Emulated EEPROM Flash area */ +__cy_memory_1_start = 0x14000000; +__cy_memory_1_length = 0x8000; +__cy_memory_1_row_size = 0x200; + +/* Supervisory Flash */ +__cy_memory_2_start = 0x16000000; +__cy_memory_2_length = 0x8000; +__cy_memory_2_row_size = 0x200; + +/* XIP */ +__cy_memory_3_start = 0x18000000; +__cy_memory_3_length = 0x08000000; +__cy_memory_3_row_size = 0x200; + +/* eFuse */ +__cy_memory_4_start = 0x90700000; +__cy_memory_4_length = 0x100000; +__cy_memory_4_row_size = 1; + +/* EOF */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_GCC_ARM/startup_psoc63_cm4.S b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_GCC_ARM/startup_psoc63_cm4.S new file mode 100644 index 0000000000..6deba77053 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_GCC_ARM/startup_psoc63_cm4.S @@ -0,0 +1,641 @@ +/**************************************************************************//** + * @file startup_psoc63_cm4.s + * @brief CMSIS Core Device Startup File for + * ARMCM4 Device Series + * @version V5.00 + * @date 02. March 2016 + ******************************************************************************/ +/* + * Copyright (c) 2009-2016 ARM Limited. All rights reserved. + * + * 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 + * + * 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. + */ + + /* Address of the NMI handler */ + #define CY_NMI_HANLDER_ADDR 0x0000000D + + /* The CPU VTOR register */ + #define CY_CPU_VTOR_ADDR 0xE000ED08 + + /* Copy flash vectors and data section to RAM */ + #define __STARTUP_COPY_MULTIPLE + + /* Clear single BSS section */ + #define __STARTUP_CLEAR_BSS + + .syntax unified + .arch armv7-m + + .section .stack + .align 3 +#ifdef __STACK_SIZE + .equ Stack_Size, __STACK_SIZE +#else + .equ Stack_Size, 0x00001000 +#endif + .globl __StackTop + .globl __StackLimit +__StackLimit: + .space Stack_Size + .size __StackLimit, . - __StackLimit +__StackTop: + .size __StackTop, . - __StackTop + + .section .heap + .align 3 +#ifdef __HEAP_SIZE + .equ Heap_Size, __HEAP_SIZE +#else + .equ Heap_Size, 0x00000400 +#endif + .globl __HeapBase + .globl __HeapLimit +__HeapBase: + .if Heap_Size + .space Heap_Size + .endif + .size __HeapBase, . - __HeapBase +__HeapLimit: + .size __HeapLimit, . - __HeapLimit + + .section .vectors + .align 2 + .globl __Vectors +__Vectors: + .long __StackTop /* Top of Stack */ + .long Reset_Handler /* Reset Handler */ + .long CY_NMI_HANLDER_ADDR /* NMI Handler */ + .long HardFault_Handler /* Hard Fault Handler */ + .long MemManage_Handler /* MPU Fault Handler */ + .long BusFault_Handler /* Bus Fault Handler */ + .long UsageFault_Handler /* Usage Fault Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long SVC_Handler /* SVCall Handler */ + .long DebugMon_Handler /* Debug Monitor Handler */ + .long 0 /* Reserved */ + .long PendSV_Handler /* PendSV Handler */ + .long SysTick_Handler /* SysTick Handler */ + + /* External interrupts Description */ + .long ioss_interrupts_gpio_0_IRQHandler /* GPIO Port Interrupt #0 */ + .long ioss_interrupts_gpio_1_IRQHandler /* GPIO Port Interrupt #1 */ + .long ioss_interrupts_gpio_2_IRQHandler /* GPIO Port Interrupt #2 */ + .long ioss_interrupts_gpio_3_IRQHandler /* GPIO Port Interrupt #3 */ + .long ioss_interrupts_gpio_4_IRQHandler /* GPIO Port Interrupt #4 */ + .long ioss_interrupts_gpio_5_IRQHandler /* GPIO Port Interrupt #5 */ + .long ioss_interrupts_gpio_6_IRQHandler /* GPIO Port Interrupt #6 */ + .long ioss_interrupts_gpio_7_IRQHandler /* GPIO Port Interrupt #7 */ + .long ioss_interrupts_gpio_8_IRQHandler /* GPIO Port Interrupt #8 */ + .long ioss_interrupts_gpio_9_IRQHandler /* GPIO Port Interrupt #9 */ + .long ioss_interrupts_gpio_10_IRQHandler /* GPIO Port Interrupt #10 */ + .long ioss_interrupts_gpio_11_IRQHandler /* GPIO Port Interrupt #11 */ + .long ioss_interrupts_gpio_12_IRQHandler /* GPIO Port Interrupt #12 */ + .long ioss_interrupts_gpio_13_IRQHandler /* GPIO Port Interrupt #13 */ + .long ioss_interrupts_gpio_14_IRQHandler /* GPIO Port Interrupt #14 */ + .long ioss_interrupt_gpio_IRQHandler /* GPIO All Ports */ + .long ioss_interrupt_vdd_IRQHandler /* GPIO Supply Detect Interrupt */ + .long lpcomp_interrupt_IRQHandler /* Low Power Comparator Interrupt */ + .long scb_8_interrupt_IRQHandler /* Serial Communication Block #8 (DeepSleep capable) */ + .long srss_interrupt_mcwdt_0_IRQHandler /* Multi Counter Watchdog Timer interrupt */ + .long srss_interrupt_mcwdt_1_IRQHandler /* Multi Counter Watchdog Timer interrupt */ + .long srss_interrupt_backup_IRQHandler /* Backup domain interrupt */ + .long srss_interrupt_IRQHandler /* Other combined Interrupts for SRSS (LVD, WDT, CLKCAL) */ + .long pass_interrupt_ctbs_IRQHandler /* CTBm Interrupt (all CTBms) */ + .long bless_interrupt_IRQHandler /* Bluetooth Radio interrupt */ + .long cpuss_interrupts_ipc_0_IRQHandler /* CPUSS Inter Process Communication Interrupt #0 */ + .long cpuss_interrupts_ipc_1_IRQHandler /* CPUSS Inter Process Communication Interrupt #1 */ + .long cpuss_interrupts_ipc_2_IRQHandler /* CPUSS Inter Process Communication Interrupt #2 */ + .long cpuss_interrupts_ipc_3_IRQHandler /* CPUSS Inter Process Communication Interrupt #3 */ + .long cpuss_interrupts_ipc_4_IRQHandler /* CPUSS Inter Process Communication Interrupt #4 */ + .long cpuss_interrupts_ipc_5_IRQHandler /* CPUSS Inter Process Communication Interrupt #5 */ + .long cpuss_interrupts_ipc_6_IRQHandler /* CPUSS Inter Process Communication Interrupt #6 */ + .long cpuss_interrupts_ipc_7_IRQHandler /* CPUSS Inter Process Communication Interrupt #7 */ + .long cpuss_interrupts_ipc_8_IRQHandler /* CPUSS Inter Process Communication Interrupt #8 */ + .long cpuss_interrupts_ipc_9_IRQHandler /* CPUSS Inter Process Communication Interrupt #9 */ + .long cpuss_interrupts_ipc_10_IRQHandler /* CPUSS Inter Process Communication Interrupt #10 */ + .long cpuss_interrupts_ipc_11_IRQHandler /* CPUSS Inter Process Communication Interrupt #11 */ + .long cpuss_interrupts_ipc_12_IRQHandler /* CPUSS Inter Process Communication Interrupt #12 */ + .long cpuss_interrupts_ipc_13_IRQHandler /* CPUSS Inter Process Communication Interrupt #13 */ + .long cpuss_interrupts_ipc_14_IRQHandler /* CPUSS Inter Process Communication Interrupt #14 */ + .long cpuss_interrupts_ipc_15_IRQHandler /* CPUSS Inter Process Communication Interrupt #15 */ + .long scb_0_interrupt_IRQHandler /* Serial Communication Block #0 */ + .long scb_1_interrupt_IRQHandler /* Serial Communication Block #1 */ + .long scb_2_interrupt_IRQHandler /* Serial Communication Block #2 */ + .long scb_3_interrupt_IRQHandler /* Serial Communication Block #3 */ + .long scb_4_interrupt_IRQHandler /* Serial Communication Block #4 */ + .long scb_5_interrupt_IRQHandler /* Serial Communication Block #5 */ + .long scb_6_interrupt_IRQHandler /* Serial Communication Block #6 */ + .long scb_7_interrupt_IRQHandler /* Serial Communication Block #7 */ + .long csd_interrupt_IRQHandler /* CSD (Capsense) interrupt */ + .long cpuss_interrupts_dw0_0_IRQHandler /* CPUSS DataWire #0, Channel #0 */ + .long cpuss_interrupts_dw0_1_IRQHandler /* CPUSS DataWire #0, Channel #1 */ + .long cpuss_interrupts_dw0_2_IRQHandler /* CPUSS DataWire #0, Channel #2 */ + .long cpuss_interrupts_dw0_3_IRQHandler /* CPUSS DataWire #0, Channel #3 */ + .long cpuss_interrupts_dw0_4_IRQHandler /* CPUSS DataWire #0, Channel #4 */ + .long cpuss_interrupts_dw0_5_IRQHandler /* CPUSS DataWire #0, Channel #5 */ + .long cpuss_interrupts_dw0_6_IRQHandler /* CPUSS DataWire #0, Channel #6 */ + .long cpuss_interrupts_dw0_7_IRQHandler /* CPUSS DataWire #0, Channel #7 */ + .long cpuss_interrupts_dw0_8_IRQHandler /* CPUSS DataWire #0, Channel #8 */ + .long cpuss_interrupts_dw0_9_IRQHandler /* CPUSS DataWire #0, Channel #9 */ + .long cpuss_interrupts_dw0_10_IRQHandler /* CPUSS DataWire #0, Channel #10 */ + .long cpuss_interrupts_dw0_11_IRQHandler /* CPUSS DataWire #0, Channel #11 */ + .long cpuss_interrupts_dw0_12_IRQHandler /* CPUSS DataWire #0, Channel #12 */ + .long cpuss_interrupts_dw0_13_IRQHandler /* CPUSS DataWire #0, Channel #13 */ + .long cpuss_interrupts_dw0_14_IRQHandler /* CPUSS DataWire #0, Channel #14 */ + .long cpuss_interrupts_dw0_15_IRQHandler /* CPUSS DataWire #0, Channel #15 */ + .long cpuss_interrupts_dw1_0_IRQHandler /* CPUSS DataWire #1, Channel #0 */ + .long cpuss_interrupts_dw1_1_IRQHandler /* CPUSS DataWire #1, Channel #1 */ + .long cpuss_interrupts_dw1_2_IRQHandler /* CPUSS DataWire #1, Channel #2 */ + .long cpuss_interrupts_dw1_3_IRQHandler /* CPUSS DataWire #1, Channel #3 */ + .long cpuss_interrupts_dw1_4_IRQHandler /* CPUSS DataWire #1, Channel #4 */ + .long cpuss_interrupts_dw1_5_IRQHandler /* CPUSS DataWire #1, Channel #5 */ + .long cpuss_interrupts_dw1_6_IRQHandler /* CPUSS DataWire #1, Channel #6 */ + .long cpuss_interrupts_dw1_7_IRQHandler /* CPUSS DataWire #1, Channel #7 */ + .long cpuss_interrupts_dw1_8_IRQHandler /* CPUSS DataWire #1, Channel #8 */ + .long cpuss_interrupts_dw1_9_IRQHandler /* CPUSS DataWire #1, Channel #9 */ + .long cpuss_interrupts_dw1_10_IRQHandler /* CPUSS DataWire #1, Channel #10 */ + .long cpuss_interrupts_dw1_11_IRQHandler /* CPUSS DataWire #1, Channel #11 */ + .long cpuss_interrupts_dw1_12_IRQHandler /* CPUSS DataWire #1, Channel #12 */ + .long cpuss_interrupts_dw1_13_IRQHandler /* CPUSS DataWire #1, Channel #13 */ + .long cpuss_interrupts_dw1_14_IRQHandler /* CPUSS DataWire #1, Channel #14 */ + .long cpuss_interrupts_dw1_15_IRQHandler /* CPUSS DataWire #1, Channel #15 */ + .long cpuss_interrupts_fault_0_IRQHandler /* CPUSS Fault Structure Interrupt #0 */ + .long cpuss_interrupts_fault_1_IRQHandler /* CPUSS Fault Structure Interrupt #1 */ + .long cpuss_interrupt_crypto_IRQHandler /* CRYPTO Accelerator Interrupt */ + .long cpuss_interrupt_fm_IRQHandler /* FLASH Macro Interrupt */ + .long cpuss_interrupts_cm0_cti_0_IRQHandler /* CM0+ CTI #0 */ + .long cpuss_interrupts_cm0_cti_1_IRQHandler /* CM0+ CTI #1 */ + .long cpuss_interrupts_cm4_cti_0_IRQHandler /* CM4 CTI #0 */ + .long cpuss_interrupts_cm4_cti_1_IRQHandler /* CM4 CTI #1 */ + .long tcpwm_0_interrupts_0_IRQHandler /* TCPWM #0, Counter #0 */ + .long tcpwm_0_interrupts_1_IRQHandler /* TCPWM #0, Counter #1 */ + .long tcpwm_0_interrupts_2_IRQHandler /* TCPWM #0, Counter #2 */ + .long tcpwm_0_interrupts_3_IRQHandler /* TCPWM #0, Counter #3 */ + .long tcpwm_0_interrupts_4_IRQHandler /* TCPWM #0, Counter #4 */ + .long tcpwm_0_interrupts_5_IRQHandler /* TCPWM #0, Counter #5 */ + .long tcpwm_0_interrupts_6_IRQHandler /* TCPWM #0, Counter #6 */ + .long tcpwm_0_interrupts_7_IRQHandler /* TCPWM #0, Counter #7 */ + .long tcpwm_1_interrupts_0_IRQHandler /* TCPWM #1, Counter #0 */ + .long tcpwm_1_interrupts_1_IRQHandler /* TCPWM #1, Counter #1 */ + .long tcpwm_1_interrupts_2_IRQHandler /* TCPWM #1, Counter #2 */ + .long tcpwm_1_interrupts_3_IRQHandler /* TCPWM #1, Counter #3 */ + .long tcpwm_1_interrupts_4_IRQHandler /* TCPWM #1, Counter #4 */ + .long tcpwm_1_interrupts_5_IRQHandler /* TCPWM #1, Counter #5 */ + .long tcpwm_1_interrupts_6_IRQHandler /* TCPWM #1, Counter #6 */ + .long tcpwm_1_interrupts_7_IRQHandler /* TCPWM #1, Counter #7 */ + .long tcpwm_1_interrupts_8_IRQHandler /* TCPWM #1, Counter #8 */ + .long tcpwm_1_interrupts_9_IRQHandler /* TCPWM #1, Counter #9 */ + .long tcpwm_1_interrupts_10_IRQHandler /* TCPWM #1, Counter #10 */ + .long tcpwm_1_interrupts_11_IRQHandler /* TCPWM #1, Counter #11 */ + .long tcpwm_1_interrupts_12_IRQHandler /* TCPWM #1, Counter #12 */ + .long tcpwm_1_interrupts_13_IRQHandler /* TCPWM #1, Counter #13 */ + .long tcpwm_1_interrupts_14_IRQHandler /* TCPWM #1, Counter #14 */ + .long tcpwm_1_interrupts_15_IRQHandler /* TCPWM #1, Counter #15 */ + .long tcpwm_1_interrupts_16_IRQHandler /* TCPWM #1, Counter #16 */ + .long tcpwm_1_interrupts_17_IRQHandler /* TCPWM #1, Counter #17 */ + .long tcpwm_1_interrupts_18_IRQHandler /* TCPWM #1, Counter #18 */ + .long tcpwm_1_interrupts_19_IRQHandler /* TCPWM #1, Counter #19 */ + .long tcpwm_1_interrupts_20_IRQHandler /* TCPWM #1, Counter #20 */ + .long tcpwm_1_interrupts_21_IRQHandler /* TCPWM #1, Counter #21 */ + .long tcpwm_1_interrupts_22_IRQHandler /* TCPWM #1, Counter #22 */ + .long tcpwm_1_interrupts_23_IRQHandler /* TCPWM #1, Counter #23 */ + .long udb_interrupts_0_IRQHandler /* UDB Interrupt #0 */ + .long udb_interrupts_1_IRQHandler /* UDB Interrupt #1 */ + .long udb_interrupts_2_IRQHandler /* UDB Interrupt #2 */ + .long udb_interrupts_3_IRQHandler /* UDB Interrupt #3 */ + .long udb_interrupts_4_IRQHandler /* UDB Interrupt #4 */ + .long udb_interrupts_5_IRQHandler /* UDB Interrupt #5 */ + .long udb_interrupts_6_IRQHandler /* UDB Interrupt #6 */ + .long udb_interrupts_7_IRQHandler /* UDB Interrupt #7 */ + .long udb_interrupts_8_IRQHandler /* UDB Interrupt #8 */ + .long udb_interrupts_9_IRQHandler /* UDB Interrupt #9 */ + .long udb_interrupts_10_IRQHandler /* UDB Interrupt #10 */ + .long udb_interrupts_11_IRQHandler /* UDB Interrupt #11 */ + .long udb_interrupts_12_IRQHandler /* UDB Interrupt #12 */ + .long udb_interrupts_13_IRQHandler /* UDB Interrupt #13 */ + .long udb_interrupts_14_IRQHandler /* UDB Interrupt #14 */ + .long udb_interrupts_15_IRQHandler /* UDB Interrupt #15 */ + .long pass_interrupt_sar_IRQHandler /* SAR ADC interrupt */ + .long audioss_interrupt_i2s_IRQHandler /* I2S Audio interrupt */ + .long audioss_interrupt_pdm_IRQHandler /* PDM/PCM Audio interrupt */ + .long profile_interrupt_IRQHandler /* Energy Profiler interrupt */ + .long smif_interrupt_IRQHandler /* Serial Memory Interface interrupt */ + .long usb_interrupt_hi_IRQHandler /* USB Interrupt */ + .long usb_interrupt_med_IRQHandler /* USB Interrupt */ + .long usb_interrupt_lo_IRQHandler /* USB Interrupt */ + .long pass_interrupt_dacs_IRQHandler /* Consolidated interrrupt for all DACs */ + + + .size __Vectors, . - __Vectors + .equ __VectorsSize, . - __Vectors + + .section .ram_vectors + .align 2 + .globl __ramVectors +__ramVectors: + .space __VectorsSize + .size __ramVectors, . - __ramVectors + + + .text + .thumb + .thumb_func + .align 2 + + /* Device startup customization */ + .weak Cy_OnResetUser + .func Cy_OnResetUser, Cy_OnResetUser + .type Cy_OnResetUser, %function +Cy_OnResetUser: + bx lr + .size Cy_OnResetUser, . - Cy_OnResetUser + .endfunc + + /* Saves and disables the interrupts */ + .global Cy_SaveIRQ + .func Cy_SaveIRQ, Cy_SaveIRQ + .type Cy_SaveIRQ, %function +Cy_SaveIRQ: + mrs r0, PRIMASK + cpsid i + bx lr + .size Cy_SaveIRQ, . - Cy_SaveIRQ + .endfunc + + /* Restores the interrupts */ + .global Cy_RestoreIRQ + .func Cy_RestoreIRQ, Cy_RestoreIRQ + .type Cy_RestoreIRQ, %function +Cy_RestoreIRQ: + msr PRIMASK, r0 + bx lr + .size Cy_RestoreIRQ, . - Cy_RestoreIRQ + .endfunc + + /* Reset handler */ + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + + bl Cy_OnResetUser + +/* Firstly it copies data from read only memory to RAM. There are two schemes + * to copy. One can copy more than one sections. Another can only copy + * one section. The former scheme needs more instructions and read-only + * data to implement than the latter. + * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */ + +#ifdef __STARTUP_COPY_MULTIPLE +/* Multiple sections scheme. + * + * Between symbol address __copy_table_start__ and __copy_table_end__, + * there are array of triplets, each of which specify: + * offset 0: LMA of start of a section to copy from + * offset 4: VMA of start of a section to copy to + * offset 8: size of the section to copy. Must be multiply of 4 + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r4, =__copy_table_start__ + ldr r5, =__copy_table_end__ + +.L_loop0: + cmp r4, r5 + bge .L_loop0_done + ldr r1, [r4] + ldr r2, [r4, #4] + ldr r3, [r4, #8] + +.L_loop0_0: + subs r3, #4 + ittt ge + ldrge r0, [r1, r3] + strge r0, [r2, r3] + bge .L_loop0_0 + + adds r4, #12 + b .L_loop0 + +.L_loop0_done: +#else +/* Single section scheme. + * + * The ranges of copy from/to are specified by following symbols + * __etext: LMA of start of the section to copy from. Usually end of text + * __data_start__: VMA of start of the section to copy to + * __data_end__: VMA of end of the section to copy to + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__etext + ldr r2, =__data_start__ + ldr r3, =__data_end__ + +.L_loop1: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .L_loop1 +#endif /*__STARTUP_COPY_MULTIPLE */ + +/* This part of work usually is done in C library startup code. Otherwise, + * define this macro to enable it in this startup. + * + * There are two schemes too. One can clear multiple BSS sections. Another + * can only clear one section. The former is more size expensive than the + * latter. + * + * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former. + * Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later. + */ +#ifdef __STARTUP_CLEAR_BSS_MULTIPLE +/* Multiple sections scheme. + * + * Between symbol address __copy_table_start__ and __copy_table_end__, + * there are array of tuples specifying: + * offset 0: Start of a BSS section + * offset 4: Size of this BSS section. Must be multiply of 4 + */ + ldr r3, =__zero_table_start__ + ldr r4, =__zero_table_end__ + +.L_loop2: + cmp r3, r4 + bge .L_loop2_done + ldr r1, [r3] + ldr r2, [r3, #4] + movs r0, 0 + +.L_loop2_0: + subs r2, #4 + itt ge + strge r0, [r1, r2] + bge .L_loop2_0 + + adds r3, #8 + b .L_loop2 +.L_loop2_done: +#elif defined (__STARTUP_CLEAR_BSS) +/* Single BSS section scheme. + * + * The BSS section is specified by following symbols + * __bss_start__: start of the BSS section. + * __bss_end__: end of the BSS section. + * + * Both addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__bss_start__ + ldr r2, =__bss_end__ + + movs r0, 0 +.L_loop3: + cmp r1, r2 + itt lt + strlt r0, [r1], #4 + blt .L_loop3 +#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */ + + /* Update Vector Table Offset Register. */ + ldr r0, =__ramVectors + ldr r1, =CY_CPU_VTOR_ADDR + str r0, [r1] + dsb 0xF + + /* Enable the FPU if used */ + bl Cy_SystemInitFpuEnable + + bl _start + + /* Should never get here */ + b . + + .pool + .size Reset_Handler, . - Reset_Handler + + .align 1 + .thumb_func + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + + .weak Cy_SysLib_FaultHandler + .type Cy_SysLib_FaultHandler, %function +Cy_SysLib_FaultHandler: + b . + .size Cy_SysLib_FaultHandler, . - Cy_SysLib_FaultHandler + + .type Fault_Handler, %function +Fault_Handler: + /* Storing LR content for Creator call stack trace */ + push {LR} + movs r0, #4 + mov r1, LR + tst r0, r1 + beq .L_MSP + mrs r0, PSP + b .L_API_call +.L_MSP: + mrs r0, MSP +.L_API_call: + /* Compensation of stack pointer address due to pushing 4 bytes of LR */ + adds r0, r0, #4 + bl Cy_SysLib_FaultHandler + b . + .size Fault_Handler, . - Fault_Handler + +.macro def_fault_Handler fault_handler_name + .weak \fault_handler_name + .set \fault_handler_name, Fault_Handler + .endm + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler NMI_Handler + + def_fault_Handler HardFault_Handler + def_fault_Handler MemManage_Handler + def_fault_Handler BusFault_Handler + def_fault_Handler UsageFault_Handler + + def_irq_handler SVC_Handler + def_irq_handler DebugMon_Handler + def_irq_handler PendSV_Handler + def_irq_handler SysTick_Handler + + def_irq_handler ioss_interrupts_gpio_0_IRQHandler /* GPIO Port Interrupt #0 */ + def_irq_handler ioss_interrupts_gpio_1_IRQHandler /* GPIO Port Interrupt #1 */ + def_irq_handler ioss_interrupts_gpio_2_IRQHandler /* GPIO Port Interrupt #2 */ + def_irq_handler ioss_interrupts_gpio_3_IRQHandler /* GPIO Port Interrupt #3 */ + def_irq_handler ioss_interrupts_gpio_4_IRQHandler /* GPIO Port Interrupt #4 */ + def_irq_handler ioss_interrupts_gpio_5_IRQHandler /* GPIO Port Interrupt #5 */ + def_irq_handler ioss_interrupts_gpio_6_IRQHandler /* GPIO Port Interrupt #6 */ + def_irq_handler ioss_interrupts_gpio_7_IRQHandler /* GPIO Port Interrupt #7 */ + def_irq_handler ioss_interrupts_gpio_8_IRQHandler /* GPIO Port Interrupt #8 */ + def_irq_handler ioss_interrupts_gpio_9_IRQHandler /* GPIO Port Interrupt #9 */ + def_irq_handler ioss_interrupts_gpio_10_IRQHandler /* GPIO Port Interrupt #10 */ + def_irq_handler ioss_interrupts_gpio_11_IRQHandler /* GPIO Port Interrupt #11 */ + def_irq_handler ioss_interrupts_gpio_12_IRQHandler /* GPIO Port Interrupt #12 */ + def_irq_handler ioss_interrupts_gpio_13_IRQHandler /* GPIO Port Interrupt #13 */ + def_irq_handler ioss_interrupts_gpio_14_IRQHandler /* GPIO Port Interrupt #14 */ + def_irq_handler ioss_interrupt_gpio_IRQHandler /* GPIO All Ports */ + def_irq_handler ioss_interrupt_vdd_IRQHandler /* GPIO Supply Detect Interrupt */ + def_irq_handler lpcomp_interrupt_IRQHandler /* Low Power Comparator Interrupt */ + def_irq_handler scb_8_interrupt_IRQHandler /* Serial Communication Block #8 (DeepSleep capable) */ + def_irq_handler srss_interrupt_mcwdt_0_IRQHandler /* Multi Counter Watchdog Timer interrupt */ + def_irq_handler srss_interrupt_mcwdt_1_IRQHandler /* Multi Counter Watchdog Timer interrupt */ + def_irq_handler srss_interrupt_backup_IRQHandler /* Backup domain interrupt */ + def_irq_handler srss_interrupt_IRQHandler /* Other combined Interrupts for SRSS (LVD, WDT, CLKCAL) */ + def_irq_handler pass_interrupt_ctbs_IRQHandler /* CTBm Interrupt (all CTBms) */ + def_irq_handler bless_interrupt_IRQHandler /* Bluetooth Radio interrupt */ + def_irq_handler cpuss_interrupts_ipc_0_IRQHandler /* CPUSS Inter Process Communication Interrupt #0 */ + def_irq_handler cpuss_interrupts_ipc_1_IRQHandler /* CPUSS Inter Process Communication Interrupt #1 */ + def_irq_handler cpuss_interrupts_ipc_2_IRQHandler /* CPUSS Inter Process Communication Interrupt #2 */ + def_irq_handler cpuss_interrupts_ipc_3_IRQHandler /* CPUSS Inter Process Communication Interrupt #3 */ + def_irq_handler cpuss_interrupts_ipc_4_IRQHandler /* CPUSS Inter Process Communication Interrupt #4 */ + def_irq_handler cpuss_interrupts_ipc_5_IRQHandler /* CPUSS Inter Process Communication Interrupt #5 */ + def_irq_handler cpuss_interrupts_ipc_6_IRQHandler /* CPUSS Inter Process Communication Interrupt #6 */ + def_irq_handler cpuss_interrupts_ipc_7_IRQHandler /* CPUSS Inter Process Communication Interrupt #7 */ + def_irq_handler cpuss_interrupts_ipc_8_IRQHandler /* CPUSS Inter Process Communication Interrupt #8 */ + def_irq_handler cpuss_interrupts_ipc_9_IRQHandler /* CPUSS Inter Process Communication Interrupt #9 */ + def_irq_handler cpuss_interrupts_ipc_10_IRQHandler /* CPUSS Inter Process Communication Interrupt #10 */ + def_irq_handler cpuss_interrupts_ipc_11_IRQHandler /* CPUSS Inter Process Communication Interrupt #11 */ + def_irq_handler cpuss_interrupts_ipc_12_IRQHandler /* CPUSS Inter Process Communication Interrupt #12 */ + def_irq_handler cpuss_interrupts_ipc_13_IRQHandler /* CPUSS Inter Process Communication Interrupt #13 */ + def_irq_handler cpuss_interrupts_ipc_14_IRQHandler /* CPUSS Inter Process Communication Interrupt #14 */ + def_irq_handler cpuss_interrupts_ipc_15_IRQHandler /* CPUSS Inter Process Communication Interrupt #15 */ + def_irq_handler scb_0_interrupt_IRQHandler /* Serial Communication Block #0 */ + def_irq_handler scb_1_interrupt_IRQHandler /* Serial Communication Block #1 */ + def_irq_handler scb_2_interrupt_IRQHandler /* Serial Communication Block #2 */ + def_irq_handler scb_3_interrupt_IRQHandler /* Serial Communication Block #3 */ + def_irq_handler scb_4_interrupt_IRQHandler /* Serial Communication Block #4 */ + def_irq_handler scb_5_interrupt_IRQHandler /* Serial Communication Block #5 */ + def_irq_handler scb_6_interrupt_IRQHandler /* Serial Communication Block #6 */ + def_irq_handler scb_7_interrupt_IRQHandler /* Serial Communication Block #7 */ + def_irq_handler csd_interrupt_IRQHandler /* CSD (Capsense) interrupt */ + def_irq_handler cpuss_interrupts_dw0_0_IRQHandler /* CPUSS DataWire #0, Channel #0 */ + def_irq_handler cpuss_interrupts_dw0_1_IRQHandler /* CPUSS DataWire #0, Channel #1 */ + def_irq_handler cpuss_interrupts_dw0_2_IRQHandler /* CPUSS DataWire #0, Channel #2 */ + def_irq_handler cpuss_interrupts_dw0_3_IRQHandler /* CPUSS DataWire #0, Channel #3 */ + def_irq_handler cpuss_interrupts_dw0_4_IRQHandler /* CPUSS DataWire #0, Channel #4 */ + def_irq_handler cpuss_interrupts_dw0_5_IRQHandler /* CPUSS DataWire #0, Channel #5 */ + def_irq_handler cpuss_interrupts_dw0_6_IRQHandler /* CPUSS DataWire #0, Channel #6 */ + def_irq_handler cpuss_interrupts_dw0_7_IRQHandler /* CPUSS DataWire #0, Channel #7 */ + def_irq_handler cpuss_interrupts_dw0_8_IRQHandler /* CPUSS DataWire #0, Channel #8 */ + def_irq_handler cpuss_interrupts_dw0_9_IRQHandler /* CPUSS DataWire #0, Channel #9 */ + def_irq_handler cpuss_interrupts_dw0_10_IRQHandler /* CPUSS DataWire #0, Channel #10 */ + def_irq_handler cpuss_interrupts_dw0_11_IRQHandler /* CPUSS DataWire #0, Channel #11 */ + def_irq_handler cpuss_interrupts_dw0_12_IRQHandler /* CPUSS DataWire #0, Channel #12 */ + def_irq_handler cpuss_interrupts_dw0_13_IRQHandler /* CPUSS DataWire #0, Channel #13 */ + def_irq_handler cpuss_interrupts_dw0_14_IRQHandler /* CPUSS DataWire #0, Channel #14 */ + def_irq_handler cpuss_interrupts_dw0_15_IRQHandler /* CPUSS DataWire #0, Channel #15 */ + def_irq_handler cpuss_interrupts_dw1_0_IRQHandler /* CPUSS DataWire #1, Channel #0 */ + def_irq_handler cpuss_interrupts_dw1_1_IRQHandler /* CPUSS DataWire #1, Channel #1 */ + def_irq_handler cpuss_interrupts_dw1_2_IRQHandler /* CPUSS DataWire #1, Channel #2 */ + def_irq_handler cpuss_interrupts_dw1_3_IRQHandler /* CPUSS DataWire #1, Channel #3 */ + def_irq_handler cpuss_interrupts_dw1_4_IRQHandler /* CPUSS DataWire #1, Channel #4 */ + def_irq_handler cpuss_interrupts_dw1_5_IRQHandler /* CPUSS DataWire #1, Channel #5 */ + def_irq_handler cpuss_interrupts_dw1_6_IRQHandler /* CPUSS DataWire #1, Channel #6 */ + def_irq_handler cpuss_interrupts_dw1_7_IRQHandler /* CPUSS DataWire #1, Channel #7 */ + def_irq_handler cpuss_interrupts_dw1_8_IRQHandler /* CPUSS DataWire #1, Channel #8 */ + def_irq_handler cpuss_interrupts_dw1_9_IRQHandler /* CPUSS DataWire #1, Channel #9 */ + def_irq_handler cpuss_interrupts_dw1_10_IRQHandler /* CPUSS DataWire #1, Channel #10 */ + def_irq_handler cpuss_interrupts_dw1_11_IRQHandler /* CPUSS DataWire #1, Channel #11 */ + def_irq_handler cpuss_interrupts_dw1_12_IRQHandler /* CPUSS DataWire #1, Channel #12 */ + def_irq_handler cpuss_interrupts_dw1_13_IRQHandler /* CPUSS DataWire #1, Channel #13 */ + def_irq_handler cpuss_interrupts_dw1_14_IRQHandler /* CPUSS DataWire #1, Channel #14 */ + def_irq_handler cpuss_interrupts_dw1_15_IRQHandler /* CPUSS DataWire #1, Channel #15 */ + def_irq_handler cpuss_interrupts_fault_0_IRQHandler /* CPUSS Fault Structure Interrupt #0 */ + def_irq_handler cpuss_interrupts_fault_1_IRQHandler /* CPUSS Fault Structure Interrupt #1 */ + def_irq_handler cpuss_interrupt_crypto_IRQHandler /* CRYPTO Accelerator Interrupt */ + def_irq_handler cpuss_interrupt_fm_IRQHandler /* FLASH Macro Interrupt */ + def_irq_handler cpuss_interrupts_cm0_cti_0_IRQHandler /* CM0+ CTI #0 */ + def_irq_handler cpuss_interrupts_cm0_cti_1_IRQHandler /* CM0+ CTI #1 */ + def_irq_handler cpuss_interrupts_cm4_cti_0_IRQHandler /* CM4 CTI #0 */ + def_irq_handler cpuss_interrupts_cm4_cti_1_IRQHandler /* CM4 CTI #1 */ + def_irq_handler tcpwm_0_interrupts_0_IRQHandler /* TCPWM #0, Counter #0 */ + def_irq_handler tcpwm_0_interrupts_1_IRQHandler /* TCPWM #0, Counter #1 */ + def_irq_handler tcpwm_0_interrupts_2_IRQHandler /* TCPWM #0, Counter #2 */ + def_irq_handler tcpwm_0_interrupts_3_IRQHandler /* TCPWM #0, Counter #3 */ + def_irq_handler tcpwm_0_interrupts_4_IRQHandler /* TCPWM #0, Counter #4 */ + def_irq_handler tcpwm_0_interrupts_5_IRQHandler /* TCPWM #0, Counter #5 */ + def_irq_handler tcpwm_0_interrupts_6_IRQHandler /* TCPWM #0, Counter #6 */ + def_irq_handler tcpwm_0_interrupts_7_IRQHandler /* TCPWM #0, Counter #7 */ + def_irq_handler tcpwm_1_interrupts_0_IRQHandler /* TCPWM #1, Counter #0 */ + def_irq_handler tcpwm_1_interrupts_1_IRQHandler /* TCPWM #1, Counter #1 */ + def_irq_handler tcpwm_1_interrupts_2_IRQHandler /* TCPWM #1, Counter #2 */ + def_irq_handler tcpwm_1_interrupts_3_IRQHandler /* TCPWM #1, Counter #3 */ + def_irq_handler tcpwm_1_interrupts_4_IRQHandler /* TCPWM #1, Counter #4 */ + def_irq_handler tcpwm_1_interrupts_5_IRQHandler /* TCPWM #1, Counter #5 */ + def_irq_handler tcpwm_1_interrupts_6_IRQHandler /* TCPWM #1, Counter #6 */ + def_irq_handler tcpwm_1_interrupts_7_IRQHandler /* TCPWM #1, Counter #7 */ + def_irq_handler tcpwm_1_interrupts_8_IRQHandler /* TCPWM #1, Counter #8 */ + def_irq_handler tcpwm_1_interrupts_9_IRQHandler /* TCPWM #1, Counter #9 */ + def_irq_handler tcpwm_1_interrupts_10_IRQHandler /* TCPWM #1, Counter #10 */ + def_irq_handler tcpwm_1_interrupts_11_IRQHandler /* TCPWM #1, Counter #11 */ + def_irq_handler tcpwm_1_interrupts_12_IRQHandler /* TCPWM #1, Counter #12 */ + def_irq_handler tcpwm_1_interrupts_13_IRQHandler /* TCPWM #1, Counter #13 */ + def_irq_handler tcpwm_1_interrupts_14_IRQHandler /* TCPWM #1, Counter #14 */ + def_irq_handler tcpwm_1_interrupts_15_IRQHandler /* TCPWM #1, Counter #15 */ + def_irq_handler tcpwm_1_interrupts_16_IRQHandler /* TCPWM #1, Counter #16 */ + def_irq_handler tcpwm_1_interrupts_17_IRQHandler /* TCPWM #1, Counter #17 */ + def_irq_handler tcpwm_1_interrupts_18_IRQHandler /* TCPWM #1, Counter #18 */ + def_irq_handler tcpwm_1_interrupts_19_IRQHandler /* TCPWM #1, Counter #19 */ + def_irq_handler tcpwm_1_interrupts_20_IRQHandler /* TCPWM #1, Counter #20 */ + def_irq_handler tcpwm_1_interrupts_21_IRQHandler /* TCPWM #1, Counter #21 */ + def_irq_handler tcpwm_1_interrupts_22_IRQHandler /* TCPWM #1, Counter #22 */ + def_irq_handler tcpwm_1_interrupts_23_IRQHandler /* TCPWM #1, Counter #23 */ + def_irq_handler udb_interrupts_0_IRQHandler /* UDB Interrupt #0 */ + def_irq_handler udb_interrupts_1_IRQHandler /* UDB Interrupt #1 */ + def_irq_handler udb_interrupts_2_IRQHandler /* UDB Interrupt #2 */ + def_irq_handler udb_interrupts_3_IRQHandler /* UDB Interrupt #3 */ + def_irq_handler udb_interrupts_4_IRQHandler /* UDB Interrupt #4 */ + def_irq_handler udb_interrupts_5_IRQHandler /* UDB Interrupt #5 */ + def_irq_handler udb_interrupts_6_IRQHandler /* UDB Interrupt #6 */ + def_irq_handler udb_interrupts_7_IRQHandler /* UDB Interrupt #7 */ + def_irq_handler udb_interrupts_8_IRQHandler /* UDB Interrupt #8 */ + def_irq_handler udb_interrupts_9_IRQHandler /* UDB Interrupt #9 */ + def_irq_handler udb_interrupts_10_IRQHandler /* UDB Interrupt #10 */ + def_irq_handler udb_interrupts_11_IRQHandler /* UDB Interrupt #11 */ + def_irq_handler udb_interrupts_12_IRQHandler /* UDB Interrupt #12 */ + def_irq_handler udb_interrupts_13_IRQHandler /* UDB Interrupt #13 */ + def_irq_handler udb_interrupts_14_IRQHandler /* UDB Interrupt #14 */ + def_irq_handler udb_interrupts_15_IRQHandler /* UDB Interrupt #15 */ + def_irq_handler pass_interrupt_sar_IRQHandler /* SAR ADC interrupt */ + def_irq_handler audioss_interrupt_i2s_IRQHandler /* I2S Audio interrupt */ + def_irq_handler audioss_interrupt_pdm_IRQHandler /* PDM/PCM Audio interrupt */ + def_irq_handler profile_interrupt_IRQHandler /* Energy Profiler interrupt */ + def_irq_handler smif_interrupt_IRQHandler /* Serial Memory Interface interrupt */ + def_irq_handler usb_interrupt_hi_IRQHandler /* USB Interrupt */ + def_irq_handler usb_interrupt_med_IRQHandler /* USB Interrupt */ + def_irq_handler usb_interrupt_lo_IRQHandler /* USB Interrupt */ + def_irq_handler pass_interrupt_dacs_IRQHandler /* Consolidated interrrupt for all DACs */ + + .end + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_IAR/cy8c6xx7_cm4_dual.icf b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_IAR/cy8c6xx7_cm4_dual.icf new file mode 100644 index 0000000000..02c7e76ee0 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_IAR/cy8c6xx7_cm4_dual.icf @@ -0,0 +1,217 @@ +/***************************************************************************//** +* \file cy8c6xx7_cm4_dual.icf +* \version 2.10 +* +* Linker file for the IAR compiler. +* +* The main purpose of the linker script is to describe how the sections in the +* input files should be mapped into the output file, and to control the memory +* layout of the output file. +* +* \note The entry point is fixed and starts at 0x10000000. The valid application +* image should be placed there. +* +* \note The linker files included with the PDL template projects must be generic +* and handle all common use cases. Your project may not use every section +* defined in the linker files. In that case you may see warnings during the +* build process. In your project, you can simply comment out or remove the +* relevant code in the linker file. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_4.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x00000000; + +/* The symbols below define the location and size of blocks of memory in the target. + * Use these symbols to specify the memory regions available for allocation. + */ + +/* The following symbols control RAM and flash memory allocation for the CM4 core. + * You can change the memory allocation by editing RAM and Flash symbols. + * Note that 2 KB of RAM (at the end of the RAM section) are reserved for system use. + * Using this memory region for other purposes will lead to unexpected behavior. + * Your changes must be aligned with the corresponding symbols for CM0+ core in 'xx_cm0plus.icf', + * where 'xx' is the device group; for example, 'cy8c6xx7_cm0plus.icf'. + */ +/* RAM */ +define symbol __ICFEDIT_region_IRAM1_start__ = 0x08010000; +define symbol __ICFEDIT_region_IRAM1_end__ = 0x08047800; +/* Flash */ +define symbol __ICFEDIT_region_IROM1_start__ = 0x10080000; +define symbol __ICFEDIT_region_IROM1_end__ = 0x100F8000; + +/* The following symbols define a 32K flash region used for EEPROM emulation. + * This region can also be used as the general purpose flash. + * You can assign sections to this memory region for only one of the cores. + * Note some middleware (e.g. BLE, Emulated EEPROM) can place their data into this memory region. + * Therefore, repurposing this memory region will prevent such middleware from operation. + */ +define symbol __ICFEDIT_region_IROM2_start__ = 0x14000000; +define symbol __ICFEDIT_region_IROM2_end__ = 0x14007FFF; + +/* The following symbols define device specific memory regions and must not be changed. */ +/* Supervisory FLASH - User Data */ +define symbol __ICFEDIT_region_IROM3_start__ = 0x16000800; +define symbol __ICFEDIT_region_IROM3_end__ = 0x160007FF; + +/* Supervisory FLASH - Normal Access Restrictions (NAR) */ +define symbol __ICFEDIT_region_IROM4_start__ = 0x16001A00; +define symbol __ICFEDIT_region_IROM4_end__ = 0x16001BFF; + +/* Supervisory FLASH - Public Key */ +define symbol __ICFEDIT_region_IROM5_start__ = 0x16005A00; +define symbol __ICFEDIT_region_IROM5_end__ = 0x160065FF; + +/* Supervisory FLASH - Table of Content # 2 */ +define symbol __ICFEDIT_region_IROM6_start__ = 0x16007C00; +define symbol __ICFEDIT_region_IROM6_end__ = 0x16007DFF; + +/* Supervisory FLASH - Table of Content # 2 Copy */ +define symbol __ICFEDIT_region_IROM7_start__ = 0x16007E00; +define symbol __ICFEDIT_region_IROM7_end__ = 0x16007FFF; + +/* eFuse */ +define symbol __ICFEDIT_region_IROM8_start__ = 0x90700000; +define symbol __ICFEDIT_region_IROM8_end__ = 0x907FFFFF; + +/* XIP */ +define symbol __ICFEDIT_region_EROM1_start__ = 0x18000000; +define symbol __ICFEDIT_region_EROM1_end__ = 0x1FFFFFFF; + +define symbol __ICFEDIT_region_EROM2_start__ = 0x0; +define symbol __ICFEDIT_region_EROM2_end__ = 0x0; +define symbol __ICFEDIT_region_EROM3_start__ = 0x0; +define symbol __ICFEDIT_region_EROM3_end__ = 0x0; + + +define symbol __ICFEDIT_region_IRAM2_start__ = 0x0; +define symbol __ICFEDIT_region_IRAM2_end__ = 0x0; +define symbol __ICFEDIT_region_ERAM1_start__ = 0x0; +define symbol __ICFEDIT_region_ERAM1_end__ = 0x0; +define symbol __ICFEDIT_region_ERAM2_start__ = 0x0; +define symbol __ICFEDIT_region_ERAM2_end__ = 0x0; +define symbol __ICFEDIT_region_ERAM3_start__ = 0x0; +define symbol __ICFEDIT_region_ERAM3_end__ = 0x0; +/*-Sizes-*/ +if (!isdefinedsymbol(__STACK_SIZE)) { + define symbol __ICFEDIT_size_cstack__ = 0x1000; +} else { + define symbol __ICFEDIT_size_cstack__ = __STACK_SIZE; +} +define symbol __ICFEDIT_size_proc_stack__ = 0x0; +if (!isdefinedsymbol(__HEAP_SIZE)) { + define symbol __ICFEDIT_size_heap__ = 0x3800; +} else { + define symbol __ICFEDIT_size_heap__ = __HEAP_SIZE; +} +/**** End of ICF editor section. ###ICF###*/ + +define memory mem with size = 4G; +define region IROM1_region = mem:[from __ICFEDIT_region_IROM1_start__ to __ICFEDIT_region_IROM1_end__]; +define region IROM2_region = mem:[from __ICFEDIT_region_IROM2_start__ to __ICFEDIT_region_IROM2_end__]; +define region IROM3_region = mem:[from __ICFEDIT_region_IROM3_start__ to __ICFEDIT_region_IROM3_end__]; +define region IROM4_region = mem:[from __ICFEDIT_region_IROM4_start__ to __ICFEDIT_region_IROM4_end__]; +define region IROM5_region = mem:[from __ICFEDIT_region_IROM5_start__ to __ICFEDIT_region_IROM5_end__]; +define region IROM6_region = mem:[from __ICFEDIT_region_IROM6_start__ to __ICFEDIT_region_IROM6_end__]; +define region IROM7_region = mem:[from __ICFEDIT_region_IROM7_start__ to __ICFEDIT_region_IROM7_end__]; +define region IROM8_region = mem:[from __ICFEDIT_region_IROM8_start__ to __ICFEDIT_region_IROM8_end__]; +define region EROM1_region = mem:[from __ICFEDIT_region_EROM1_start__ to __ICFEDIT_region_EROM1_end__]; +define region IRAM1_region = mem:[from __ICFEDIT_region_IRAM1_start__ to __ICFEDIT_region_IRAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block PROC_STACK with alignment = 8, size = __ICFEDIT_size_proc_stack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; +define block HSTACK {block HEAP, block PROC_STACK, last block CSTACK}; +define block RO {first section .intvec, readonly}; + +/*-Initializations-*/ +initialize by copy { readwrite }; +do not initialize { section .noinit, section .intvec_ram }; + + +/*-Placement-*/ + +/* Flash */ +place at start of IROM1_region { block RO }; +".cy_app_signature" : place at address (__ICFEDIT_region_IROM1_end__ - 0x200) { section .cy_app_signature }; + +/* Emulated EEPROM Flash area */ +".cy_em_eeprom" : place at start of IROM2_region { section .cy_em_eeprom }; + +/* Supervisory Flash - User Data */ +".cy_sflash_user_data" : place at start of IROM3_region { section .cy_sflash_user_data }; + +/* Supervisory Flash - NAR */ +".cy_sflash_nar" : place at start of IROM4_region { section .cy_sflash_nar }; + +/* Supervisory Flash - Public Key */ +".cy_sflash_public_key" : place at start of IROM5_region { section .cy_sflash_public_key }; + +/* Supervisory Flash - TOC2 */ +".cy_toc_part2" : place at start of IROM6_region { section .cy_toc_part2 }; + +/* Supervisory Flash - RTOC2 */ +".cy_rtoc_part2" : place at start of IROM7_region { section .cy_rtoc_part2 }; + +/* eFuse */ +".cy_efuse" : place at start of IROM8_region { section .cy_efuse }; + +/* Execute in Place (XIP). See the smif driver documentation for details. */ +".cy_xip" : place at start of EROM1_region { section .cy_xip }; + +/* RAM */ +place at start of IRAM1_region { readwrite section .intvec_ram}; +place in IRAM1_region { readwrite }; +place at end of IRAM1_region { block HSTACK }; + +/* These sections are used for additional metadata (silicon revision, Silicon/JTAG ID, etc.) storage. */ +".cymeta" : place at address mem : 0x90500000 { readonly section .cymeta }; + + +keep { section .cy_app_signature, + section .cy_em_eeprom, + section .cy_sflash_user_data, + section .cy_sflash_nar, + section .cy_sflash_public_key, + section .cy_toc_part2, + section .cy_rtoc_part2, + section .cy_efuse, + section .cy_xip, + section .cymeta, + }; + + +/* The following symbols used by the cymcuelftool. */ +/* Flash */ +define exported symbol __cy_memory_0_start = 0x10000000; +define exported symbol __cy_memory_0_length = 0x00100000; +define exported symbol __cy_memory_0_row_size = 0x200; + +/* Emulated EEPROM Flash area */ +define exported symbol __cy_memory_1_start = 0x14000000; +define exported symbol __cy_memory_1_length = 0x8000; +define exported symbol __cy_memory_1_row_size = 0x200; + +/* Supervisory Flash */ +define exported symbol __cy_memory_2_start = 0x16000000; +define exported symbol __cy_memory_2_length = 0x8000; +define exported symbol __cy_memory_2_row_size = 0x200; + +/* XIP */ +define exported symbol __cy_memory_3_start = 0x18000000; +define exported symbol __cy_memory_3_length = 0x08000000; +define exported symbol __cy_memory_3_row_size = 0x200; + +/* eFuse */ +define exported symbol __cy_memory_4_start = 0x90700000; +define exported symbol __cy_memory_4_length = 0x100000; +define exported symbol __cy_memory_4_row_size = 1; + +/* EOF */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_IAR/startup_psoc63_cm4.S b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_IAR/startup_psoc63_cm4.S new file mode 100644 index 0000000000..e6329ba27a --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/device/TOOLCHAIN_IAR/startup_psoc63_cm4.S @@ -0,0 +1,1148 @@ +;/**************************************************************************//** +; * @file startup_psoc63_cm4.s +; * @brief CMSIS Core Device Startup File for +; * ARMCM4 Device Series +; * @version V5.00 +; * @date 08. March 2016 +; ******************************************************************************/ +;/* +; * Copyright (c) 2009-2016 ARM Limited. All rights reserved. +; * +; * 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 +; * +; * 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. +; */ + +; +; The modules in this file are included in the libraries, and may be replaced +; by any user-defined modules that define the PUBLIC symbol _program_start or +; a user defined start symbol. +; To override the cstartup defined in the library, simply add your modified +; version to the workbench project. +; +; The vector table is normally located at address 0. +; When debugging in RAM, it can be located in RAM, aligned to at least 2^6. +; The name "__vector_table" has special meaning for C-SPY: +; it is where the SP start value is found, and the NVIC vector +; table register (VTOR) is initialized to this address if != 0. +; +; Cortex-M version +; + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + SECTION .intvec_ram:DATA:NOROOT(2) + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN Cy_SystemInitFpuEnable + PUBLIC __vector_table + PUBLIC __vector_table_0x1c + PUBLIC __Vectors + PUBLIC __Vectors_End + PUBLIC __Vectors_Size + PUBLIC __ramVectors + + DATA + +__vector_table + DCD sfe(CSTACK) + DCD Reset_Handler + + DCD 0x0000000D ; NMI_Handler is defined in ROM code + DCD HardFault_Handler + DCD MemManage_Handler + DCD BusFault_Handler + DCD UsageFault_Handler +__vector_table_0x1c + DCD 0 + DCD 0 + DCD 0 + DCD 0 + DCD SVC_Handler + DCD DebugMon_Handler + DCD 0 + DCD PendSV_Handler + DCD SysTick_Handler + + + ; External interrupts Description + DCD ioss_interrupts_gpio_0_IRQHandler ; GPIO Port Interrupt #0 + DCD ioss_interrupts_gpio_1_IRQHandler ; GPIO Port Interrupt #1 + DCD ioss_interrupts_gpio_2_IRQHandler ; GPIO Port Interrupt #2 + DCD ioss_interrupts_gpio_3_IRQHandler ; GPIO Port Interrupt #3 + DCD ioss_interrupts_gpio_4_IRQHandler ; GPIO Port Interrupt #4 + DCD ioss_interrupts_gpio_5_IRQHandler ; GPIO Port Interrupt #5 + DCD ioss_interrupts_gpio_6_IRQHandler ; GPIO Port Interrupt #6 + DCD ioss_interrupts_gpio_7_IRQHandler ; GPIO Port Interrupt #7 + DCD ioss_interrupts_gpio_8_IRQHandler ; GPIO Port Interrupt #8 + DCD ioss_interrupts_gpio_9_IRQHandler ; GPIO Port Interrupt #9 + DCD ioss_interrupts_gpio_10_IRQHandler ; GPIO Port Interrupt #10 + DCD ioss_interrupts_gpio_11_IRQHandler ; GPIO Port Interrupt #11 + DCD ioss_interrupts_gpio_12_IRQHandler ; GPIO Port Interrupt #12 + DCD ioss_interrupts_gpio_13_IRQHandler ; GPIO Port Interrupt #13 + DCD ioss_interrupts_gpio_14_IRQHandler ; GPIO Port Interrupt #14 + DCD ioss_interrupt_gpio_IRQHandler ; GPIO All Ports + DCD ioss_interrupt_vdd_IRQHandler ; GPIO Supply Detect Interrupt + DCD lpcomp_interrupt_IRQHandler ; Low Power Comparator Interrupt + DCD scb_8_interrupt_IRQHandler ; Serial Communication Block #8 (DeepSleep capable) + DCD srss_interrupt_mcwdt_0_IRQHandler ; Multi Counter Watchdog Timer interrupt + DCD srss_interrupt_mcwdt_1_IRQHandler ; Multi Counter Watchdog Timer interrupt + DCD srss_interrupt_backup_IRQHandler ; Backup domain interrupt + DCD srss_interrupt_IRQHandler ; Other combined Interrupts for SRSS (LVD, WDT, CLKCAL) + DCD pass_interrupt_ctbs_IRQHandler ; CTBm Interrupt (all CTBms) + DCD bless_interrupt_IRQHandler ; Bluetooth Radio interrupt + DCD cpuss_interrupts_ipc_0_IRQHandler ; CPUSS Inter Process Communication Interrupt #0 + DCD cpuss_interrupts_ipc_1_IRQHandler ; CPUSS Inter Process Communication Interrupt #1 + DCD cpuss_interrupts_ipc_2_IRQHandler ; CPUSS Inter Process Communication Interrupt #2 + DCD cpuss_interrupts_ipc_3_IRQHandler ; CPUSS Inter Process Communication Interrupt #3 + DCD cpuss_interrupts_ipc_4_IRQHandler ; CPUSS Inter Process Communication Interrupt #4 + DCD cpuss_interrupts_ipc_5_IRQHandler ; CPUSS Inter Process Communication Interrupt #5 + DCD cpuss_interrupts_ipc_6_IRQHandler ; CPUSS Inter Process Communication Interrupt #6 + DCD cpuss_interrupts_ipc_7_IRQHandler ; CPUSS Inter Process Communication Interrupt #7 + DCD cpuss_interrupts_ipc_8_IRQHandler ; CPUSS Inter Process Communication Interrupt #8 + DCD cpuss_interrupts_ipc_9_IRQHandler ; CPUSS Inter Process Communication Interrupt #9 + DCD cpuss_interrupts_ipc_10_IRQHandler ; CPUSS Inter Process Communication Interrupt #10 + DCD cpuss_interrupts_ipc_11_IRQHandler ; CPUSS Inter Process Communication Interrupt #11 + DCD cpuss_interrupts_ipc_12_IRQHandler ; CPUSS Inter Process Communication Interrupt #12 + DCD cpuss_interrupts_ipc_13_IRQHandler ; CPUSS Inter Process Communication Interrupt #13 + DCD cpuss_interrupts_ipc_14_IRQHandler ; CPUSS Inter Process Communication Interrupt #14 + DCD cpuss_interrupts_ipc_15_IRQHandler ; CPUSS Inter Process Communication Interrupt #15 + DCD scb_0_interrupt_IRQHandler ; Serial Communication Block #0 + DCD scb_1_interrupt_IRQHandler ; Serial Communication Block #1 + DCD scb_2_interrupt_IRQHandler ; Serial Communication Block #2 + DCD scb_3_interrupt_IRQHandler ; Serial Communication Block #3 + DCD scb_4_interrupt_IRQHandler ; Serial Communication Block #4 + DCD scb_5_interrupt_IRQHandler ; Serial Communication Block #5 + DCD scb_6_interrupt_IRQHandler ; Serial Communication Block #6 + DCD scb_7_interrupt_IRQHandler ; Serial Communication Block #7 + DCD csd_interrupt_IRQHandler ; CSD (Capsense) interrupt + DCD cpuss_interrupts_dw0_0_IRQHandler ; CPUSS DataWire #0, Channel #0 + DCD cpuss_interrupts_dw0_1_IRQHandler ; CPUSS DataWire #0, Channel #1 + DCD cpuss_interrupts_dw0_2_IRQHandler ; CPUSS DataWire #0, Channel #2 + DCD cpuss_interrupts_dw0_3_IRQHandler ; CPUSS DataWire #0, Channel #3 + DCD cpuss_interrupts_dw0_4_IRQHandler ; CPUSS DataWire #0, Channel #4 + DCD cpuss_interrupts_dw0_5_IRQHandler ; CPUSS DataWire #0, Channel #5 + DCD cpuss_interrupts_dw0_6_IRQHandler ; CPUSS DataWire #0, Channel #6 + DCD cpuss_interrupts_dw0_7_IRQHandler ; CPUSS DataWire #0, Channel #7 + DCD cpuss_interrupts_dw0_8_IRQHandler ; CPUSS DataWire #0, Channel #8 + DCD cpuss_interrupts_dw0_9_IRQHandler ; CPUSS DataWire #0, Channel #9 + DCD cpuss_interrupts_dw0_10_IRQHandler ; CPUSS DataWire #0, Channel #10 + DCD cpuss_interrupts_dw0_11_IRQHandler ; CPUSS DataWire #0, Channel #11 + DCD cpuss_interrupts_dw0_12_IRQHandler ; CPUSS DataWire #0, Channel #12 + DCD cpuss_interrupts_dw0_13_IRQHandler ; CPUSS DataWire #0, Channel #13 + DCD cpuss_interrupts_dw0_14_IRQHandler ; CPUSS DataWire #0, Channel #14 + DCD cpuss_interrupts_dw0_15_IRQHandler ; CPUSS DataWire #0, Channel #15 + DCD cpuss_interrupts_dw1_0_IRQHandler ; CPUSS DataWire #1, Channel #0 + DCD cpuss_interrupts_dw1_1_IRQHandler ; CPUSS DataWire #1, Channel #1 + DCD cpuss_interrupts_dw1_2_IRQHandler ; CPUSS DataWire #1, Channel #2 + DCD cpuss_interrupts_dw1_3_IRQHandler ; CPUSS DataWire #1, Channel #3 + DCD cpuss_interrupts_dw1_4_IRQHandler ; CPUSS DataWire #1, Channel #4 + DCD cpuss_interrupts_dw1_5_IRQHandler ; CPUSS DataWire #1, Channel #5 + DCD cpuss_interrupts_dw1_6_IRQHandler ; CPUSS DataWire #1, Channel #6 + DCD cpuss_interrupts_dw1_7_IRQHandler ; CPUSS DataWire #1, Channel #7 + DCD cpuss_interrupts_dw1_8_IRQHandler ; CPUSS DataWire #1, Channel #8 + DCD cpuss_interrupts_dw1_9_IRQHandler ; CPUSS DataWire #1, Channel #9 + DCD cpuss_interrupts_dw1_10_IRQHandler ; CPUSS DataWire #1, Channel #10 + DCD cpuss_interrupts_dw1_11_IRQHandler ; CPUSS DataWire #1, Channel #11 + DCD cpuss_interrupts_dw1_12_IRQHandler ; CPUSS DataWire #1, Channel #12 + DCD cpuss_interrupts_dw1_13_IRQHandler ; CPUSS DataWire #1, Channel #13 + DCD cpuss_interrupts_dw1_14_IRQHandler ; CPUSS DataWire #1, Channel #14 + DCD cpuss_interrupts_dw1_15_IRQHandler ; CPUSS DataWire #1, Channel #15 + DCD cpuss_interrupts_fault_0_IRQHandler ; CPUSS Fault Structure Interrupt #0 + DCD cpuss_interrupts_fault_1_IRQHandler ; CPUSS Fault Structure Interrupt #1 + DCD cpuss_interrupt_crypto_IRQHandler ; CRYPTO Accelerator Interrupt + DCD cpuss_interrupt_fm_IRQHandler ; FLASH Macro Interrupt + DCD cpuss_interrupts_cm0_cti_0_IRQHandler ; CM0+ CTI #0 + DCD cpuss_interrupts_cm0_cti_1_IRQHandler ; CM0+ CTI #1 + DCD cpuss_interrupts_cm4_cti_0_IRQHandler ; CM4 CTI #0 + DCD cpuss_interrupts_cm4_cti_1_IRQHandler ; CM4 CTI #1 + DCD tcpwm_0_interrupts_0_IRQHandler ; TCPWM #0, Counter #0 + DCD tcpwm_0_interrupts_1_IRQHandler ; TCPWM #0, Counter #1 + DCD tcpwm_0_interrupts_2_IRQHandler ; TCPWM #0, Counter #2 + DCD tcpwm_0_interrupts_3_IRQHandler ; TCPWM #0, Counter #3 + DCD tcpwm_0_interrupts_4_IRQHandler ; TCPWM #0, Counter #4 + DCD tcpwm_0_interrupts_5_IRQHandler ; TCPWM #0, Counter #5 + DCD tcpwm_0_interrupts_6_IRQHandler ; TCPWM #0, Counter #6 + DCD tcpwm_0_interrupts_7_IRQHandler ; TCPWM #0, Counter #7 + DCD tcpwm_1_interrupts_0_IRQHandler ; TCPWM #1, Counter #0 + DCD tcpwm_1_interrupts_1_IRQHandler ; TCPWM #1, Counter #1 + DCD tcpwm_1_interrupts_2_IRQHandler ; TCPWM #1, Counter #2 + DCD tcpwm_1_interrupts_3_IRQHandler ; TCPWM #1, Counter #3 + DCD tcpwm_1_interrupts_4_IRQHandler ; TCPWM #1, Counter #4 + DCD tcpwm_1_interrupts_5_IRQHandler ; TCPWM #1, Counter #5 + DCD tcpwm_1_interrupts_6_IRQHandler ; TCPWM #1, Counter #6 + DCD tcpwm_1_interrupts_7_IRQHandler ; TCPWM #1, Counter #7 + DCD tcpwm_1_interrupts_8_IRQHandler ; TCPWM #1, Counter #8 + DCD tcpwm_1_interrupts_9_IRQHandler ; TCPWM #1, Counter #9 + DCD tcpwm_1_interrupts_10_IRQHandler ; TCPWM #1, Counter #10 + DCD tcpwm_1_interrupts_11_IRQHandler ; TCPWM #1, Counter #11 + DCD tcpwm_1_interrupts_12_IRQHandler ; TCPWM #1, Counter #12 + DCD tcpwm_1_interrupts_13_IRQHandler ; TCPWM #1, Counter #13 + DCD tcpwm_1_interrupts_14_IRQHandler ; TCPWM #1, Counter #14 + DCD tcpwm_1_interrupts_15_IRQHandler ; TCPWM #1, Counter #15 + DCD tcpwm_1_interrupts_16_IRQHandler ; TCPWM #1, Counter #16 + DCD tcpwm_1_interrupts_17_IRQHandler ; TCPWM #1, Counter #17 + DCD tcpwm_1_interrupts_18_IRQHandler ; TCPWM #1, Counter #18 + DCD tcpwm_1_interrupts_19_IRQHandler ; TCPWM #1, Counter #19 + DCD tcpwm_1_interrupts_20_IRQHandler ; TCPWM #1, Counter #20 + DCD tcpwm_1_interrupts_21_IRQHandler ; TCPWM #1, Counter #21 + DCD tcpwm_1_interrupts_22_IRQHandler ; TCPWM #1, Counter #22 + DCD tcpwm_1_interrupts_23_IRQHandler ; TCPWM #1, Counter #23 + DCD udb_interrupts_0_IRQHandler ; UDB Interrupt #0 + DCD udb_interrupts_1_IRQHandler ; UDB Interrupt #1 + DCD udb_interrupts_2_IRQHandler ; UDB Interrupt #2 + DCD udb_interrupts_3_IRQHandler ; UDB Interrupt #3 + DCD udb_interrupts_4_IRQHandler ; UDB Interrupt #4 + DCD udb_interrupts_5_IRQHandler ; UDB Interrupt #5 + DCD udb_interrupts_6_IRQHandler ; UDB Interrupt #6 + DCD udb_interrupts_7_IRQHandler ; UDB Interrupt #7 + DCD udb_interrupts_8_IRQHandler ; UDB Interrupt #8 + DCD udb_interrupts_9_IRQHandler ; UDB Interrupt #9 + DCD udb_interrupts_10_IRQHandler ; UDB Interrupt #10 + DCD udb_interrupts_11_IRQHandler ; UDB Interrupt #11 + DCD udb_interrupts_12_IRQHandler ; UDB Interrupt #12 + DCD udb_interrupts_13_IRQHandler ; UDB Interrupt #13 + DCD udb_interrupts_14_IRQHandler ; UDB Interrupt #14 + DCD udb_interrupts_15_IRQHandler ; UDB Interrupt #15 + DCD pass_interrupt_sar_IRQHandler ; SAR ADC interrupt + DCD audioss_interrupt_i2s_IRQHandler ; I2S Audio interrupt + DCD audioss_interrupt_pdm_IRQHandler ; PDM/PCM Audio interrupt + DCD profile_interrupt_IRQHandler ; Energy Profiler interrupt + DCD smif_interrupt_IRQHandler ; Serial Memory Interface interrupt + DCD usb_interrupt_hi_IRQHandler ; USB Interrupt + DCD usb_interrupt_med_IRQHandler ; USB Interrupt + DCD usb_interrupt_lo_IRQHandler ; USB Interrupt + DCD pass_interrupt_dacs_IRQHandler ; Consolidated interrrupt for all DACs + +__Vectors_End + +__Vectors EQU __vector_table +__Vectors_Size EQU __Vectors_End - __Vectors + + SECTION .intvec_ram:DATA:REORDER:NOROOT(2) +__ramVectors + DS32 __Vectors_Size + + + THUMB + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default handlers +;; + PUBWEAK Default_Handler + SECTION .text:CODE:REORDER:NOROOT(2) +Default_Handler + B Default_Handler + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Saves and disables the interrupts +;; + PUBLIC Cy_SaveIRQ + SECTION .text:CODE:REORDER:NOROOT(2) +Cy_SaveIRQ + MRS r0, PRIMASK + CPSID I + BX LR + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Restores the interrupts +;; + PUBLIC Cy_RestoreIRQ + SECTION .text:CODE:REORDER:NOROOT(2) +Cy_RestoreIRQ + MSR PRIMASK, r0 + BX LR + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Weak function for startup customization +;; + PUBWEAK Cy_OnResetUser + SECTION .text:CODE:REORDER:NOROOT(2) +Cy_OnResetUser + BX LR + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Define strong version to return zero for +;; __iar_program_start to skip data sections +;; initialization. +;; + PUBLIC __low_level_init + SECTION .text:CODE:REORDER:NOROOT(2) +__low_level_init + MOVS R0, #1 + BX LR + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + PUBWEAK Reset_Handler + SECTION .text:CODE:REORDER:NOROOT(2) +Reset_Handler + + ; Define strong function for startup customization + LDR R0, =Cy_OnResetUser + BLX R0 + + ; Copy vectors from ROM to RAM + LDR r1, =__vector_table + LDR r0, =__ramVectors + LDR r2, =__Vectors_Size +intvec_copy + LDR r3, [r1] + STR r3, [r0] + ADDS r0, r0, #4 + ADDS r1, r1, #4 + SUBS r2, r2, #1 + CMP r2, #0 + BNE intvec_copy + + ; Update Vector Table Offset Register + LDR r0, =__ramVectors + LDR r1, =0xE000ED08 + STR r0, [r1] + dsb + + ; Enable the FPU if used + LDR R0, =Cy_SystemInitFpuEnable + BLX R0 + + LDR R0, =__iar_program_start + BLX R0 + +; Should never get here +Cy_Main_Exited + B Cy_Main_Exited + + + PUBWEAK NMI_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +NMI_Handler + B NMI_Handler + + + PUBWEAK Cy_SysLib_FaultHandler + SECTION .text:CODE:REORDER:NOROOT(1) +Cy_SysLib_FaultHandler + B Cy_SysLib_FaultHandler + + PUBWEAK HardFault_Wrapper + SECTION .text:CODE:REORDER:NOROOT(1) +HardFault_Wrapper + IMPORT Cy_SysLib_FaultHandler + movs r0, #4 + mov r1, LR + tst r0, r1 + beq L_MSP + mrs r0, PSP + b L_API_call +L_MSP + mrs r0, MSP +L_API_call + ; Storing LR content for Creator call stack trace + push {LR} + bl Cy_SysLib_FaultHandler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +HardFault_Handler + B HardFault_Wrapper + + PUBWEAK MemManage_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +MemManage_Handler + B HardFault_Wrapper + + PUBWEAK BusFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +BusFault_Handler + B HardFault_Wrapper + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +UsageFault_Handler + B HardFault_Wrapper + + PUBWEAK SVC_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:REORDER:NOROOT(1) +SysTick_Handler + B SysTick_Handler + + + ; External interrupts + PUBWEAK ioss_interrupts_gpio_0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_0_IRQHandler + B ioss_interrupts_gpio_0_IRQHandler + + PUBWEAK ioss_interrupts_gpio_1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_1_IRQHandler + B ioss_interrupts_gpio_1_IRQHandler + + PUBWEAK ioss_interrupts_gpio_2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_2_IRQHandler + B ioss_interrupts_gpio_2_IRQHandler + + PUBWEAK ioss_interrupts_gpio_3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_3_IRQHandler + B ioss_interrupts_gpio_3_IRQHandler + + PUBWEAK ioss_interrupts_gpio_4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_4_IRQHandler + B ioss_interrupts_gpio_4_IRQHandler + + PUBWEAK ioss_interrupts_gpio_5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_5_IRQHandler + B ioss_interrupts_gpio_5_IRQHandler + + PUBWEAK ioss_interrupts_gpio_6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_6_IRQHandler + B ioss_interrupts_gpio_6_IRQHandler + + PUBWEAK ioss_interrupts_gpio_7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_7_IRQHandler + B ioss_interrupts_gpio_7_IRQHandler + + PUBWEAK ioss_interrupts_gpio_8_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_8_IRQHandler + B ioss_interrupts_gpio_8_IRQHandler + + PUBWEAK ioss_interrupts_gpio_9_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_9_IRQHandler + B ioss_interrupts_gpio_9_IRQHandler + + PUBWEAK ioss_interrupts_gpio_10_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_10_IRQHandler + B ioss_interrupts_gpio_10_IRQHandler + + PUBWEAK ioss_interrupts_gpio_11_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_11_IRQHandler + B ioss_interrupts_gpio_11_IRQHandler + + PUBWEAK ioss_interrupts_gpio_12_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_12_IRQHandler + B ioss_interrupts_gpio_12_IRQHandler + + PUBWEAK ioss_interrupts_gpio_13_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_13_IRQHandler + B ioss_interrupts_gpio_13_IRQHandler + + PUBWEAK ioss_interrupts_gpio_14_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupts_gpio_14_IRQHandler + B ioss_interrupts_gpio_14_IRQHandler + + PUBWEAK ioss_interrupt_gpio_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupt_gpio_IRQHandler + B ioss_interrupt_gpio_IRQHandler + + PUBWEAK ioss_interrupt_vdd_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +ioss_interrupt_vdd_IRQHandler + B ioss_interrupt_vdd_IRQHandler + + PUBWEAK lpcomp_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +lpcomp_interrupt_IRQHandler + B lpcomp_interrupt_IRQHandler + + PUBWEAK scb_8_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +scb_8_interrupt_IRQHandler + B scb_8_interrupt_IRQHandler + + PUBWEAK srss_interrupt_mcwdt_0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +srss_interrupt_mcwdt_0_IRQHandler + B srss_interrupt_mcwdt_0_IRQHandler + + PUBWEAK srss_interrupt_mcwdt_1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +srss_interrupt_mcwdt_1_IRQHandler + B srss_interrupt_mcwdt_1_IRQHandler + + PUBWEAK srss_interrupt_backup_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +srss_interrupt_backup_IRQHandler + B srss_interrupt_backup_IRQHandler + + PUBWEAK srss_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +srss_interrupt_IRQHandler + B srss_interrupt_IRQHandler + + PUBWEAK pass_interrupt_ctbs_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +pass_interrupt_ctbs_IRQHandler + B pass_interrupt_ctbs_IRQHandler + + PUBWEAK bless_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +bless_interrupt_IRQHandler + B bless_interrupt_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_0_IRQHandler + B cpuss_interrupts_ipc_0_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_1_IRQHandler + B cpuss_interrupts_ipc_1_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_2_IRQHandler + B cpuss_interrupts_ipc_2_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_3_IRQHandler + B cpuss_interrupts_ipc_3_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_4_IRQHandler + B cpuss_interrupts_ipc_4_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_5_IRQHandler + B cpuss_interrupts_ipc_5_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_6_IRQHandler + B cpuss_interrupts_ipc_6_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_7_IRQHandler + B cpuss_interrupts_ipc_7_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_8_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_8_IRQHandler + B cpuss_interrupts_ipc_8_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_9_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_9_IRQHandler + B cpuss_interrupts_ipc_9_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_10_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_10_IRQHandler + B cpuss_interrupts_ipc_10_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_11_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_11_IRQHandler + B cpuss_interrupts_ipc_11_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_12_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_12_IRQHandler + B cpuss_interrupts_ipc_12_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_13_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_13_IRQHandler + B cpuss_interrupts_ipc_13_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_14_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_14_IRQHandler + B cpuss_interrupts_ipc_14_IRQHandler + + PUBWEAK cpuss_interrupts_ipc_15_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_ipc_15_IRQHandler + B cpuss_interrupts_ipc_15_IRQHandler + + PUBWEAK scb_0_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +scb_0_interrupt_IRQHandler + B scb_0_interrupt_IRQHandler + + PUBWEAK scb_1_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +scb_1_interrupt_IRQHandler + B scb_1_interrupt_IRQHandler + + PUBWEAK scb_2_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +scb_2_interrupt_IRQHandler + B scb_2_interrupt_IRQHandler + + PUBWEAK scb_3_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +scb_3_interrupt_IRQHandler + B scb_3_interrupt_IRQHandler + + PUBWEAK scb_4_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +scb_4_interrupt_IRQHandler + B scb_4_interrupt_IRQHandler + + PUBWEAK scb_5_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +scb_5_interrupt_IRQHandler + B scb_5_interrupt_IRQHandler + + PUBWEAK scb_6_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +scb_6_interrupt_IRQHandler + B scb_6_interrupt_IRQHandler + + PUBWEAK scb_7_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +scb_7_interrupt_IRQHandler + B scb_7_interrupt_IRQHandler + + PUBWEAK csd_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +csd_interrupt_IRQHandler + B csd_interrupt_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_0_IRQHandler + B cpuss_interrupts_dw0_0_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_1_IRQHandler + B cpuss_interrupts_dw0_1_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_2_IRQHandler + B cpuss_interrupts_dw0_2_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_3_IRQHandler + B cpuss_interrupts_dw0_3_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_4_IRQHandler + B cpuss_interrupts_dw0_4_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_5_IRQHandler + B cpuss_interrupts_dw0_5_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_6_IRQHandler + B cpuss_interrupts_dw0_6_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_7_IRQHandler + B cpuss_interrupts_dw0_7_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_8_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_8_IRQHandler + B cpuss_interrupts_dw0_8_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_9_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_9_IRQHandler + B cpuss_interrupts_dw0_9_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_10_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_10_IRQHandler + B cpuss_interrupts_dw0_10_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_11_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_11_IRQHandler + B cpuss_interrupts_dw0_11_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_12_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_12_IRQHandler + B cpuss_interrupts_dw0_12_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_13_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_13_IRQHandler + B cpuss_interrupts_dw0_13_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_14_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_14_IRQHandler + B cpuss_interrupts_dw0_14_IRQHandler + + PUBWEAK cpuss_interrupts_dw0_15_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw0_15_IRQHandler + B cpuss_interrupts_dw0_15_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_0_IRQHandler + B cpuss_interrupts_dw1_0_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_1_IRQHandler + B cpuss_interrupts_dw1_1_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_2_IRQHandler + B cpuss_interrupts_dw1_2_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_3_IRQHandler + B cpuss_interrupts_dw1_3_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_4_IRQHandler + B cpuss_interrupts_dw1_4_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_5_IRQHandler + B cpuss_interrupts_dw1_5_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_6_IRQHandler + B cpuss_interrupts_dw1_6_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_7_IRQHandler + B cpuss_interrupts_dw1_7_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_8_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_8_IRQHandler + B cpuss_interrupts_dw1_8_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_9_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_9_IRQHandler + B cpuss_interrupts_dw1_9_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_10_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_10_IRQHandler + B cpuss_interrupts_dw1_10_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_11_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_11_IRQHandler + B cpuss_interrupts_dw1_11_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_12_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_12_IRQHandler + B cpuss_interrupts_dw1_12_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_13_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_13_IRQHandler + B cpuss_interrupts_dw1_13_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_14_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_14_IRQHandler + B cpuss_interrupts_dw1_14_IRQHandler + + PUBWEAK cpuss_interrupts_dw1_15_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_dw1_15_IRQHandler + B cpuss_interrupts_dw1_15_IRQHandler + + PUBWEAK cpuss_interrupts_fault_0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_fault_0_IRQHandler + B cpuss_interrupts_fault_0_IRQHandler + + PUBWEAK cpuss_interrupts_fault_1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_fault_1_IRQHandler + B cpuss_interrupts_fault_1_IRQHandler + + PUBWEAK cpuss_interrupt_crypto_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupt_crypto_IRQHandler + B cpuss_interrupt_crypto_IRQHandler + + PUBWEAK cpuss_interrupt_fm_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupt_fm_IRQHandler + B cpuss_interrupt_fm_IRQHandler + + PUBWEAK cpuss_interrupts_cm0_cti_0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_cm0_cti_0_IRQHandler + B cpuss_interrupts_cm0_cti_0_IRQHandler + + PUBWEAK cpuss_interrupts_cm0_cti_1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_cm0_cti_1_IRQHandler + B cpuss_interrupts_cm0_cti_1_IRQHandler + + PUBWEAK cpuss_interrupts_cm4_cti_0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_cm4_cti_0_IRQHandler + B cpuss_interrupts_cm4_cti_0_IRQHandler + + PUBWEAK cpuss_interrupts_cm4_cti_1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +cpuss_interrupts_cm4_cti_1_IRQHandler + B cpuss_interrupts_cm4_cti_1_IRQHandler + + PUBWEAK tcpwm_0_interrupts_0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_0_interrupts_0_IRQHandler + B tcpwm_0_interrupts_0_IRQHandler + + PUBWEAK tcpwm_0_interrupts_1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_0_interrupts_1_IRQHandler + B tcpwm_0_interrupts_1_IRQHandler + + PUBWEAK tcpwm_0_interrupts_2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_0_interrupts_2_IRQHandler + B tcpwm_0_interrupts_2_IRQHandler + + PUBWEAK tcpwm_0_interrupts_3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_0_interrupts_3_IRQHandler + B tcpwm_0_interrupts_3_IRQHandler + + PUBWEAK tcpwm_0_interrupts_4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_0_interrupts_4_IRQHandler + B tcpwm_0_interrupts_4_IRQHandler + + PUBWEAK tcpwm_0_interrupts_5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_0_interrupts_5_IRQHandler + B tcpwm_0_interrupts_5_IRQHandler + + PUBWEAK tcpwm_0_interrupts_6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_0_interrupts_6_IRQHandler + B tcpwm_0_interrupts_6_IRQHandler + + PUBWEAK tcpwm_0_interrupts_7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_0_interrupts_7_IRQHandler + B tcpwm_0_interrupts_7_IRQHandler + + PUBWEAK tcpwm_1_interrupts_0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_0_IRQHandler + B tcpwm_1_interrupts_0_IRQHandler + + PUBWEAK tcpwm_1_interrupts_1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_1_IRQHandler + B tcpwm_1_interrupts_1_IRQHandler + + PUBWEAK tcpwm_1_interrupts_2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_2_IRQHandler + B tcpwm_1_interrupts_2_IRQHandler + + PUBWEAK tcpwm_1_interrupts_3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_3_IRQHandler + B tcpwm_1_interrupts_3_IRQHandler + + PUBWEAK tcpwm_1_interrupts_4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_4_IRQHandler + B tcpwm_1_interrupts_4_IRQHandler + + PUBWEAK tcpwm_1_interrupts_5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_5_IRQHandler + B tcpwm_1_interrupts_5_IRQHandler + + PUBWEAK tcpwm_1_interrupts_6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_6_IRQHandler + B tcpwm_1_interrupts_6_IRQHandler + + PUBWEAK tcpwm_1_interrupts_7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_7_IRQHandler + B tcpwm_1_interrupts_7_IRQHandler + + PUBWEAK tcpwm_1_interrupts_8_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_8_IRQHandler + B tcpwm_1_interrupts_8_IRQHandler + + PUBWEAK tcpwm_1_interrupts_9_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_9_IRQHandler + B tcpwm_1_interrupts_9_IRQHandler + + PUBWEAK tcpwm_1_interrupts_10_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_10_IRQHandler + B tcpwm_1_interrupts_10_IRQHandler + + PUBWEAK tcpwm_1_interrupts_11_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_11_IRQHandler + B tcpwm_1_interrupts_11_IRQHandler + + PUBWEAK tcpwm_1_interrupts_12_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_12_IRQHandler + B tcpwm_1_interrupts_12_IRQHandler + + PUBWEAK tcpwm_1_interrupts_13_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_13_IRQHandler + B tcpwm_1_interrupts_13_IRQHandler + + PUBWEAK tcpwm_1_interrupts_14_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_14_IRQHandler + B tcpwm_1_interrupts_14_IRQHandler + + PUBWEAK tcpwm_1_interrupts_15_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_15_IRQHandler + B tcpwm_1_interrupts_15_IRQHandler + + PUBWEAK tcpwm_1_interrupts_16_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_16_IRQHandler + B tcpwm_1_interrupts_16_IRQHandler + + PUBWEAK tcpwm_1_interrupts_17_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_17_IRQHandler + B tcpwm_1_interrupts_17_IRQHandler + + PUBWEAK tcpwm_1_interrupts_18_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_18_IRQHandler + B tcpwm_1_interrupts_18_IRQHandler + + PUBWEAK tcpwm_1_interrupts_19_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_19_IRQHandler + B tcpwm_1_interrupts_19_IRQHandler + + PUBWEAK tcpwm_1_interrupts_20_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_20_IRQHandler + B tcpwm_1_interrupts_20_IRQHandler + + PUBWEAK tcpwm_1_interrupts_21_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_21_IRQHandler + B tcpwm_1_interrupts_21_IRQHandler + + PUBWEAK tcpwm_1_interrupts_22_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_22_IRQHandler + B tcpwm_1_interrupts_22_IRQHandler + + PUBWEAK tcpwm_1_interrupts_23_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +tcpwm_1_interrupts_23_IRQHandler + B tcpwm_1_interrupts_23_IRQHandler + + PUBWEAK udb_interrupts_0_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_0_IRQHandler + B udb_interrupts_0_IRQHandler + + PUBWEAK udb_interrupts_1_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_1_IRQHandler + B udb_interrupts_1_IRQHandler + + PUBWEAK udb_interrupts_2_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_2_IRQHandler + B udb_interrupts_2_IRQHandler + + PUBWEAK udb_interrupts_3_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_3_IRQHandler + B udb_interrupts_3_IRQHandler + + PUBWEAK udb_interrupts_4_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_4_IRQHandler + B udb_interrupts_4_IRQHandler + + PUBWEAK udb_interrupts_5_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_5_IRQHandler + B udb_interrupts_5_IRQHandler + + PUBWEAK udb_interrupts_6_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_6_IRQHandler + B udb_interrupts_6_IRQHandler + + PUBWEAK udb_interrupts_7_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_7_IRQHandler + B udb_interrupts_7_IRQHandler + + PUBWEAK udb_interrupts_8_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_8_IRQHandler + B udb_interrupts_8_IRQHandler + + PUBWEAK udb_interrupts_9_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_9_IRQHandler + B udb_interrupts_9_IRQHandler + + PUBWEAK udb_interrupts_10_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_10_IRQHandler + B udb_interrupts_10_IRQHandler + + PUBWEAK udb_interrupts_11_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_11_IRQHandler + B udb_interrupts_11_IRQHandler + + PUBWEAK udb_interrupts_12_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_12_IRQHandler + B udb_interrupts_12_IRQHandler + + PUBWEAK udb_interrupts_13_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_13_IRQHandler + B udb_interrupts_13_IRQHandler + + PUBWEAK udb_interrupts_14_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_14_IRQHandler + B udb_interrupts_14_IRQHandler + + PUBWEAK udb_interrupts_15_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +udb_interrupts_15_IRQHandler + B udb_interrupts_15_IRQHandler + + PUBWEAK pass_interrupt_sar_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +pass_interrupt_sar_IRQHandler + B pass_interrupt_sar_IRQHandler + + PUBWEAK audioss_interrupt_i2s_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +audioss_interrupt_i2s_IRQHandler + B audioss_interrupt_i2s_IRQHandler + + PUBWEAK audioss_interrupt_pdm_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +audioss_interrupt_pdm_IRQHandler + B audioss_interrupt_pdm_IRQHandler + + PUBWEAK profile_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +profile_interrupt_IRQHandler + B profile_interrupt_IRQHandler + + PUBWEAK smif_interrupt_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +smif_interrupt_IRQHandler + B smif_interrupt_IRQHandler + + PUBWEAK usb_interrupt_hi_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +usb_interrupt_hi_IRQHandler + B usb_interrupt_hi_IRQHandler + + PUBWEAK usb_interrupt_med_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +usb_interrupt_med_IRQHandler + B usb_interrupt_med_IRQHandler + + PUBWEAK usb_interrupt_lo_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +usb_interrupt_lo_IRQHandler + B usb_interrupt_lo_IRQHandler + + PUBWEAK pass_interrupt_dacs_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(1) +pass_interrupt_dacs_IRQHandler + B pass_interrupt_dacs_IRQHandler + + + END + + +; [] END OF FILE diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/hex/LICENSE.txt b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/hex/LICENSE.txt new file mode 100644 index 0000000000..4ac41bfc74 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/hex/LICENSE.txt @@ -0,0 +1,52 @@ +Copyright (c) 2017-2018 Future Electronics. +Copyright (c) 2007-2018 Cypress Semiconductor. + +Permissive Binary License + +Version 1.0, September 2015 + +Redistribution. Redistribution and use in binary form, without +modification, are permitted provided that the following conditions are +met: + +1) Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. + +2) Unless to the extent explicitly permitted by law, no reverse + engineering, decompilation, or disassembly of this software is + permitted. + +3) Redistribution as part of a software development kit must include the + accompanying file named "DEPENDENCIES" and any dependencies listed in + that file. + +4) Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +Limited patent license. The copyright holders (and contributors) grant a +worldwide, non-exclusive, no-charge, royalty-free patent license to +make, have made, use, offer to sell, sell, import, and otherwise +transfer this software, where such license applies only to those patent +claims licensable by the copyright holders (and contributors) that are +necessarily infringed by this software. This patent license shall not +apply to any combinations that include this software. No hardware is +licensed hereunder. + +If you institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the software +itself infringes your patent(s), then your rights granted under this +license shall terminate as of the date such litigation is filed. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/hex/README.md b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/hex/README.md new file mode 100644 index 0000000000..abd8627062 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/hex/README.md @@ -0,0 +1,16 @@ +README for pre-compiled PSoC 6 Cortex M0+ core images +===================================================== + +This folder contains precompiled program images for the CM0+ core of the PSoC 6(63xx) MCU suitable for use with MBed OS applications running on CM4 core. Two images are available: + +* `psoc63_m0_default_1.01.hex` + + This image contains basic code, that brings up the chip, starts CM4 core and puts CM0+ core into a deep sleep. It is suitable for use with all Mbed applications except those intendif to use BLE feature. + +* `psoc63_m0_ble_controller_1.01.hex` + + This image brings up the chip, starts CM4 core and runs BLE HCI controller for the build-in BLE device. This image is suitable for use with Mbed BLE applications. + +The images are 'bare metal' code prepared with Cypress PSoC Creator IDE and are toolchain agnostic, i.e. can be used with CM4 Mbed applications build with any supported toolchain. + +**These images were prepared by Future Electronics and are made available under the conditions of Permissive Binary Licence, see file LICENSE.txt** diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/hex/psoc63_m0_ble_controller_1.01.hex b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/hex/psoc63_m0_ble_controller_1.01.hex new file mode 100644 index 0000000000..3942055ebc --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/hex/psoc63_m0_ble_controller_1.01.hex @@ -0,0 +1,1655 @@ +:020000041000EA +:4000000000000108310100100D00000095010010000000000000000000000000000000000000000000000000000000009101001000000000000000009101001091010010DC +:400040009101001061080010910100109101001091010010910100109101001091010010910100109101001091010010910100109101001091010010910100109101001089 +:400080009101001091010010910100109101001091010010910100109101001091010010910100109101001091010010910100109101001091010010910100109101001020 +:4000C00010B5064C2378002B07D1054B002B02D0044800E000BF0123237010BD2819000800000000C0510010084B10B5002B03D00749084800E000BF07480368002B00D11A +:4001000010BD064B002BFBD09847F9E7000000002C190008C051001094020008000000007047EFF3108072B6704780F310887047FFF7F6FF72B6104C104DAC4209DA2168F0 +:400140006268A368043B02DBC858D050FAE70C34F3E70B490B4A0020521A02DD043A8850FCDC094809490860BFF34F8F00F0FCF800F01EF8FEE70000E4950110FC950110BB +:40018000281900089C2800080000000808ED00E0FEE7FEE700B504207146084202D0EFF3098001E0EFF30880043001F067FEFEE7002110B5080000F063FA002000F0C2FAAB +:4001C00000F0DEF962B60B4B5B689B0301D501F0F7FD002000F09CFDFA20400001F006FE054800F031F905F0BBF8002001F0AEFDF9E7C0460000264000000810F8B5E023D7 +:40020000504C9B00E2580F231340D022990092000919885807224C4D0240032A05D0042A05D0002A0FD0494811E028680FE0C022920089581F220A40112A01D0132A04D198 +:400240008020000203E0424801E0FA20C001002B27D1B223B1210322DB00C900E658635867581B0F3F0F1340174205D0354F7958090F0A40012A01D1F20701D4032B3AD1B4 +:40028000B023344ADB00E658A158E758C904C90C02F0B8FBB603F901B60BC90F7043013127E0012B27D1C823C0210322DB00C900E658635867583F0F174205D0214F7958EF +:4002C000090F0A40012A01D1F20703D49B009B0F032B10D1C0227F23D200A758A1583B401F27A658090A3940584302F08BFB310C394002F087FBE0239B00E3589B069B0F81 +:40030000D840154B68601C691969240A090E013102F078FBE1B2A860013102F073FB0F4BE860286104000E49C01802F06BFBFA210C4B28758900E01802F064FBA861C0030A +:40034000E861F8BD00002640C000000800366E0100127A0084050000000021403F420F0040420F00E7030000B021E02010B530241F4BC9005A588000520052085A501A5814 +:40038000A2431A50802252045A501A491A4A80209950A021043289019950FF21174AC005995081315A5892009208024380205A505A580006024301205A505A5882435A505B +:4003C00000F06CFBFFF71AFF00F056FA00F05EFA01F0EAF9B0235B055A78002A02D05B78212B03D10022064BDA605A6010BDC0460000264001000200840500008C0500008A +:40040000E0002340024BD86F032318407047C0460400214010B5FFF784FE074A074BD16F0B4007490B43D367102306490A681A42FCD0FFF77AFE10BD04002140FCFF00004B +:400440000100FA058800214070B50F4C0600FFF768FEE36F0500DB439B0701D1FFF7DAFFB0230A4A9B00D650E26F094B09491340094A1343E36710230A681A42FCD02800DF +:40048000FFF753FE70BDC0460400214000002140FCFF0000880021400300FA05436870B50400012B02D1007B06F07CF92500A2682B1B01359A4203D9E87B06F073F9F6E758 +:4004C00070BD000010B5034A0349002000F0C4FA10BDC046B96700109D04001007B50022030000911000110000F03AFA07BD10B500F0ACFA10BD10B500F0CAFA10BD10B541 +:400500000400007B00F0F2F8606010BD10B50400007B216900F0B4F8606010BD10B5037B0169180000F0CCF810BD10B50400C06800F008F9606010BD10B5C06800F016F93D +:4005400010BD10B50400C06800F022F9606010BD10B5C06800F036F910BD10B504000C23C05E00F055F8606010BD10B50C23C05E00F06EF810BD10B5C06800F035F910BD5F +:4005800010B500221849042000F0F4FD01221749042000F0EFFD02221549042000F0EAFD03221449042000F0E5FD04221249100000F0E0FD05221149042000F0DBFD062283 +:4005C0000F49042000F0D6FD07220E49042000F0D1FD08220C49042000F0CCFD09220B49042000F0C7FD10BDFF0400100D0500101D0500102B05001039050010430500108D +:40060000510500105B0500106B0500107705001070B507260512EDB206400D2D11D801F094FC0A4901224B5D1C003441144003D1B24013434B5501E00124644201F089FC05 +:4006400001E001246442200070BDC0464419000870B50412E4B20D2C0FD80725054001F074FC064901220B5D1E002E41164202D0AA4093430B5501F06CFC70BD44190008B7 +:40068000F8B50C00050001F060FC0C2301225D431300A3401A00094E71198F683A4008D13B43AD598B60631C4B60AB4202D94A6000E0FF2401F04DFC2000F8BDE0000008FD +:4006C00070B50C00050001F040FC01210C23A1406B43054AD3189A680A4201D08A439A6001F037FC70BDC046E0000008F0B50C2485B0019001F029FC019B114D5C432B19CA +:400700005B68029003932E1971680198FFF7B8FF0700FF280DD173682A59934201D9002373602A1953680399994202D001335360E9E7029801F00DFC380005B0F0BDC04627 +:40074000E000000810B5040007280AD801F0FDFB054B0E331A5D002A01D101321A5501F0F8FB0120404210BD4419000810B5040007280AD801F0E9FB044B0E331A5D012A8E +:4007800001D100221A5501F0E4FB10BD4419000870B505001F280ED801F0D7FB084B30335C5D002C02D101225A5501E00124644201F0CFFB01E001246442200070BDC04614 +:4007C000E000000810B504001F280AD801F0BDFB044B30331A5D012A01D100221A5501F0B8FB10BDE000000870B5B024C025144B144A15496405ED00E35CA25C615C665D5A +:400800003F251F242A400C4024039201224311002B407F2219430B003240520413430B4A1C0A110050310B701B0C8B7000234C7011005031595CC1540133062BF8D170BD5A +:40084000040600000506000003060000E000000810B50248B03000F0ABFC10BDDC19000810B50248583000F0A3FC10BDDC19000810B5FFF7F5FF10BD10B5034A8021603271 +:40088000042000F019FB10BDDC1A000870B501F05CFB0500094800F0DFFB094C200000F00DFC2000343000F009FC2000683000F005FC280001F04DFB70BDC046DC19000897 +:4008C000404500108A22044952000B6853430022CB181A717047C046CC1B00088A230A495B000A6809485A438A18926810B5920082180868D26A4343CB18002119718A42FF +:4009000000D0904710BDC046CC1B0008CC1D00088A21084A490013684B43D3181B79002BF9D101211533FF334343D318197110607047C046CC1B00088A20074A074940005C +:40094000D36C4343CB181B79002BF9D1D06CD36C59424B41D3647047CC1D0008CC1B0008F0B585B0039300238A2714001E00029001917F000A9A96424FD2FFF7DDFF03004B +:400980007B432D490090CA18D46000220431944206D00198855CD018081805740132F6E7019A350012190192721CFF32944622499B1B0A98AA1B0C00A8420BD9654507D045 +:4009C000039A1E48545DEA18821814750135F0E780225200009B00987B43E418029B2261A360FFF795FF164B134ADB6C7B43D3181E79009BF6B27B43D2180832114B002E8F +:400A000000D1114B0221032000F086FB0028EAD17342734104002E00ACE7002CADD1002B07D0029B064A9B00D318DB6A002B00D0984705B0F0BDC046CC1B0008D01B000839 +:400A4000CC1D0008DD080010C508001010B5022000F004FC10BD000070B5040015000200022000F087FB0849022000F097FB074AA400136D14190133E5621365012B01D1B3 +:400A8000FFF7E4FF70BDC046C5080010CC1D000810B5022000F0C8FB10BD0000F0B5962191B0002001F002FA01F0D8F9002801D101F0C6F9012001F077F8E8217E4C7F4BC1 +:400AC000626C89011A400A436264626C0193120AD2B23A2A04D1636C794A13400B4363643422002103A803F00DFD03AA0021754800F002FF3422002103A803F003FD03AA9F +:400B00000121704800F0F8FE0822042623686E4D134323602369334207D1002D04D0012001F07EF9013DF5E701E0002D00D1FEE7A02603220127654CF600A35903AD934305 +:400B40003B43A351D2196249280003F0D2FC280001F06AFB5F4901980B685F4A03400B608021136949041B021B0A0B4313611369019902200B401361E0230F219B00E2588E +:400B80008A433A43E250E25821318A438021E250E25809060A43E250002100F075FB0021032000F071FB0021042000F06DFB0321002000F069FB0321380000F065FB444B34 +:400BC0000522191D280003F094FC2900380000F091FB002800D0FEE74049380000F0DCFB002800D0FEE73E4B3E4AE1580A403A43E250E1583C4A0A408021E250E258090666 +:400C00000A43E250A259394B1340A351A259384B13408022920113438022A351A35912021343A351244B1A68324B1340224A136001F092F9C0235B00E3583B4204D12E4AC4 +:400C4000A3585B005B08A3506421002001F02EF9C0230021294A1B01D15080210901535801981B4C0340802080010343535080232349DB00D150D35823002A000C3343CBE4 +:400C800043C243CB43C243CB43C229000D4800F0ADFE23002A00303313CB13C213CB13C213CB13C22900174800F0A0FE164A174B1A6011B0F0BDC04600002740FF00FFFFFD +:400CC000FFC5FFDF0000324020A1070000002640EC45001090002140000021401027000004050000FEFCFFFFFFFF00FFFFF0FFFFFF8FFFFFFFFCFFFF0C0500000000014026 +:400D000000FF00800003324001001180000E1F4110B5054801F07EF90122044B1A70002801D101F083F910BD38010008201E0008030010B5FF24800882009B1ADB009C402D +:400D40009940E243214007282DD8174B01F050FE04090E13181D2227186A02401143196221E0586A0240114359621CE0986A02401143996217E0D86A02401143D96212E061 +:400D8000186B0240114319630DE0586B02401143596308E0986B02401143996303E0D86B02401143D96310BD00002140064B10309A68064B9A4203D183009858995002E027 +:400DC000034B8000C058704700ED00E00000000800000010F7B5051E01913DD00023C05E002802DBA978FFF7A3FF6A680023E85E9201002812DB1A4B81088900C918FF23A7 +:400E000003271C00C0250740FF00BC401A40BA40AD004E59A64332434A5113E003250F2381B20B402940A940FC352F002A408F408A40083B9B080B4C9B001B19DE69BE43D0 +:400E40003243DA61074B00259A68074B9A4204D10199FFF7ABFF00E0044D2800FEBDC04600E100E000ED00E000000008010056000369002B03DA89B24160002000E001486C +:400E80007047C04601008A000368002B01DB034803E089B2C26081600020704701008A000369002B03DAC36800200B6000E001487047C04601008A0070B5040010000F2C9B +:400EC0002BD8002A07D1002927D1154B6401E418144B1C6022E000291FD01F260E401CD1104D0F4B6401E4186960AA60CA0831002C6003F007FB31002000FFF7B9FF3100F7 +:400F00002A1D2868FFF7C0FF011E04D12868FFF7AFFF011E02D0044900E00449080070BD00002340241E000801018A0003018A00194BF7B51A680193D76804003B680E007C +:400F4000834223D90025A94202D100F0FEFF0500019B18680368002B01DB104C10E063095A01A41A012279689B00CB181968A2400C0014400CD10A431A600021FFF778FF05 +:400F8000002E07D1280000F0E4FF03E0044C01E0044CF2E72000FEBD241E00080301880004018A0002018800194BF7B51A680193D76804003B680E00834223D90025A9423D +:400FC00002D100F0C2FF0500019B18680368002B01DB104C10E063095A01A41A0122A24079689B00CB18196811420DD00024914319600021FFF73CFF002E07D1280000F013 +:40100000A8FF03E0044C01E0044CF2E72000FEBD241E00080301880004018A00020188000A4B1B68DA68136883420DD9430999005B01C31A0120984052688B581840431E54 +:401040009841034BC01800E002487047241E00080001880004018A00024B1A68002A00D118607047301E0008F0B52C246043104C1E0024681F0A2018FF2426403C400D4F7F +:4010800006607601F61906610B4E1B0C44606401A4191E04836033434461A3600023059DC261016283619D4201D02B888381F0BD301E00080000234000102340F0B50389D4 +:4010C00085B002AD2B800368066A1933AB704368476A0095826AC16A040003930369C068FFF7C2FF00213B000A0000913000FFF7BBFF216B2800FFF76DFE0023EA5E002AB1 +:4011000005DB1F231A401E3B9340024A136005B0F0BDC04600E100E0F7B52C25124C6843276801933C182669002E08D04D4379198869002805D13568002D02DA03E00B4820 +:4011400011E00B480FE06768012425004B689D4013882D041D431560F2608C61BC40019BA4B24B62B460FEBD301E000804028A0007028A002C235843064B1B681818C369B6 +:40118000934204D9036A9200D150002000E002487047C046301E00080A028A00034B1A682C235843101881627047C046301E000873B5002642690400D56801962B0CB34295 +:4011C0001CD01B040069136013680369B34215DA01A9FFF765FEB0420CD10198E26903681E0C0378934205D2226A9B009B58002B00D0984731002069FFF73AFEADB2002D63 +:401200000ED063691D6000251B68636AAB4202D09847656203E0A36A002B00D09847A56163691B6873BD00000A4B1A682C23584310180C23C25E002A09DB1F231A401E3B23 +:401240009340054AD367BFF34F8FBFF36F8F00207047C046301E000804E100E0084B1A682C23584310180C23C25E002A05DB1F231A401E3B9340034A136000207047C04635 +:40128000301E000800E100E0042819D804290FD94B1EFF3B132B13D81F231940094B8000C018C02304229B00C1504033C25005E00723D0301940034B8000C150002000E051 +:4012C000014870470000264001004A00084B8200D218D0239B00D05807231840042806D1C0239B00D0581F231840E1331843704700002640F0B5012819D1C022224BD2009E +:401300009A58002A0CDB8A78901E0E280FD84C78601E11280BD8C8780D7800282FD101E01A4830E07026152D01D9AE4201D2184829E00E79022E14D0F82124024901F8271E +:401340000C4021007F2412047F033A4011432C4021438024C022C006240520400143D2009950C020C0248005360706403200E4001D590849002029400A431A5103E0382628 +:40138000122DD4D9D1E7F0BD0000264003004A0001004A00FFFFFFCFF8B50D00012819D1C02180240D4BC9005A582406C826224307001C005A50F600A3593B4206D1002D30 +:4013C0000AD0012000F02CFD013DF5E70020002D03D101E0024800E00248F8BD0000264001004A0002004A00494BF7B51C789C46002C05D0474B484CE358002B00DB82E017 +:40140000464B984200D980E09A427ED8444B99427BD80123644663703F4B424CFF280BD8A3260F25F6009F592840AF43384398511859A843083D1FE03B4E0F25B04204D882 +:401440001E592840AE43304317E01E59AE433500060A35431D51354DA84206D8FF261D59000130400F3EB54306E0F02500022D011E5928402E4D354028431851FF2A10D825 +:40148000A326FF27F6009D5912013A400F3FBD432A439A511A5927481040E022D20210430AE0F027204D3F03AA4207D81D592148120417402840384318511EE01859164EDD +:4014C000009010020740019700981A4F154D3840019F074315481F517459824205D8F020120500040240144804E0F020120600050240124820400243725162465160054AE5 +:401500000020995002E00E4800E00E48FEBDC046341E00081C050000000026400F060000FFFFFF0014050000FF040000FF050000FFF0FFFFFFFFF0FFFFFF0FFFFFFFFFF08D +:4015400003004A0001004A00A423F0B500251F4ADB008446D0582B000002020A85B00292039363461A484570AB421BD1029A039B1A43AA4226D0029C039D029E039F0A00D8 +:4015800063464068614601F0D3FBEB0762081A4300900191009801996B088018594132003B000BE0029A039B44680800290001F0BFFB2B00620880185941220001F098FB3B +:4015C000029003910298039905B0F0BD00002640341E0008174B70B5C318DA179B185340042B22DD8023144E144D1B027459A405A40D984209D9124B0521C01801F002FAF8 +:40160000201AC343DB17184009E00E4B0521181A01F0F8F90C4B0019984200D90B4873599B0A9B020343735101E000242000201A70BDC0460080FFFF000026403C0500005F +:401640000280FFFF02800000FE030000FF0300001E4A0300904238D010D840282ED005D8002831D010282DD119482EE0802827D08021100049008B4227D023E0154A904296 +:4016800014D008D8A022120690421DD0124AA020934211D016E0114A904209D0104A904208D0104A90420DD10F480EE0A42003E00E480AE00E4808E0C00306E00D4804E0A5 +:4016C0000D4802E00D4800E0002070470600520001005000010000F0090000A0040000F0050000F0030000F00100520002005200030052000200500005005200FF00520092 +:40170000F0230F4A1B06C318934201D8580A15E0EC230C4A1B06C318934203D8580A80235B0207E0EA231B06C018904204D88023400A9B02184301E0012040427047C04608 +:40174000FFFF0F00FF7F000010B50400FFF7D8FF0022431C02D0E40562426241100010BD0B4B10B51B69002B10DB0A4B0A4C1868FFF76EFF0121094B094A995099580029D9 +:40178000FCD1064909590029F8D100E0054810BD00002340401E00088C040000000025400C0400000200500010B5022202490020FFF7E0FC10BDC0469503000810B5FFF74B +:4017C000CFFF10BD70B50400FFF7BEFF002824D0FEF714FDE022124B52051A605C600024FA219C60DC600F4B0F4A1D691B692D0E013555431B0ADBB201335D430B4B8900C2 +:40180000186801F0FFF80100280001F0FBF8084BC118200002F08CFE00E0064870BDC046401E00080000214060F59000C4000008980800000600520070B505000C00FFF76E +:4018400083FF002828D0002C26D0FEF7D7FCC022124BD2041A608322FA2152005A609D60DC600F4B0F4A1C691B69240E013454431B0ADBB201335C430B4B8900186801F0B9 +:40188000C1F80100200001F0BDF8E1239B00C118002002F04DFE00E0044870BD401E000800002140808D5B00C4000008060052000F4B30B5C0180F4BC009C01800011F23D2 +:4018C000032909D81D00C9008D4013408B400468AC432343036009E01D000439C9008D4013408B404468AC432343436030BDC0460000CEBF00100304F7B504000E001500E1 +:4019000000286ED0002A6CD0012312688B40002A01D1436000E08360B30001930F231900B0008140A26A8A4369680B4083401343A3622A7A31002000FFF7BAFF03207100C2 +:4019400088400322636A83431800EB6813408B400343636201231F00B7400097FF43BC462F6962461F40B740A0691031104038436F69A0611F40B740E06A10403843E0620D +:40198000A86903221840B0400600E869276B10408A408840009930430A4397436A6A384356000222206304201640AA6A616B92000240286A324303401A43EB6AD800182322 +:4019C0000340FF2013432A6B019D520102401343FE2292002A40934081430B436363002000E00148FEBDC04601005A0000281BD0002919D00D4B0E4AC318DB099B180A682C +:401A00001B010260CA6882620A69C2624A6902638A6842624A6882618A694263CA6900201A600A6A5A6000E0024870470000CEBF0010030401005A0010B50F24022006495C +:401A4000064BCA58A2430243CA50F02212028B58A34303438B5010BD0000214004F0000010B50F2403200649064BCA58A2430243CA50F02212028B58A34303438B5010BD7F +:401A80000000214004F000000449054A054B88580340C020C00103438B5070470000214004F00000FF8FFFFF0449054A054B885803408020C00103438B50704700002140BF +:401AC00004F00000FF8FFFFFF8B50500072700F03CFA1C4C060063693B409D422DD0022D0FD18021184A490493690B439361FFF7A3FF03226369BB4313436361FFF7C4FFD8 +:401B000009E003226369C820BB431343636100F087F9FFF7C9FF072362699A432B4013436361052D09D1C82000F07AF9FFF798FF054A064B91690B409361300000F009FA66 +:401B4000F8BDC0460000264000F02540FFFFFFFE031E03D1084B5869C00F0CE00020012B09D1054918008A69920F1A4201D18869C00F01231840704700002640072370B53A +:401B8000084CA2691A4090420BD0A5699D4303402B43A361002904D0904202D9C82000F03FF970BD00002640F7B5060000F0CDF9B022E8211F27244D244C01902B595205F9 +:401BC000C900525C3B409B1A5A1E9341B34236D0002E13D180211E4A490493690B439361FFF72AFF0B222B59BB4313432B51FFF74BFFB023E8225B05D2000CE00B222B59C5 +:401C00000920BB4313432B5100F00AF9FFF74CFFB022104B5205D35C2959DAB21F23994313400B432B51012E09D1092000F0F8F8FFF716FF064A084B91690B4093610198E9 +:401C400000F087F9F7BDC046000026401CFF000000F0254041070000FFFFFFFE70B5050000F073F92C1E20D0124B19681F2901D900241AE0EC68002C17D02C68002C14D038 +:401C80005E6800243200002A04D0AA42F0D014005269F8E7002E01D15D6000E0656100222C61012401316A61196000F052F9200070BDC046501E0008F0B5060085B00D0012 +:401CC000204F042901D001291AD100207C68002C35D01D4B984232D02379B3420ED1A368002B01D02B4209D1E36801A85A689B6842608360057023689847BC606469E6E758 +:401D0000BC68022902D1002C00D024690020002C15D00D4B984212D02379B3420DD1A368002B01D02B4208D1E36801A85A689B68426083600570236898472469E7E705B0CA +:401D4000F0BDC046501E0008FF00420070B5194C06002368002B0AD100F0F7F823680500002B10D004210020FFF7A6FF0BE001210020FFF7A1FF0028EED002210020FFF79C +:401D80009BFF0D4C14E004210C4A13698B431361012E01D030BF00E020BF280000F0D9F823680024A34203D008212000FFF784FF200070BD501E0008FF00420000ED00E072 +:401DC00010B5E82400F0C1F8064B07495A68A4010A4022435A605A68114059605B6800F0B8F810BD00002640FF00FC0F70B5802504002D02AC4206D9064B186800F09CF86D +:401E0000054BE418F6E7054B1868604300F094F870BDC046DC0000080080FFFFD800000810B5034B1B78584300F086F810BDC046D40000080122014B9A6070470000254032 +:401E400080220020034B12069A649B6C834200DA0148704700002740030046008022054B120198585B68DBB2002B02D08023DB021843704700002640FEE7000002680A4B08 +:401E800010B51A6042685A6082689A60C268DA6002691A6142695A6182699A61C269DA61FFF7EAFF10BDC04678050008F0B51922002800D14B32E82403258A429241194ED8 +:401EC000640033595242AB43134333513359164F3B403351154B5C68AC4322435A605A6817405F60002808D00023102913D921338B429B415B4201330DE003001D290AD96D +:401F000001233A2907D9DB18572904D976338B4240410422131A0F21054A1068884303431360F0BD00002140FFFCFFFFFC00214000002540000000000230800803D001309E +:401F40000238FCD1C046C0467047EFF3108072B6704780F310887047094B042803D11A68104318600BE0C022000692041040902204499200885004211A688A431A6070471C +:401F800010E000E000002140F8B50778012F06D0082F34D11C4B1868FFF7DBFF31E00320FFF73EF8194B984229D000F0CFF8012825D0022003F0D8F90600FFF7C6FF124D59 +:401FC000286003F0D5F9040006281AD0022E0AD1033CB4433000E4B204F026FE002C0BD100280ED008E0380004F01EFE022C03D0002801D1FFF7AAFE2868FFF7AAFF04480B +:4020000000E00020F8BDC0467C1E000801018800FF004200002803D0024B5860002000E0014870477C1E00080100160000B58BB000212822684602F065FA6A46154B1648F7 +:402040009381FB2313835383F83B1377013353770C33D3770132D3776A460232D3776A465B3353846B4601220733DA77FFF7F6FD03F05AF903F060F903F05AF906A803F0FD +:40208000A7F9002804D1054B6846019303F074F90BB000BD901300004C01000898050008014B024AD050704778F0010000003C4010B50BF0EFFA10BDF8B58023FA250C0037 +:4020C00001271B0218430D4E0004F061AD00326C0A4B01203A4205D1002D0CD0013DFFF79FFEF4E7002D06D01A6C10431864DB6A0020238000E00248F8BDC04600003C4007 +:402100000400160070B5FA2401260D4B000418400C4D0143E961A4002B6C0A4A0120334205D1002C0AD0013CFFF77AFEF4E7002C04D0136C18431064002000E0024870BD34 +:402140000000FF7F00003C400400160010B500242000FFF7BBF8032804D00134052CF7D1002000E0012010BDA023034ADB00D058012318407047C0460000264030B524259E +:402180009DB02A00002101A802F0BCF9154B164C0493164B2A0000210AA808930993069402F0B0F9124B2A000D93124B00211193114B13A812930F9402F0A4F90F4B01A9D9 +:4021C00016930F4B0F481A931894FFF70FFC0AA90D48FFF70BFC13A90C48FFF707FC1DB030BDC046666666660000FFFF1C1C1C1C66E6EE661C1A1A1A1A1A000066E6666601 +:402200001A1A001C00013240800132400002324010200349034A8B5803438B507047C04600003C4070F00100F0B585B00090002800D147E1BE4F7B689B0301D5FFF7C0FD6B +:402240000122BC4BBC4C1D001959114204D0BB495B58134200D037E1FFF790FFB84AB94BEA508022009BD2021B781343B64AAB50B64AB74BEA50B74B5A6801231A4200D078 +:4022800024E1B54A116F08220A4008D1B34BB44918681300884202D900F0B4FB431E2A68002B03D0AF485B03034300E0AE4B13432B607B699F499E4E01275B000DD53900DF +:4022C0000320FFF75BFC73699B0F3B420AD08022B369D2051343B36104E00320A34A8B5803438B502B5940200193019AA04BA14E13432B51FFF794FD0123AA598D4F1A42F5 +:4023000008D1BB514020FFF78BFD03234020BB51FFF786FDFA27019A974B984E1A4016430192FF002E51964A964BD3581022134207D1002F00D1CBE00120013FFFF770FDCD +:40234000F1E7002F00D1C3E008218F4A0120AB580B43AB50FFF7FCFB002802D18B4E019B1E438B4B1E4001231E432E511E00894C724BEB58334207D1002C00D1A8E0012097 +:40238000013CFFF74DFDF3E7002C00D1A0E00B27C02181484901FFF7B5FE041E05D102AB991D7D48FFF788FE0400013F002F00D196E0002C25D1C02202AB9E1D33885201AA +:4023C0009342E5D131007548FFF776FE041E18D180233288DB001A4200D083E00B27019380216E48C900FFF78DFE041E04D131006A48FFF761FE0400013F002F70D0002CB3 +:4024000068D0B0256D056B78002B44D06B78212B41D0634FEB5B002B3DD0002C00D0FEE002AB9E1D31005F48FFF746FE041E00D0F5E0C021E85B3488084060398C43400898 +:40244000594920430140F020EA5BC000EB5BD201024011439B05554A9B0F1140DB02194350483180FFF74EFE041E00D0D7E031004F48FFF721FE041E00D0D0E0C022EB5B04 +:4024800031889B069B0F9B019143194348483180FFF738FE0400002C00D0C0E0009B454859781D78444B49001943FFF72BFE041E04D142494248FFF725FE04006801FFF7D6 +:4024C000AFFCACE03F4CAAE03F4CA8E03F4CA6E03F4CA4E03388019A934200D080E701E03B4C8EE731003B48FFF7E6FD041E00D087E732883F2310009843009B36499F78F9 +:40250000DB78012F0ED10222012B04D89FB2D21B92B2019201E0170001947022104330802E4A66E0002B5BD0019401275BE0C0460000264000003C40A0F00100B4F00100AC +:4025400006000001A4F00100A8F0010001000100ACF00100FC003C4000F03D40C800000800093D00041A0080040A0080C4F0010030000300B0F00100EFFFFEFF20000200CA +:40258000000032401040000068F0010028000200FFFFFBFFF07E0E00021E0000031E000016180000071E00007FF8FFFFFFE7FFFF061E0000081E000001100000376800007B +:4025C0000F1E000001001600030016000200160004001600091E0000C00000080048E80101201F0001907F2082436F38024332800C4ADA400A6031880B4839433180FFF750 +:4026000081FD009B0400DB78DF1B03231F40019B9B001F43054BBFB23780EF50F1E6200005B0F0BD0024F400091E000064F00100014B18687047C046C0000008024B58690F +:402640004000C00F7047C046000026400120024B1B68DB0D984370470000264010B50A00002808D0FA23FF33994204D8034901F040FF002000E0024810BDC04607080016C4 +:4026800001001600F0B57D4C7D4BA54407900C000492994200D8ECE08B187A4A93420ED9794A914200D8E4E0784A934207D9784A914200D8DDE0774A934200D9D9E0FFF718 +:4026C000BDFF0523019300280BD0734B5D6907231D40EBB20193022D03D10520FFF7F4F90195FFF7B3FF01230393002810D06B4B694AD158E823B022DB005205D25C1F2307 +:402700000B40934204D10120FFF74EFA00230393F0231B06E3185D0A06936D0200210320FEF706FC0028F9D1070008AB5B1B0293049BBB4273D980239B00EB180593002615 +:402740002B00069A9A4214D8049ABA4211D9079A0299D25DCA54002E08D18021490559180978521A511E8A41160000E00126013705E0802252059A1812780299CA54059A64 +:4027800001339A42DDD10024A6423FD08023C8265B05ED182800FFF715F804000120FFF73FFBA423A422DB032340D203934203D1013E002EEED128E0394B9C4204D1FEF71E +:4027C000FDFF384B0400F8E70120002C1ED1C82608A92800FFF730F804000120FFF720FBA423A422DB032340D203934203D1013E002EEDD109E02A4B01209C4206D1FEF780 +:40280000DDFF284B04009842F9D00120264A029B944663440293002C02D1059D88E70024002801D0FFF706FB00210320FEF7BCFB0028F9D1FFF702FF002805D0019B022B9B +:4028400002D11800FFF740F9FFF700FF002805D0039B002B02D11800FFF7A6F9134B9C4207D0134B9C4204D00020844202D0114800E0114889239B009D44F0BDDCFDFFFFEA +:40288000FFFFFF0F00001010FFFFFF1300800014FF070016000A0016000026401CFF0000010050000200500000FEFFFF0200520006005200130016000100160010B50A0031 +:4028C000002807D0FA23FF33994203D80249FFF7D9FE00E0014810BD0708001601001600002070470020704710B5FFF799FA10BD10B5FDF7FCFD074B1B681B6800229A5E9D +:40290000002A05DB1F231A401E3B9340024A136010BDC046801E000800E100E010B5FDF7EAFD094B1B681B6800229A5E002A09DB1F231A401E3B9340044AD367BFF34F8FCA +:40294000BFF36F8F10BDC046801E000804E100E0A023034ADB00D058032318407047C04600002640024B034AD058C00F7047C0461C0500000000264010B5FEF7E5FD10BD77 +:4029800010B5FEF731FD10BD10B5FEF723FE10BD10B5FFF7F3FB0220FFF782FB094C0A4923681868FEF716FA23681B6800229A5E002A05DB1F231A401E3B9340034A13600A +:4029C00010BDC046801E0008B120001000E100E00420704710B5FFF7B8FA10BD10B5FFF7B8FA10BD10B50021FFF7C8F810BD000002B4714649084900095C49008E4402BCBF +:402A00007047C046002243088B4274D303098B425FD3030A8B4244D3030B8B4228D3030C8B420DD3FF22090212BA030C8B4202D31212090265D0030B8B4219D300E0090A03 +:402A4000C30B8B4201D3CB03C01A5241830B8B4201D38B03C01A5241430B8B4201D34B03C01A5241030B8B4201D30B03C01A5241C30A8B4201D3CB02C01A5241830A8B42AC +:402A800001D38B02C01A5241430A8B4201D34B02C01A5241030A8B4201D30B02C01A5241CDD2C3098B4201D3CB01C01A524183098B4201D38B01C01A524143098B4201D320 +:402AC0004B01C01A524103098B4201D30B01C01A5241C3088B4201D3CB00C01A524183088B4201D38B00C01A524143088B4201D34B00C01A5241411A00D20146524110462E +:402B00007047FFE701B5002000F0F0F802BDC0460029F7D076E7704703460B437FD4002243088B4274D303098B425FD3030A8B4244D3030B8B4228D3030C8B420DD3FF2267 +:402B4000090212BA030C8B4202D31212090265D0030B8B4219D300E0090AC30B8B4201D3CB03C01A5241830B8B4201D38B03C01A5241430B8B4201D34B03C01A5241030B23 +:402B80008B4201D30B03C01A5241C30A8B4201D3CB02C01A5241830A8B4201D38B02C01A5241430A8B4201D34B02C01A5241030A8B4201D30B02C01A5241CDD2C3098B4221 +:402BC00001D3CB01C01A524183098B4201D38B01C01A524143098B4201D34B01C01A524103098B4201D30B01C01A5241C3088B4201D3CB00C01A524183088B4201D38B007B +:402C0000C01A524143088B4201D34B00C01A5241411A00D201465241104670475DE0CA0F00D04942031000D34042534000229C4603098B422DD3030A8B4212D3FC228901BF +:402C400012BA030A8B420CD3890192118B4208D3890192118B4204D389013AD0921100E08909C3098B4201D3CB01C01A524183098B4201D38B01C01A524143098B4201D3C7 +:402C80004B01C01A524103098B4201D30B01C01A5241C3088B4201D3CB00C01A524183088B4201D38B00C01A5241D9D243088B4201D34B00C01A5241411A00D20146634601 +:402CC00052415B10104601D34042002B00D54942704763465B1000D3404201B5002000F005F802BD0029F8D016E770477047C046002B11D1002A0FD1002900D1002802D090 +:402D00000021C943081C07B4024802A14018029003BDC046D9FFFFFF03B4684601B5029800F050F8019B9E4602B00CBC7047C046F0B54F464646C0B41604360C99463300C8 +:402D400005042C0C070C150C63437E436F4365431C0CAD1964199C46A64203D980235B02984647446346250CEF191D044B464A4343432D0C240464199918C91920000CBCA3 +:402D800090469946F0BDC04670B500220C4B04000D0001F05DFA002804D12000290001F0B5F970BD064B00222000290000F05AFE01F0ACF980231B069C466044F1E7C046E0 +:402DC0000000E041F0B54D46564644465F46F0B4924683B004000D0099468B422FD82CD04946504601F05CFA29000600200001F057FA331A9846203B9B4600D574E053461A +:402E00005A4693401F005346424693401E00AF4229D826D05B46A41BBD41002B00DA79E0002200230092019301235A4693400193012342469340009319E08242D0D900221A +:402E40000023009201930C9B002B01D01C605D600098019903B03CBC90469946A246AB46F0BDA342D6D900220023009201934346002BE8D0FB0772081A4346467B080EE0D4 +:402E8000AB4201D1A2420CD8A41A9D41012024196D410021013E24184D41002E06D0AB42EED9013E24196D41002EF8D15B460098019900196941002B22DB2B005A46D34044 +:402EC0002A004446E2401C005B461500002B2CDB26009E40330026004746BE403200801A994100900191AEE7424620239B1A5246DA40414613004A468A4017001F4382E7AB +:402F0000424620239B1A2A0046469A402300F3401343D5E74246202300219B1A0022009101920122DA40019282E74246202326009B1ADE402F00B446974066463B003343D8 +:402F4000C9E7C046F0B556464D4644465F46F0B41D000E034C00CB0F87B0070092468146360B640D98466AD06D4B9C4235D08022430F12041343F6001E43C3009946694B51 +:402F800000279C460023644402932B0368001B0BED0F51469B46400D009500D178E0604B98426CD05B46DA004B0F802109040B4313439B465346D9005A4B9C4600236044E4 +:402FC0004246201A6A40924601901F430F2F00D9B0E05548BF00C0598746374300D088E0002399460233082700260293CDE74346B34649460093029B009A9246022B00D07A +:40300000BFE1002153460122002689461A40444B002136030C0D2405360B2643434C1B0526401E437600D207760816434846310007B03CBC90469946A246AB46F0BD330077 +:4030400003434FD0002E00D1BCE1300001F00AF903000B3B1C2B00DDADE11D220100D31A08393A008F408E40DA40B9461643304B00279C46002360444442029385E753460E +:403080005A4613432CD1002300219B46023397E70B4320D05B46002B00D19EE1584601F0E1F803000B3B1C2B00DD8FE102005946083A91408B461D21CB1A5146D9400B0043 +:4030C00059460B4351469B469140194B9C4660444042002374E7002300219B4601336FE703236DE70023994601330427002602934BE703230C27029347E70122D51A382DA6 +:4031000000DCB0E153461A4000210023002689467EE700238026994600223603004B77E7FF07000001FCFFFF40510010FFFF0F80F30300005E4500D972E100D16DE1019B36 +:403140004D46013B01930023340002935B461E020B0E1E430B020393330C994633041B0C494620000093FFF74DFC009B370043430600494620009846FFF7CAFC2C0C090439 +:403180000C43A04509D9E419731EA74200D95CE1A04500D859E1023EE4194346E41A49462000FFF72FFC0300009A80465343494620009B46FFF7ACFC2A040904120C0A4314 +:4031C00093450DD94346D219013B974200D93AE1934500D837E102235B429C46D219E0445B46D21A4346360433439B460399180C0B0C1D00059309045B46090C0C001B04F8 +:403200001B0C4443049159436B4368431B190D0CEB189C4203D980246402A44660441C0C09041B04090C20185D18824200D2DEE000D1D7E0161A029B9C465D1BAC459B41CE +:403240005B42F61AB74200D106E149463000FFF7D9FB009B04004343494630009846FFF757FC2E0C09040E43B04509D9F619631EB74200D9F3E0B04500D8F0E0023CF619CE +:403280004346F31A494618000293FFF7BBFB009B06004343494602989846FFF739FC2D0409042D0C0D43A84509D9ED19731EAF4200D9D6E0A84500D8D3E0023EED192404A4 +:4032C000210043463143049E059A3000ED1A0B040C0C1B0C58436643534354439A19030C9B189E4203D980225202944664441A0C00041B04000C14191B18A54250D34DD0F4 +:4033000001231943964A019B94466344002B00DCF3E64A0709D00F220A40042A05D00A1D8A42894149428B4411005A46D20108D55A468C4B1A4093468022D2009446019B7C +:403340006344894A934200DD5BE65A46C908500708435602514601225B058146360B5B0D0A4055E680231B031E4211D05A461A420ED15E461E433603360B2A0089467B4B4B +:4033800046E6032B00D1E1E0012BBBD11A40BBE61E433603360B4246744B39E6002BB1D07D194A1EAF4252D91100A542A8D1039A9A42A5D1A6E703003E00283B9E400023D5 +:4033C000994654E600F04EFF203041E603005246283B9A400021934677E6504600F042FF20305EE6029B0026AB4200D323E7039E0299B44661448846B045B6415B467642FB +:40340000F619B218013B0291974213D290424FD800D18EE0161A9B460DE7894500D28EE674084B46F60735005B081D434B46DB0702938BE69742EDD10399029CA142E5D9E8 +:403440003E1A9B46F7E69846CAE61E00A5E6AC423ED874D0110053E70121494252E71C000EE71E002BE71F2D3CDC20230A0058465B1B9840EA4099400243481E81415E4694 +:403480001143EE404B0709D00F230B40042B05D00B00191D99429B415B42F61833023CD55346012200211A40002601238946AFE502235B429C46039CE344A446029B634479 +:4034C0009846A045B6417642F6190293B218B1E603988A1E41008142B6417642F619AD19039161E71F225242D31A5A46DA401300202D29D040225846551BA8400143481ED7 +:40350000814107200B4318400026002809D00F2200261A401900042ABBD10B0070077602360BDB0803439946012253461A4000236EE502998D42BBD89B4600267BE6039882 +:403540009842C5D3110032E70020D7E780265B4636031E433603360B009A8946034B57E5FF030000FFFFFFFEFE070000FF070000F0B55F4656464D464446F0B40D039946E5 +:403580004E002B0B87B00700924680469B46760DCC0F002E69D06D4B9E4235D05B468022DD001204430F13432B439B46C3009846674B00279C460023664401934A461503D6 +:4035C0005000D20F53462D0B400D914600D176E05E4A90426CD080225B0F120413435C4AED0094461D4353460022DB00604449463618701C6140029017430F2F00D9AFE0AD +:403600005448BF00C759BF465B461F4300D088E000239B469846023308270193CEE74946022A6AD0032A00D109E2012A00D0BBE111400022002300259046CCB200212D036B +:403640000A0D12052D0B1543434A1B0515401D436D00E4076D0825434046290007B03CBC90469946A246AB46F0BD034352D05B46002B00D18AE1584600F0F4FD03000B3B24 +:403680001C2B00DD7BE11D22D31A3A0001005D46DA4008398D4013008F402B439B46B8462E4B00279C46002360444642019385E752462A432CD100250023022297E75246D4 +:4036C0002A4321D0002D00D154E1280000F0CAFD03000B3B1C2B00DD46E11D21CB1A51460200D9405346083A954093400D431B4A944660444042002279E7012400220C40A4 +:40370000124B0025904699E70025002301226EE703226CE700239B4698460133042701934CE703230C27019348E700238025984600242D03054B81E75D464346019A6FE786 +:403740005D4643462100019A6AE7C046FF07000001FCFFFF80510010FFFF0F80F30300004246120C91461A0C9446424617044A461B041B0C5A43604690464A464243100071 +:40378000039262461C003F0C7A437C4342440192220C9246019A5244904506D98246802040028046C24450460390100C049048462404240C1204121905922A0C2D042D0C38 +:4037C00068432C00824648467C4350438146200C8046574357444744BA4503D9802040028046C144380C3F04B84648442404240C01900498A044404404905846000C814646 +:4038000058460404200C8246070048465F434C464343604660436446834650464443380C8446E4186444A34203D980235B029C46E34448463F04230C3F0C2404E41957463D +:4038400068436F4384464D46504655434243380C814662444A445B44944503D9802040028446654403983F04834604983F0C8446E344C345804140428246100484460198EA +:40388000674484466744A344BC46A345A4419946D44464428742BF41D4458041E144A04699459B417F424042C8440743120CBA18A045A4415F423B0064422343D71843467A +:4038C0007D19DB0D6D021D435B465A02059B1A43531E9A415B46DB0D1A4343465B021343EA0107D501225C0813402343EA07029E13436D08574AB218002A4BDD580709D0BB +:403900000F201840042805D0181D98429B415B42ED180300E80104D54F4A15408022D200B2184E48824200DDE7E60124DB08680718436D02530580462D0B5B0D0C407DE6CF +:40394000802259461203114208D0154206D115432D0398462D0B4C46414B6FE65D4615432D032D0B3E4B69E603005546283B9D400023BCE6504600F075FC2030A8E60300D1 +:40398000283B9F400023BB46984689E600F06AFC203073E60124A61A382E07DD00220C4000230025904649E6029EA3E71F2E20DC20222C001800921BF040944093400443A7 +:4039C000581E83411C43F540630709D00F232340042B05D023001C1D9C4292415242AD182B021FD5012400220C4001230025904624E61F202C004042821AD440202E1CD003 +:403A00004022961BB5402B43581E83410720234318400025002809D00F2200251A401C00042AD8D1230068076D022D0B0124DB08034398460C40002300E60025E3E78022DD +:403A40000124120315432D0398462D0B0C40044BF4E5C046FF030000FFFFFFFEFE070000FF070000F0B557464E464546E0B40E001100F20F9246C500420F18033703740020 +:403A8000400A4E0F7F0A3043CF4E17435A00640D520DDB0FC900B24200D1E5E001267340A61AB446534500D1AFE0002E00DC0DE1002A3AD103000B4300D0E4E06B0709D09C +:403AC0000F232B40042B05D02B1DAB42AD416D427F191D003B0200D488E0BB4B01349C4200D110E13A00B94B51461A4001235007ED08520264050543120B640D0B400021AC +:403B0000280012030D0D120B64052D0515436208AF4CDB072C401443640064081C4321001CBC90469946A246F0BDA74B9C42C5D080231B0418436346382B00DDFDE01F2B10 +:403B400000DD30E1624620239B1A02009A40664690460A009940F24046464B1E99413243114363460200DA40691A8D429B410D00BA1A5B42D71A3B0235D57A02530A98464C +:403B80004346002B00D1C4E0404600F06BFB0300083B1F2B00DDC5E020222900D21A4746D1409F400A009D403A439C4200DDC0E01C1B631C1F2B00DDE4E02021140028003D +:403BC000C91AD8408C408D400443DA40681E854117002543002471E7424663461A4300D14CE2674645466B0700D069E7012351467807ED08FA080B40054373498C4238D0DC +:403C000012036405120B640D79E7002E00DC9AE0002A47D06C4A944200D14FE78022120410436246382A00DC08E10143481E81410022C9B24919D219A942BF410D007F42D7 +:403C4000BF183A0200D442E15F4A0134944200D14EE101205D4A69083A4028400843D507054357089A4629E706000E4300D017E714E72900114300D1F9E1802109030A436B +:403C80001203120B3BE701235B429846C4446346002B72D1691A8D429B413F1A5B42FF1A0D0068E702000A4300D107E7012252429046C4446246002A00D0E6E06918A942E2 +:403CC000B6413F187642F7190D00BAE7002E00D080E0621C5205520D012A00DCF9E06A1A91464D45B6413A1A7642921B9046120200D499E04D1BA9428941C71B49427A1A9C +:403D000090469A463CE752460123002513400022F5E6280000F0A6FA20300300083B1F2B00DC39E72A002838824000259C4200DC3EE7264FE41A1740C0E60143481E8141B9 +:403D40000022C9B210E7002E00D0F1E0621C94465205520D012A00DCA0E01B4A944500D1C5E06918A94292413F185242D2194908D5070D4357086446A0E6134B9C4200D06A +:403D8000D9E69BE611001F3CE1400C00202B00D180E04021CB1A9A4015436A1E95410027254300241FE763460200203BDA406346202B71D0402366469B1B98400143481E83 +:403DC000814111430022CFE6FF070000FFFF7FFFFFFF0F80002C48D0CA4CA24200D1A2E07442A1468024240427434C46382C00DDDBE01F2C00DD44E14E462024A41B3E00B3 +:403E0000A640A246B0464C462E00E640B4464646644626435446A5406C1EA54134002C434D46EF400D1B28E04A4643464D461A4300D0A5E6002300240025DEE61F2A5ADCA8 +:403E400066462022921B060096409146B04662460E00D640424616434A4691404A1E9141020060463143C240E4E63C002C435AD0F443A146002C52D14D1BA9428941C71B8D +:403E800049427F1A14009A4675E69E4A944200D0C7E613E600227FE700208FE7002C00D0C8E03B002B4300D10FE103000B4300D104E66918A9429B413F185B42DF193B02B2 +:403EC00000D41AE1904B0D001F406446F6E59A4689E63A002A43002C5CD1002A75D102000A4300D1CAE007000D009A46E6E564460022002581E662460600203AD6406246C1 +:403F0000B046202A00D1B7E040226646921B904001434246481E8141114300228AE6794CA24200D061E707000D0014009A46C5E5002C41D13C002C4378D0F443A146002C86 +:403F400020D0704CA24271D04C46382C00DDB2E01F2C00DDBCE02026341BA2463C005646B4404E46A0462C00F440A446444666463443A4465446A54064466E1EB541254390 +:403F80004C46E7406D188D4289413F184942CF19140056E6002A2FD102000A4300D184E007000D009A46574C88E53D436F1EBD41ECB200270D1B60E7524CA24236D07442E1 +:403FC00080263604A1463743BEE702000A4300D174E56A1A90464545B6413A1A7642921B9446120200D4F7E54D1BA9428941C71B49427F1A9A4661E502000A433AD0ED0899 +:404000007C072C438025FA082D032A4208D0C7082F4205D145072C003A009A46C9080C43670FD200E5001743364C47E507000D00140043E53A002A4343D002000A4319D034 +:40404000ED087C072C438025FA082D032A4207D0C6082E4204D147073C003200C9080C43D700620FE50017439A46264C26E50022002544E5234C21E5002049E700230025EF +:40408000BBE54C463E00203CE6404C46B446202C31D040244E46A61BB7403D436C1EA54164462C4300270D1BE7E6802200231203144C0025A1E53D436F1EBD410027EDB2AA +:4040C00060E707000D000F4CF8E407000D00F5E44E463C00203EF440A0464C46202C0ED040244E46A41BA7403D436F1EBD4144460027254346E70027CFE70D0073E50027E5 +:40410000F2E7C046FF070000FFFF7FFF0B0330B5134D1A0B4B005B0DC90F0024AB4211DD104CA34210DC8024640322430E4CE41A1F2C0CDD0D48C31ADA4013005C420029CD +:4041400000D11C00200030BD094BCC18FAE7E040084CA44663449A4013000343EEE7C046FE0300001D0400003304000013040000FFFFFF7FEDFBFFFF70B5051E28D000F017 +:4041800071F8154B154A1B1AD21A1F2A16DD2C00134A0025D21A94405A052403240B520D002124030B0D240B1B0523430D4C1205234013435B002800590870BD0B212C0051 +:4041C000081AC440954024035A05240B520DE7E700220024E4E7C0461E0400003304000013040000FFFF0F808446101C62468C46191C634600E0C0461FB500F001F90028B4 +:4042000001D40021C8421FBD10B500F055F84042013010BD10B500F0F3F8002801DB002010BD012010BDC04610B500F0E9F8002801DD002010BD012010BDC04610B500F069 +:404240007BF8002801DC002010BD012010BDC04610B500F071F8002801DA002010BD012010BDC0461C2101231B04984201D3000C10391B0A984201D3000A08391B09984244 +:4042800001D30009043902A2105C40187047C0460403020201010101000000000000000010B5002903D1FFF7DDFF203002E0081CFFF7D8FF10BDC046F0B55F4656464D46AD +:4042C0004446F0B41F035C00DB0F9A46194B0E034D00C90F8046360B6D0D8B4691463F0B640D9D4219D0134B9C421BD00123A54206D018003CBC90469946A246AB46F0BDAF +:40430000BE42F6D1C845F4D1D34510D0002DF0D1304303005A1E9341EBE7310001230143E7D1E0E73A430123002AE2D1DEE70023DFE7C046FF070000F0B55F4644465646AA +:404340004D46F0B41F033C0B2C4F0E034D00A3465C008446360B6D0DC90F9046640DDB0FBD422BD0254FBC422ED0002D0ED130430700814678427841002C17D15F463A4391 +:4043800014D14B460020002B0AD006E0002C02D15846024301D099421AD00123484218433CBC90469946A246AB46F0BD0028F2D058425841012240421043F1E7370007435A +:4043C000D0D002204042EBE75F461743CDD0F8E7A542E2DC05DB5E45DFD808D000205E45DED248424841012340421843D8E7C445D3D80020C445F4D3D2E7C046FF070000C6 +:40440000F0B55F464D4644465646F0B41C03240BA4462F4C0F034D005E00C90F80463F0B6D0D8B469146760DDB0FA54220D0284CA64222D0002D12D1384344424441002E05 +:4044400020D0002C0DD05C42634101245B421C4320003CBC90469946A246AB46F0BD002E17D05B4519D05B465C4201231C43EFE7390002240143EBD1D9E761460224114317 +:40448000E6D1D7E761460A43DBD100240028DFD0E9E761460A43E4D1E5E7B54203DD01225C421443D4E7B542CDDB6745DBD809D000246745CCD259464C4261410124494239 +:4044C0000C43C5E7C845CED80024C845F3D3BFE7FF07000030B50024A24208D0035D651C0C5DA34201D0181B02E02C00F4E7002030BD002310B59A4203D0CC5CC454013372 +:40450000F9E710BD03008218934202D019700133FAE77047F8B5C046F8BC08BC9E467047F8B5C046F8BC08BC9E4670470000000001B40248844601BC604700BF990200081A +:4045400003000000010000000100000000000000050360000400000001000000000000000100000006046000080000004C1B00086108001008000000010000000200000063 +:4045800002000000080800030900000001000000000000000300000009090003080000006C1B0008710800100A0000000100000004000000040000000A0A000C0B00000066 +:4045C0000100000000000000050000000B0B000C100000008C1B0008510800100A0029000300000003001800030000001920010219010200000000000C00000000000000B3 +:4046000000000000006800000000000000000000000000000000121200000000000000000000000000000000000000BA0000000000000000000000000000000000001D1DFA +:40464000000000000D0000000800000000020000000000000000000000000000000000000000000000000000000000000B0000000000000064000000000000002002000092 +:404680007C01000031010000090901120C00FF0380ABCDABCD80409C1B04041BFFFFFFFF000000000410080007070400F216FBE0FBE01F60427EF56D720096BE209000000F +:4046C00010502604060037D7F401FA00960064004B0032001E00140003040506020D1100F1D9001055D90010A7DF0010A5DA001057DB001053DF00106BDF00102DE000101A +:40470000D1DB001039DC001015DE001043DE00107BE0001041DF00100FE000100FE000100FE00010E9DE001091DE0010D5DE001075150110811501104D2501103526011082 +:4047400041260110A1DA0010EFD90010EBDF001055DB00108FDB001063DF001085DF001079E0001035DC001091DC00102FDE001069DE0010E7E000104BDF001079E000100F +:4047800079E0001079E0001039DF001079E0001079E0001079E0001079E0001079E0001079E0001079E00010DFF50010E7F50010E3F50010DDF50010BBF50010B7F500100A +:4047C000D5F50010D3F50010AFF50010B3F50010EBF50010D7F50010D1F50010EFF50010EFF50010ADF50010DBF50010CD0C011081100110450E0110F10B011001FF001072 +:40480000B5FB001085060110C901011021F7001085F70010D9110110110A01106101011035FB001011060110F15B0010C10A011079120110051601105117011025180110C4 +:4048400041140110D51201108D150110B5130110DF130110EF130110F1130110F51301100FE00010E1130110EB130110E91301107D29011035230110E928011099280110D6 +:40488000352901104D26011059250110F1250110B526011025BE0010572301104D2301105323011051230110552301104F2301100FE000100FE000100FE00010F9AC00109A +:4048C000453C0110273C0110273C0110273C01105D3C01103D7B0110273C01102D7B0110457B0110357B0110DF400110D74001104140011039400110373C01101F3C011034 +:40490000153C01103B3C011031400110614001102F3C011059400110B9400110273C0110694001105140011049400110273C0110653C01106D3C0110753C01102B3C0110A5 +:404940002B3C0110453C0110273C0110273C0110273C01105D3C01103D7B0110273C01102D7B0110457B0110357B0110DF400110D74001104140011039400110373C0110A7 +:404980001F3C0110153C01103B3C011031400110614001102F3C011059400110B9400110273C0110694001105140011049400110273C0110653C01106D3C0110753C011031 +:4049C0002B3C01102B3C0110696401105D640110756401102B3C01102B3C0110096101104561011015610110396101102D61011021610110516101105D610110516401104F +:404A0000B5660110B9660110C56601109D660110A96601102B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C011082 +:404A40002B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C01102B3C011069610110A7570110BC +:404A8000555601105556011055560110D957011069570110555601104D5701101958011063570110F3570110E9570110D75501105556011055560110555601105B55011014 +:404AC0003757011081550110B9570110DF560110EF56011069560110555601102F580110A556011097560110555601102357011067580110555601105556011055560110FA +:404B0000F9630110ED63011005640110ED5601108756011055600110916001106160011085600110796001106D6001109D600110A9600110E1630110F1650110FD6501103C +:404B400009660110D9650110E5650110555601105556011055560110555601105556011055560110555601105556011055560110555601105556011055560110555601107F +:404B8000555601105556011055560110555601105556011055560110555601105556011055560110555601105556011055560110B5600110D75A0110055A0110055A0110DD +:404BC000055A01101B5B0110815A0110055A0110C95A0110C95A0110735A0110315B01101F5B0110815901107D590110615A01101559011007590110075901101959011072 +:404C0000FB5A0110355A0110495A0110095A0110055A0110655B0110215A01100D5A0110055A0110655A0110815B01107D5B0110055A0110055A01102563011019630110E5 +:404C400031630110A95B0110035901109D5F0110A55F0110B15F0110BD5F0110A55F0110A55F0110C95F0110D55F01100D630110FD6401100965011015650110E56401109E +:404C8000F1640110055A0110055A0110055A0110055A0110055A0110055A0110055A0110055A0110055A0110055A0110055A0110055A0110055A0110055A0110055A0110FE +:404CC000055A0110055A0110055A0110055A0110055A0110055A0110055A0110055A0110055A0110055A0110E15F011008000000060F0020200107021900000007070E0562 +:404D0000020220001C1202000103000E030600040040270700000707010200020307030400000000000000000000000000000000000000000000000000080000A757011057 +:404D4000555601105556011055560110D957011069570110555601104D5701101958011063570110F3570110E9570110D75501105556011055560110555601105B55011051 +:404D80003757011081550110B9570110DF560110EF56011069560110555601102F580110A55601109756011055560110235701106758011055560110555601105556011037 +:404DC000D75A0110055A0110055A0110055A01101B5B0110815A0110055A0110C95A0110C95A0110735A0110315B01101F5B0110815901107D590110615A011015590110B3 +:404E0000075901100759011019590110FB5A0110355A0110495A0110095A0110055A0110655B0110215A01100D5A0110055A0110655A0110815B01107D5B0110055A011014 +:404E4000055A011008000000060F0020200107021900000007070E05020220001C1202000103000E032000800000C00000000004000000A822000000000000040000F7FF90 +:404E8000FF7F0000003000000000000000000000000000000000000000000000000000000000000000000000355E0110ED5F0110555F0110955E0110FB5F01107D5F011022 +:404EC000655E011009600110615F0110935E01100D600110795F01107D5E0110FB5F0110715F0110675E0110FB5F0110695F0110AB5E011019600110855F0110B15E01101F +:404F0000296001108D5F011055560110055A01102B3C011055560110055A01102B3C011055560110055A01102B3C011055560110055A01102B3C011055560110055A01101E +:404F40002B3C011055560110055A01102B3C011055560110055A01102B3C011055560110055A01102B3C0110BF5E011041600110955F011055560110055A01102B3C011044 +:404F800055560110055A01102B3C011055560110055A01102B3C011055560110055A01102B3C011055560110055A01102B3C01107961011055630110FD6201107761011054 +:404FC00049630110F56201109F610110A163011005630110756101103D630110ED62011055560110055A01102B3C011055560110055A01102B3C011055560110055A011081 +:405000002B3C011055560110055A01102B3C011055560110055A01102B3C0110A16401105D65011000000000AF64011071650110BD270110BD6401109B650110ED2701105F +:405040008164011021650110412401108F6401103F6501105D24011030303031423830303031303230333034303530363037303830393041304230433044304530463130A4 +:40508000313131323133313431353136313731383139314131423143314431453146323032313232323332343235323632373238323932413242324332443245324633307A +:4050C000333133323333333433353336333733383339334133423343334433454142000026002B00300036003C0043004B0055005F006A00770086009600A800BD00D400CC +:40510000EE000B012B014F017801A601DA01130254029D02EE024A03B1032404A5043605D9058F065C0742084409650AAA0B160DAF0E79107C12BD1445171C1A4B1DDE20A6 +:40514000343100100230001008310010F82F0010083100101231001008310010F82F0010023000100230001012310010F82F0010EE2F0010EE2F0010EE2F001064330010A0 +:405180006037001020360010203600101E36001038370010383700102A3700101E360010383700102A370010383700101E3600104037001040370010403700104039001054 +:4051C00000000000F8B5074600256846058078683C1D2D492E46002807D06268002A06D0800702D1207A800701D00D4649E0FDF7CFFBFDF793FBFDF7EBFB00F029F9002855 +:405200003DD1788C0006C00F00F0A2F905460004000C34D11D49084600F0A4FE0004000C2DD12289A17A2068194C002806D02060A280E68021810021FFF764F9684601F0DA +:405240001BFC054613486B460078E2888000001DC1B21B88A088D418A04206D3C01A801A80B201F09BF9044600E00B4C00F044FD002C04D100F07CFB08490120087000F03D +:40528000F5F82846F8BD00000100160025540010901E0008CC1E0008FFFF00006401000810B503480078012801D101F013F810BD6401000810B5FDF74BFB032801D100F086 +:4052C000FFFD00F0FDF901F059FC00F07DFE02490020087010BD00006401000800487047901E000870B5044600208A0703D08A07920F891A091D084B89B2DA889E885518D8 +:40530000B54206D81D68AA182260DA885118D98070BD024870BD0000901E000803001600004870479C1E000810B501F033FB10BD10B501F039FB10BD10B501F03DFB10BD54 +:405340000549002806D0054981800521017000214170817008467047010016008203000010B5FFF79DFF10BD10B501F02DFB10BD10B501F03BFB10BD38B505460020694608 +:405380000880002D09D0284601F03CFC0446684601F066FB002C02D015E00C4838BD01F01DFB2846FFF70EFF04000CD1284601F0B1FB040007D1FDF7CBFA032803D100F058 +:4053C00055FD00F093FD204638BD00000100160038B50446002069460880002C08D06189090A05D1617A102902D8E179102901D90A4838BDA0816946204601F0CFFB054626 +:405400006946A08909884018A081002D04D1102221460348FFF76DF8284638BD010016009C1E00087047000010B5084900200978002909D005F052FE044605F015FD201ACD +:4054400080B281004018C00810BD00006C01000810B5FCF793FE442202490348FFF749F8002010BD84460010AC1E000810B5FDF73FFA10BD10B519461046044C01F0C4F9CB +:40548000002800D00024204610BD0000FFFF000010B501F0E5F910BD10B501F0CBF910BD010010B5044806D0044A01201070002007F064FD002010BDFFFF00006C01000848 +:4054C00070B50024034D20462C7007F085FD2C70204670BD6C01000801480078704700006C01000870B5591C89B24C080B4D64000021451906E028685054000A5618891C6C +:40550000707089B2A142F6D3D80705D0D0182038D15CC47FD454C17770BD000000103C4030B50A4C002100195B1E07E054186478555C240225430560891C89B29942F5DBDB +:40554000994201D1515C016030BD000000103C40F8B50746FF2000F0F3F9164EFF2070701548164900684018406B0024410F301D0125022901D0457000E0447005700D4882 +:40558000801C4470384612F03DFB070010D112F07BFB3070012000F0D3F912F07FFB68460470447012F0E4FE6846457012F0E0FE3846F8BD6D0100086801000840F03D40C6 +:4055C000F0B50021094D5B1E08E0441924685718260A7E705454001D891C89B29942F4DB994202D1401900685054F0BD00103C4070B500210A4E5B1E09E0541864782502AE +:40560000545C2C4385192C60001D891C89B29942F3DB994202D1515C8019016070BD000000103C40F0B50599091FCFB200217E1E0AE054186478555C24022543144C0419D6 +:405640002560001D891C89B2B142F2DBFC0710D01C78515C24020E4A0C4381180C609C785D782102001D294384182160001DD9780BE059781A7809021143054A84182160B9 +:40568000D978001D9B780902194380180160F0BD00103C4038B509480024447012F0FEFA69460C704C70684612F062FE012069464870684612F05CFE002038BD6F010008AA +:4056C00010B501F08BF90A480078012805D1FCF73DFD012809D012F02FFF05490020891E0870062000F02CF910BD12F00FFFF4E76F01000810B50B46062816D006DC01281B +:405700000FD0032801D1FFF7C5FF10BD0B2811D0112813D01228F8D11146184612F018FA10BD0020FFF714FF10BD1146184612F09DFD10BD04480078107010BD1146184663 +:4057400012F016FA10BD000071010008F8B5184D184E28688019846AE00719D001F07AF90127012811D1002001F046FA052000F0E7F81149FF204870881C4078002804D10B +:4057800028688019416B39434163286880198762E0050CD50848801C0078052802D1042000F0CEF8FF202968013089198862F8BD6801000840F03D406D01000805490028B2 +:4057C00005D005494A784270097801700021084670470000010016007101000838B504000C4816D06178012913D801F0F7F8607812F074FD207000280AD1694608706846BD +:4058000000F090F869460878012801D104202070002038BD0100160010B5094900280CD00278082A09D24278042A06D205494A700078087012F032FA0021084610BD000022 +:40584000010016007101000810B504460448032C05D801F0C3F8204612F04CFD002010BDFFFF160010B50400054808D06178012905D801F0B3F8204612F07AFD002010BD9C +:405880000100160010B5FCF761FC0122084992040028084B086804D0C018016A1143016210BDC018016A9143016212F04FF910BD6801000880F03D400949087805280ED15F +:4058C0004A780848084900684018002A03D1416B490849004163C16A01221143C16270476F0100086801000840F03D4001480078704700006F01000802484078022800D09F +:40590000012070476D010008012807D0032807D0042803D0052803D0FF207047012070470220704710B5040002D012F065F9207010BD000001494870704700006F01000808 +:4059400010B50446FCF7EAFF062C01D9FF2C01D102480470FCF7CCFF10BD00006F01000801494870704700006D010008002070471CB5002469460C70022001902346054AE1 +:40598000054800F0F5F904480068401C00D1034C20461CBDE559001074010008FFFF00003EB50F4A01460D4800230124126800290BD0012908D1684600930481438169469A +:4059C000104600F0D0F980B23EBD68460093048143816946104600F0C1F9F4E7FFFF00007401000810B50089002100280BD0012802D0052807D103E000200DF061FD02E02A +:405A0000084600F0F5F8002010BD000010B50248006800F041FC10BD74010008FFB581B01F00154606463CD000F0D8FFFCF776FF2F49304B4878401CC0B2044606E02201A6 +:405A4000D218127A202A2AD0641CE4B2202CF6D3002406E02201D218127A202A1FD0641CE4B28442F6D32024202C1AD03470029821490202120A200602432001C618726042 +:405A80001F501B4869180078009120280CD0FFF7CBFC0746BD4223D3281AF0601BE04C70E2E7164805B0F0BD13484042854207D9FFF7F6FC014611488142F3D0009807E084 +:405AC000A8B2FFF7EDFC01460C488142EAD00020F060074804703472FCF70AFF0020E1E7FFF7EEFC781B012100F01EF9DCE7000078010008F01E0008C063FFFFFFFF000083 +:405B000070B5074CA5780E2D07D2FFF787FF002802D1A178491CA17070BD024870BD000078010008FFFF0000F8B520280BD2234D07017C19207A202805D000F04FFFE06877 +:405B4000002802D031E00120F8BDFCF7E7FEFFF76BFC012100F0E8F80020184EE060FFF7AFFCFCF7C5FE00F0ADF80546202819D0FCF7D4FE280186191148F168814205D90F +:405B80000646FFF78DFC0021304604E088B2FFF787FC0021F06800F0C7F8FCF7A9FE0948057002E00749202008702020034920720020C8516060E060F8BD0000F01E000858 +:405BC000409C00007801000810B5074CA178002908D0FFF7A9FF002802D1A078401EA070002010BD014810BD78010008FFFF0000F0B500258BB02E46089500F0EFFE00235F +:405C00006A4618462C49040161180C7A202C02D0C96800291DD000211154401CC0B22028F0D300240993099800280FD06846005D00283BD020482101081806684168089119 +:405C400000210160202241600272C160002D04D028E0012111540B46DFE700F033F80546202819D0144829010818C7681348874207D90021074600F057F8FCF74FFE3846A8 +:405C800006E00021384600F04FF8FCF747FEB8B2FFF706FCFCF72CFE094805700998002808D00125002E01D00898B047641CE4B2202CB8D30BB0F0BDF01E0008409C000007 +:405CC0007801000830B50023DB432020094C00210A011219157A202D06D0D268002A03D09A4201D808461346491CC9B22029EFD330BD0000F01E000830B50020084C05463A +:405D00002023020111190B72A550401C4D60C0B2CD602028F5D303480370457030BD0000F01E00087801000830B50B4D00231A015219147A202C0AD0D468002901D02418C6 +:405D400004E0844201D9241A00E00024D4605B1CDBB2202BEBD330BDF01E000810B50EC900F0B2FA10BD10B50EC900F0E9FA10BD38B50024E443054600290AD0052000909D +:405D80004B68097804A000F043FA2860401C00D00024204638BD00007461736B000000000EB5002005216A46009011815081034869460068FFF7D7FF0EBD000074010008D6 +:405DC00010B51D481D4C0178491E0170FF206070FCF7C8FD002825D0FCF72AFC01460020FCF7CAFDFCF7D0FD411C14DB80B2012811D862881248824208D0124B0021601C97 +:405E0000FFF77EFE002802D10220207010BD0D2010F086FE10BDFF20F530FCF765FD00F065F810BD0548084B02220021401CFFF767FE0028EBD110BD7A0100087C010008F0 +:405E4000FFFF0000855E0010C15D001010B503480078042801D100F049F810BD7C01000801480078704700007C010008044800210170FF214170FF21F53141807047000090 +:405E80007C01000806490878401E087005480178012901D003210170FF214170704700007A0100087C01000801494880704700007C01000801490870704700007C01000886 +:405EC00010B5054C6078FF2803D000F007F8FF2060700020207010BD7C01000810B502484078FFF771FE10BD7C01000810B5FF22043280210820FCF743FD0B4C6078FF28EE +:405F000001D0FFF7EBFF0848084B04220021401CFFF7F6FD002803D00D2010F001FE10BD0120207010BD00007C010008C15D0010C0080A21484380B20849C82801D2084848 +:405F400009E002461923C83A5B019A4201D2400801E0FF20F5304880704700007C010008FFFF000010B50F4A002313600E4A13600E4B18600E4801600E49012008600E49FA +:405F80000860282090600E490C4808600D49143008603C38506000F0C5F800F0F5F9002010BD00009801000880010008AC010008B00100089C0100088C010008182100087D +:405FC00090010008A401000800207047014610B50020002910D0094B1A689C685118A14209D25868196080188A0704D08A07920F891A091D196010BD002010BD8001000861 +:40600000F8B50024164E671E321F3D463168136806E01422624310328A58521C1BD0641C9C42F6D36A1C14D02C461422544322460C3288500C214843FFF7C8FF31680028FC +:4060400008510AD031680020103408517068401C70602846F8BD2546E4E73846F8BD000090010008F3B50026F64381B000281FDB2149096888421BD80299002918D01E4F63 +:40608000142204463F1D54432546396810354859401C0DD0FAF72FFAFCF740FC38682F1F4159C359994205DBFAF721FAFCF720FC3046FEBD214608310091465801590C20F9 +:4060C000704308180C220299FEF713FA0A48761C001D0068C159B14200D100260649009A091D865008684159491C4151FAF7FFF9FCF7FEFB0020FEBD8C010008002803DB64 +:4061000007490968884202D90020C043704704491422091D0968504310300858704700008C010008F0B500200D4A451E0346171F50600FE014260146714314680E1DA35119 +:406140000C461668083433511668083435511468401C635039688842ECD30020F0BD000090010008F3B50026F64381B0002845DB26490968884241D8029900293ED0234FAD +:40618000142204463F1D54432546396810354859401C33D0FAF7AFF9FCF7C0FB3868415900292DD0211D009146580C21005971430F46C1190C220298FEF79BF913480021D1 +:4061C000001D0068761C00590C34C0190160416081600E48001D00680159B14200D100260A49009A091D865008684159491E4151FAF77DF9FCF77CFB0020FEBD3046FEBD4B +:40620000FAF775F9FCF774FBF8E700008C010008FEB504460D4600201E49089E0860471E009001900290002C11D0486885420ED2002A0CD0002E0AD0642E08D808460C30BE +:4062400001681C2068430C18207A002801D03846FEBD0120226020721846FFF7D1FE6060401C13D06681A6810A4827610C3067610179A94200D205710021684601810A464D +:406280002846029B00F05CF82846FEBD00202072DDE700009801000810B5002810DB0949496888420CD807491C220C310968504308184068FFF722FF002801D0002010BD32 +:4062C000012010BD9801000838B50124009400F03DF838BDFEB50027184EFF433D4600240EE01C20316860430818017A002906D04068FFF703FF002801D0254603E0641CBF +:406300003079A042EDDA681C16D01C2130684D434419FAF7F0F8FCF701FB69466068FFF721FF0546FAF7E3F8FCF7E2FA002DD5D1216868468847D1E7FEBD0000A4010008AB +:4063400038B50024009400F001F838BD1FB500220C49541E0A60002811DB496888420ED808491C220C31096850430818406801A9FFF778FE401C02D0002004B010BD20461B +:40638000FBE7000098010008F0B50021114A4D1E174611710C3F0B46BD6016E008461C2460431668041D355114680646235014680836A3551468361DA353044616680A3432 +:4063C000335318301468491C255078688142E5D30020F0BDA401000838B500210091002811DB0F49097888420DDA0D4D04010C3529680859002807D0201D0818694600F0DA +:4064000073F9002801D0002038BDFCF787FA28680F34015D491E0155FCF76AFA009838BDB4010008F7B582B0002502986E1E06602F48D21C024017462E4A2C4610460C38C8 +:406440000178106805E02301C358002B0FD0641CE4B28C42F7D3711C29D03401211D40180191039900F02EF9002820D101E02646F1E72048016820460C300F521D480399A6 +:40648000026820460E3011541A480399026820460F30115403993846484300F0A1F8154900280968085102D00024009011E001251AE01048016801980818009900F02FF9B7 +:4064C000002801D0012502E00098C0190090641CE4B203988442ECD3002D05D10298054906600879401C0871284605B0F0BD0000FCFF0000C0010008F8B50D4600216A4658 +:406500008C461180002839DB23490978884235DA214B04010C3319680A59002A2ED020460C300B5A801C0E5C184670438018954224D3854222D2002006E007465F43BF182F +:40654000AF4206D0401CC0B2B042F6D36046002814D0114E271DC8190C366A46294600F008F900280AD168460088012808D030682946C01900F0D3F8002803D00120F8BD9D +:406580000020F8BDFCF7CAF930680F34015D491C0155FCF7ADF9F3E7B4010008F8B50F46002400F031F8002817D10C4900220B460C334A600EE021011D680E466A501D6804 +:4065C0000C36AA53B61C1D680F31AA551D68641C6A54E4B2BC42EED31A71F8BDB401000800280BD0C01C074A81085068890053884118994203D8936851601818704700201A +:4066000070470000B4010008F8B5064600200F4D009029700C0121466846FEF763FE00280CD129460C3100980860301B001F84B221466846FEF756FE002801D00448F8BD27 +:406640006C800098A8600020F8BD0000B4010008FFFF0000F8B5002827DB19490978884223DA174C05010C342168485900281CD028460C30085A009028460E300E5C401C88 +:406680000E5420682F1DC01900F064F800280CD12068002445590EE0094829460C300068C01900F03CF8002801D00120F8BD00982D18641CE4B2B442EED30020F8BD000093 +:4066C000B401000830B50D4604000BD0A800FFF787FF6060002805D000202570C0436080002030BD012030BD70B50D46040005D0002D03D00220205E002801DA012070BDF0 +:40670000FCF70CF90221615E60688900405828606088401E6080FCF7EBF8002070BD70B50D46040007D0002D05D002212078615E401E814201DB012070BDFCF7EFF86088E9 +:40674000401C00B26080616880000D50FCF7D0F8002070BD10B5040009D0227800216068FDF7D0FE0020C0436080002010BD012010BDF0B500231D46002802D00224045F0A +:406780000AE00120F0BD46689F00F6598E4201D1012503E05B1CDBB29C42F4DA15700020F0BD000001B503480122436811466846984708BD4821000810B50021052010F0E4 +:4067C0005DFA10BD70B50546FCF7A8F80D4C218A002914D0638A8B4209D100206082208201202070A3682A46E068984707E0E0680121C018F9F772FE608A401C6082FCF732 +:4068000077F870BD4821000810B50023084A00280BD0002909D001241470141D0BC413825382F9F74FFE012010BD1370F5E700004821000807B509480378012B01D0002059 +:406840000EBD02230370C16002820021418201216846F9F743FE01200EBD00004821000804480021C160018241820121017008467047000048210008FEB5114C114F089EDB +:40688000099D00280BD0002909D0002A07D0002E05D0002D03D0002B01D01B2B01D93C460CE00096019508F03FFC042802D0052803D003E0034C133400E000242046FEBDA4 +:4068C000FFFF160001001600FEB50E4C0E4F089E099D00280BD0002909D0002A07D0002D05D0002E03D0002B01D01B2B01D93C4606E00096019508F060FC042800D1002489 +:406900002046FEBDFFFF160001001600F0B589B015460F460646144C00F060F8002E20D0002F1ED0002D1CD0102239466846FDF7E0FD1022314604A8FDF7DBFD1021684605 +:4069400010F0DAFB102104A810F0D6FB2B46102204A9684608F000FC1021284610F0CCFB0024204609B0F0BD0100160010B50FF04FFD0AF0A7FC0EF089FC10BD10B50FF074 +:4069800049FE0BF0DBFC10BD10B508F007FE0FF097FB10BD10B50DF089F80FF049FD0AF02BFD0EF07DFC10BD10B50DF07FF80FF043FE0BF0D1FC10BD10B50DF077F808F0AC +:4069C00019FE0FF08DFB10BD10B5022801D100F089FAFEF78BFFFEF797FF10BD10B500F07DFBFEF783FFFEF78FFF10BD10B5FEF77DFF012801D1FEF77FFF10BD10B501886E +:406A00008A0703D08A07920F891A091D0379827B1031534359438BB241888C0703D08C07A40F091B091D447910316143C918438989B2DC0703D092015118103189B29A07B6 +:406A400005D5C0794422504340180C3081B2084610BD000001488078704700009C2100080100034803D00348008808800020704701001600C801000810B504000C4815D030 +:406A8000FEF74EFC817B44238A01C179594351181C312180827B9B005A43891880312180407AC000083008182080002010BD00000100160000B501464A7809781202114337 +:406AC000124A11488BB091421BD111490978002917D1FEF725FC0146102206A8FDF709FDFEF7FCFB01680191808869468881FFF775FF6846FEF766FB002802D1684600F016 +:406B000009F80BB000BD000002001600030C00006401000870B5184D00280BD0FEF700FC0446807A800701D4FFF72EFFA07AC00703D004E01048801E70BDFFF717FFA07A26 +:406B4000000701D4FFF71AFF204610F0EFFB002810D110F071FB00280CD100F0D1FD002808D110F05DF8002804D10DF05DFB002800D10025284670BD0300160010B5064C11 +:406B800010F066FC002804D110F094FC002800D10024204610BD0000FFFF160070B5044640890D46002681070BD0C00709D020881B38E12804D26088FB2801D81B2800D2FB +:406BC0000B4E2046FFF71AFF2880617A5322C900083140182880A17BD20051430922D20189184018034928800880304670BD000001001600C8010008014988707047000054 +:406C00009C2100080021002807D04268002A04D0034A80891288904200D2024908467047C80100080100160070B50546FEF75EFE074CFF280AD0FEF7E9FE012806D10020EA +:406C4000012D04D103494978002900D1204670BD020016005C21000870B5054613480E460078A84201D8002404E01148016AD02068430C18002C13D0228B50060AD5D2072B +:406C8000D20FA078022106F05DFA208B40218843208305E0D207D20FA078012106F052FA3146284604F050FC70BD0000CC1E00085C210008F8B50546002004460B4E0090C2 +:406CC0000FE022466946284601F008FD0098002801D010F001FBA878214603F0A0FF641CE4B2B08AA042ECD8F8BD0000F0210008FFB50446C034A068002103468C468E46B6 +:406D00002033997887B0002915D05E78F200511D06920591415C0091911D0291415CD51D0495475D151D0395455D82580192109A002A07D03CE00A99FF2008700899002070 +:406D400008605EE0002908D0DA78002A05D1002D03D0491E029AC9B281540098854227D3002925D1019810F0B7FAA268059900235354A26802995354A26804995354A268EF +:406D800003995354A26806995350A06820304178491C8907890F4170A16820318878401E0006000E887027D02148864601208446A0686346014620318A78002B0AD04E7804 +:406DC000F1004B1DC35C0093CB1DC75C0B1DC55C40580190002A28D0009885421FD20199401B4A190899C0B20A60B8420CD2099A2918C9B210700BE00A99FF200870089947 +:406E00000B600B480BB0F0BDE819C1B2099807700A980670F000A268001D115405E00A98FF2101700899002008607046EAE70000FFFF0000064A02235188891C89B2518047 +:406E4000814201D8102900D95380508870470000CC0100080148407870470000CC010008F8B517460D460446FBF758FDC034A16820318878042827D0E8780202A87810436A +:406E80000A78521C9207920F0A70A16820318A78521C8A70A1682022525CD6008D51A168721D8854A2680021331DD154F21DA168B8428F540CD33946FBF72AFEC0B20029A1 +:406EC00007D0401CC0B204E0FBF712FD0448F8BD0120A168B61D8855FBF70AFD0020F8BDFFFF0000FEB575480478FEF7FFFC012831D1FBF72DFD724D032831D1A87B012806 +:406F000029D800F033FF012803D100F003FF012808D0A87B002818D06849002020390A782B6A10E0A87B0028E2D10EE0824201D8002102E0D021414359188031C97801294C +:406F400009D0401CC0B28242F0D8FEF789FF032802D3FEF7CBFFAFE0FEF782FF0128FAD05848007800285FD004F052F900285BD00CF0C8F9002857D0FEF748FD002853D018 +:406F800004F08CF800284FD111F084F801284BD06878C00703D000F0F1FE012844D0287E002841D16878484F002803D1FEF794FA002860D06878000706D504F06FF8064623 +:406FC00000F0E4F8304377D16A7801A9684608F03DF90646B4426FD83C48864206D3FEF77BFA002868D06878002865D104F010F9002861D03648006A80B2029068784007C3 +:4070000003D56846008805F02BFA03F007FE6846008803F041FE03F027FF2E490988814203D10120FEF78CFC46E0FBF7D3FC054603F01AFF69468988401A301AA0420ADB09 +:407040000CF060F9012806D1FEF7E0FC012802D1387003F09BFE2846FBF7C0FC3878012803D01B4902980862DBE70120FEF762FC00F0E4FD1BE004F0CBF800281CD0102489 +:4070800003F0F2FE214603F017FD03F005FEFEF7BDFC002810D00120387003F077FE0020FEF748FC00F0CAFD38780128B9D1FEF7E9FB00203870FEBD0748FEBDEC1E0008B7 +:4070C0005C2100086D010008CC010008FF7F000040123C40E6010008FFFF000010B517480078002825D01648046AFEF7FFFB032821D004281FD005281AD103F061FE00F082 +:40710000B1FD03F0EFFE8007800F022810D10D48418800290CD08321095D002908D101210170207E0221C207D20FA07806F00AF810BD0024D9E700F095FD10BDCC1E000871 +:407140005C210008DC010008F8B50646002406F0DBF90546304606F00FFA03460A480021868A0DE001228A401046174628401F40002803D0002F01D1224394B2491CC9B257 +:407180008E42EFD82046F8BDF0210008F8B500252C460A4F0A4E0CE0D020396A604308180079002803D02046FFF7CEFF0543641CE4B23078A042EFD82846F8BD5C210008D9 +:4071C000CC1E000808B50020694648706846FEF705FB69460020085608BD70B50D4601F0BBFF04000BD02079002808D0FFF7F6FBE178A0782A4605F0E9FA002070BD02201A +:4072000070BD00000148007F70470000CC1E00088030C078002800D00120704700B500F001F800BD10B5094BD0225043196A85300A5C074C521CD2B20A54648A196AA24269 +:4072400001D300220A54196A085C10BD5C210008F021000870B50D4601F07EFF04000BD002F0F3FD002807D021462A460A310620FEF740FA002070BD022070BD70B50D4647 +:4072800001F06AFF040007D002F0DFFD002803D0207B2870002070BD022070BDF8B50F4606460146384606F025F9044614480078B04201D8002504E01248016AD020704380 +:4072C0000D18002D12D0284601F084FF032C0ED0002C0BD000220121304602F091F9284603F0C8FA0221284603F0DEFAF8BD3146384606F0C7F90146304606F05FFDEEE76B +:40730000CC1E00085C210008F7B52B4F0446F8682A4D0078297F884201D30720FEBD07F0CDFE002801D00C20FEBD2078611C05F06DFCFF2822D1F868297F007888421DD287 +:4073400005F0B6FC0646FF2816D02178621C03F083FB1B4821780068426B601C904705462078611C02F0B2FEFF2802D0314602F033FE002D04D01CE007251AE01F2518E02D +:407380000298002815D1F86841680078C200101A401C08180622611CFDF7ABF8F868217842680078C300181A1154F8680178491C01702846FEBD0000CC010008CC1E0008EC +:4073C000EC01000810B507F079FE002801D00C2010BD05F0EBFB05480068006B804702F011FE002000F0A2F9002010BDEC01000870B50D46044610210FF07EFE102160180C +:4074000006460FF079FE334610221946204607F0A3FE102130460FF06FFE0220287020460CF028FE70BD0000F8B504464078217802028006870FE0781143A67809050002BE +:40744000090D0643084601F087FE00210546F2B2002816D0002C10D0022F0ED0032F0CD0002A0AD00279092A07D0002A05D0134A8223527D1B5C9A4207D8288900210CF049 +:40748000E8FC20460FF028FF0D49002914D10D48224600682946436930469847084988420AD1284680308178F2B2491C8170FF232146284600F02FFAF8BD0000AC1E0008C5 +:4074C000FFFF0000FC01000800207047F8B5434D0646E8680078002805D007F0EFFD002803D00C20F8BD0220F8BD3078711C05F08DFB0446FF280ED005F024FA3848317891 +:407500000068826B701C90470746204602F0A0FD002F02D060E01F275EE0E968087800285AD0421EA24246D0C200101A4968821FC01F8A18085C114602F0C8FDFF2802D0E5 +:40754000214602F049FDE86842680078C100081A801F1118E000061B701C009010180622FCF7C7FFE86842680078C100081AC01F115C9155E868426800981218204603F08D +:407580006BFAE8680078401EC0B205F0DBF9E86841680078C200101A801F081806220021FCF7B0FFE868002142680078C300181AC01F11540CE04868E1000C1B611C4018B9 +:4075C00006220021FCF79EFFE968002049680855E8680178491E01703846F8BDCC010008EC01000810B500F05BFA0CF01DFE002010BD000010B5014605220A48FCF779FF97 +:407600000849052208463438FCF773FF01F000F9044880224438C17B1143C17300F088FA10BD0000A021000810B5044600786178E2780843A1781143084321790843617917 +:40764000084305D007F024FD002803D00C2010BD122010BD204605F0D1FB002010BD000010B50078002105F02FF8024902200876002010BD5C21000810B502788178407804 +:40768000002305F037F8024901200876002010BD5C21000810B50C4605F08AFC064A117E012900D1002000211176022121700CF03DFA002010BD00005C210008024A936853 +:4076C0000360D06808607047CC01000870B505460024800708D50948807A400604D500F06FFA002800D10224680705D500F086FA002801D104200443204670BDAC1E00089E +:4077000010B5FBF765F905F041FF074807F034FE012000F033F8040001D105F01DF909F041FD204610BD0000B81E000870B50024104D114E002811D0304608210C30FDF745 +:40774000D1FD0404240C13D1287FC100091AF068001DFDF7C7FD0404240C09D1F06800210170297F4068CA00521A0021FCF7CAFE204670BDCC1E0008CC010008F1B54D4874 +:407780009F22817A82B0114000248172FDF7C8FD0746807AC00706D0474802990068C268384690470446B87A800708D5002C7CD1424802990068C26A384690470446002CE8 +:4077C00073D1787A102809D83A492031009108770298FFF7ABFF040002D066E0384C64E038480025457045734571C5750576457645758570C5708571C573042144300173E1 +:407800001F21C1809B21417245732E4EFF2020363073757300F09CFB07F0CEF802F0F6FA30462030C5700298012814D100980178D02041433046FDF755FD0004000C08D131 +:407840000098007841012048FDF74CFD0404240C01D01B48FEBD002507E02846029902F04FFA040005D16D1CEDB200980078A842F3D8144900204431C87288724439887335 +:40788000401E4883FF200877B87A0121000700280848C27A01DA0A4301E052085200C272032030757075F175B1750849002008702046FEBDAC1E0008FC010008EC010008FA +:4078C000FFFF00005C210008D00100087A01000870B505460E46084605F016FE0446304605F04AFE0121A9400A46224001400A4301D0012070BD002070BD10B5044608467D +:4079000005F03AFE0121A140014201D0012010BD002010BD7047FEB51C4616460F46054602F0A8FFA878FFF779FC02460190334639460094284600F00DF8002808D1A87853 +:407940000199FFF789F9FF2C02D138460FF0C4FCFEBD0000FFB50D4685B004468178164610460E9F05F07AFE00280ED0FF2F27D0C8200159F800031D0A58C01DCB5C085C65 +:407980005278834216D9012716E02648D022016AA078504385300A5C002A01D1224A927C521E0A54FF2F02D128460FF095FC012009B0F0BD9006870F69460898088108E0E4 +:4079C0006878A9788006870FE8780002014368460181204602F044FA0390002806D032462946204600F0C3FD0398E1E7384600F0F4FE074604A800903B4602AA21460196F9 +:407A0000284600F02FFC094BB200A178D218FF208854684600893B46C2B2A078314605F047FBE1E75C210008F0210008C5210008F8B518480026009027E000253046FFF718 +:407A400083FB07001ED01448D022016A3046504385300C5C12E0601CFBF75AF8CCB23846E040C007C00F07D02146304603F0CCF821463046FFF712FC6D1CEDB20748818A82 +:407A8000A942E8D8761C0098F6B20078B042D4D8F8BD0000CC1E00085C210008F021000810B5FEF729F90020FFF768FE04F054FFFAF74EFF032803D1FEF7D8F9FEF716FA47 +:407AC0000FF0C6FC09F06EFB002010BDF8B5002400F04CF90125012800D1012406F0F0FE012801D1022004430F4E1049002004270A78336A0FE0D021414359180979002943 +:407B000007D001290BD002290BD0082181402143CCB2401CC0B28242EDD87470F8BD2C43F7E73C43F5E700005C210008CC1E0008F8B5FF2069461E4E0870F07B0024C009D1 +:407B400035D01C4D15E0D020316A60430F188320C05D01280BD102236A46FF21384602F0DAF901280ED04420C05D01280AD0641CE4B22878A042E6D8F07B4006400EF0730D +:407B8000002410E04520C05D00280FD10121384600F0D4FC0AE0D020316A6043081800F092FC641CE4B22878A042F4D80020F8BD5C210008CC1E000810B5FFF787FF10BD53 +:407BC000F8B500252C460B4E0EE049682C20604308180122694607F005FE0006000E01D0054D05E0641CE4B2B1680878A042ECD82846F8BDCC010008FFFF0000F8B5002535 +:407C00002C460C4E0FE04068E100091B401801226946FFF779FB69460870002801D0064D05E0641CE4B2F0680178A142EBD82846F8BD0000CC010008FFFF000010B5084C54 +:407C4000FDF754FE052809D02078012806D1FDF74DFE052802D020780028F1D110BD0000CC01000810B5FDF741FE012803D0FDF73DFE0228F7D110BDF8B504468079254681 +:407C8000603517460E46002806D0687FFDF79CFF0020A071FF206877A671002E09D0687FFF2806D12046A178024B3A467D30FDF727FFF8BD7992001010B5827904468A431E +:407CC00082716034607FFF2803D0FDF77DFFFF20607710BD30B50D4C022061690C4B8AB29978002901D0022906D11D785B78EB18282B01D9032002E0032900D10120510516 +:407D0000490DC0020143616130BD0000C0113C40BA21000800B500F031F8002807D0012805D0032801D0042801D0002000BD012000BD000002460448806901040020C90C12 +:407D4000114200D00120704700103C40014600B50020C90701D000F009F800BD014600B50020C90701D000F001F800BD0248006AC005C00F7047000000103C4004488069EE +:407D800080B2410501D5042070474007800F704700103C4038B50446000610D5FFF7EEFF01280CD1684603F033F86846007800F0E3FB012002F0E8FD0220FFF7FDFE034860 +:407DC000006801692046884738BD0000EC01000810B5034A0178117004F084FF002010BDBA21000870B50446FFF7C0FF002801D00C2070BDA27B01212848002A827801D025 +:407E00000A4301E05208520082706279012A0AD0C17849084900C1702079214E012806D0042804D00AE0C2780A43C270F4E70622E11D301DFCF75DFBA079B072194D28681E +:407E40000168204688472079012808D06188208806F0A2FB2080207904280CD013E02868C168E01D88470021E01D04F0A3FF0120C002208007E02868C168E01D8847002129 +:407E8000E01D04F097FF2079B070204604F038FFB07A05F0EBF8002070BD00005C210008BA210008EC01000808B50178FFF75EFF814201D10C2008BD002927D00720694640 +:407EC0000870FFF75BFF012801D0042808D11A49887A091D02F0FAF8FF2801D00B2008BDFFF718FF01280BD10121684600F092F8012801D0092008BD6846007804F09EF870 +:407F0000FFF7E8FE04F030FF012011E0FFF702FF012806D1684602F07BFF6846007800F087FB04F017FFFFF721FF0028FBD10220FFF742FE002008BDBA21000810B5034A41 +:407F40000178517004F0EEFF002010BDBA21000838B5002168460FF035F9002801D01F2038BD01210098C90201804180002505714571857107214173857304F0C1FE009CCF +:407F8000202200212046FCF7BDFA25702A460021601CFCF7B7FA204604F0A4FE204604F0C1FF00980FF098F90B2200210248FCF7A9FA002038BD0000BA21000810B5044695 +:407FC0000748844209D8204601F0C6F8002804D00089A04201D1012010BD002010BD0000FF0E0000074A9179491C8906890E917138220A4092014907090E114308430249E5 +:40800000084070475C210008FF0E0000C006C00E70470000F3B5174B0E4618781649401C164AC4B281B000200978126A10E0A14200D80024A14201D8002502E0D025654368 +:4080400055192F79002F07D0401C641CC0B2E4B28142ECD80020FEBD1C700021204601F04FFE2E712046FFF7BDFF2881019804700120FEBDE0010008CC1E00085C210008A4 +:4080800010B507F0D9F80222002100F003F804F08BFB10BD10B5094B40074907000F090F185A595A40185043C0086421FAF730FD002800D1012080B210BD0000C846001033 +:4080C000F7B54120405C88B015460C46002802D02878042802D200200BB0F0BD6946087200262046FFF794F8012800D00126204603A93C300191009023460327217F38333B +:408100003246606A07F058F902A8089900900B46019120463A4603A9283006F0E5FF06006846007A287002D1204600F0C1FA204601F0D2FD3046CFE7FFB587B00C460546AF +:408140001078694608724120005D1746002829D000262046FFF75CF8012800D00126204603A93C30019100902346217F38333246606A07F021F902A80090291D019120463D +:408180002B1D03A928300A9A06F0AEFF05006846007A388005D1204601F09EFD204600F087FA28460BB0F0BDFFB50C464020415C25468035107889B0164600290BD06946DF +:4081C0000873C0B2002814D000272046FFF720F8012810D010E0002100910190A078099B129A0C9903F038F80120E87100200DB0F0BD1F20FBE7012703200890204604A964 +:408200003C30019100902346617F38333A46206A07F0D2F8A0780C9902F066FF0F4A0999801803AA01900B4600920291204604A92830089A06F0A5FF02466846007B30701E +:408240000120E8710C99064DA3788900491912985854204601F04AFD1046C8E700103C40C5210008FFB506464020405C89B015460C46002810D0084601F0F2FD01280BD0F7 +:40828000288869468883002813D000272046FEF7BFFF01280FD00FE02878002100910190A078331DFF22139902F0D6FF00200DB0F0BD0220FBE70127204603A93C3001916D +:4082C00000902346617F38333A46206A07F074F8A078139902F008FF00900C4A009912988918029007AA009201912046331D03A928300C9A06F045FF02466846808B28809C +:40830000204601F0F3FC1046D1E7000000103C4070B5054680350446E9784030002908D0012905D10179042902D14078002808D070BD01790C29F8D00D29F9D1287800287E +:40834000F6D0A078FEF700FF2979C840C007C00FEED0A07802F058FC2979A078FEF79EFF70BD000010B518490446484028D0002101231A468A40904221D0491C2029F8D3BB +:4083800000212046C840C243520618D0400616D0491C1929F5D3A0B2210C020AC3B2884201D193420BD01F21204600F01BFA182805D8A00E062100F015FA022801D2002049 +:4083C00010BD012010BD0000D6BE898E70B50D460446FEF71DFF01280AD0E87AA97A00020143A07802F0E0FE012808D0002070BD00222421204606F03CF8242070BD28218F +:408400005A200155204600F037FD282070BD000008490978814201D8002004E00649D022096A504308188030C079012800D0002070470000CC1E00085C210008014610B558 +:40844000002049070FD5094A0021146A084A137807E0D0224A43A2181279022A04D0491CC9B28B42F5D810BD012010BD5C210008CC1E0008014610B5002049070FD5094ACF +:408480000021146A084A137807E0D0224A43A2181279022A04D0491CC9B28B42F5D810BD012010BD5C210008CC1E000810B5044601468034E06A002804D089780EF02AFF71 +:4084C0000020E06210BD38B50546002000902846FEF79EFE01282BD1284601F0B6FC002826D028792C46C01E4034030002F0FCF90705051B1B051B201B00284601F0B6FC10 +:40850000012810D0284605F09BF900280BD0284605F0A0F9012806D0A97868460EF068FE002803D105E06079002801D10120607138BD2846009905F0EDFD38BD4030417172 +:40854000704740308171704770B50546403528790C46052904D0002C05D1801E022802D8022006F003F82C7170BD017170479200101880304161704770B53C2502F0AAF8CA +:40858000040004D020460021473002F007FD0023FF222946204600F05BFD002C02D0A07802F00EF870BD000010B50B490978814201D8002404E00949D022096A50430C18A7 +:4085C00020217F200155002C05D020890BF0B4FC204600F06DF810BDCC1E00085C21000870B505460F480078A84201D8002404E00D48016AD02068430C18002C11D02079C2 +:4086000007280ED1204600F0BAF8204605F0E0FF0A21484302462046044B29467F30FDF76FFA70BDCC1E00085C2100089DA0001010B502F04FF8002802D0807801F0C0FF2B +:4086400010BD38B5044600206946087001236A46FF21204601F018FC054601236A46FF21204601F058FC2843012812D0214640318A79002A02D1087901280CD048790128A8 +:408680000DD0022A0FD0E079400602D5204605F04BFF002038BD204601F0C2FEF9E72046FFF711FFF5E7204600F028F8F1E7000010B50446408A00280DD00748F521807AD8 +:4086C0000840C00607D5204605F082FF82B2618AA07803F0BFFF10BDAC1E000810B50023054C0B60A48A944205D992001018803042690A60436110BDF0210008FEB506469F +:40870000002000900190A8208559B17868460EF06FFD002801D00720FEBD0098374660370290344678884034608238882082E08BA082304605F035FFA88CE18B884207D158 +:40874000288A3988884203D1688A7988884203D0F07920210843F071688A7880288A3880A88CE083FEF766FBA083E08BFEF772FBE0763046029905F009FD0198FEBD38B52E +:40878000044600200090A07900280FD14420005D052801D00E2809D1A17868460EF028FD002803D12046009905F034FE38BD10B501F054FE002010BD70B50C4605460146D0 +:4087C000204605F025F8002805D0A17828460EF095FD232070BD0D2070BD002800D102207047704770B500231A46491E0CE00446D440E507ED0F541C0646E640F407E40F89 +:40880000A54200D05B1C521C8A42F0D3D8B270BD30B50021124C0A46A05C002308E0C50701D0491CC9B201290AD840085B1CDBB20028F4D1012903D8521CD2B2052AEBD3F5 +:4088400002290BD207488118C87B0122082B03D29A400243D0B200E01043C87330BD0000A02100085C2100087FB504468034E16A05460E46183108226846FBF73AFE314672 +:408880002031082202A8FBF734FE102168460EF033FCE06A102108300EF02EFCE06A2B46083028331022694606F056FC7FBD10B504460821FFF700FA10212046FFF7FCF92B +:4088C0002079052822D0062820D008281DD1218900200BF07DFA072020712046FEF798FC012819D00E212046FFF72EFE002180200155204601F06EFE2046FFF7D7FD204668 +:40890000FFF7D6FE2046FFF79CFE10BD2089012200210BF041FADEE70521E4E7FFB581B01F4604460821FFF7C7F910212046FFF7C3F92079082803D0092804D0042503E068 +:408940000425012601E009250026204601F074FA00212046FFF7F8FD25712046FFF7A6FD0398002E02D0012808D00BE001280AD12089002202990BF00FFA04E02189029889 +:408980000BF026FA0127002180200155012F07D0204601F01FFE2046FFF753FE05B0F0BD5A2102980855204605F090FD054605480121428A2046FFF75FF9002DEED109202A +:4089C0002071EBE7AC1E000870B50C460546FEF71FFC012809D108212846FFF76DF90023012221462846FFF799FF70BD10B5044601F022FA2046FFF759FD00212046FFF759 +:408A0000A3FD10BD70B505461A24FEF701FC012809D108212846FFF74FF90023012221462846FFF77BFF70BD38B5044600200090A17868460EF0DCFB002801D00D2038BDFB +:408A40002046009D01F0A4FB2946204605F05CFC05480821428A2046FFF70EF906212046FFF772FD002038BDAC1E0008F8B50446002000900E46A17868460EF0B9FB002827 +:408A800001D00D20F8BD204604213830009D0EF010F9AC200059082118300EF00AF9012E02D1204601F074FB2946204605F0B0FB05480821428A2046FFF7DEF8022120469B +:408AC000FFF742FD0020F8BDAC1E000810B50446FFF7CAFE03212046FFF736FD204601F0C9FE10BD10B50021FFF7C0FF10BD000038B5044600200090A17868460EF078FBA8 +:408B0000002811D12046009A01F096F91146204605F005FC05480821428A2046FFF7ACF807212046FFF710FD38BD0000AC1E000838B5044600200090A17868460EF058FB5F +:408B4000002810D12046009905F0B5FC06480821428A2046FFF790F804212046FFF7F4FC204601F087FE38BDAC1E000810B5FFF79EFE10BDF8B50446002000900E46A178D4 +:408B800068460EF035FB002801D00D20F8BDAC20005908212030009D0EF08BF8204604213C300EF086F8002E02D1204601F0F0FA2946204605F053FB0E480821428A2046C4 +:408BC000FFF75AF8204601F08AFD00280AD0204600F026F8002803D009212046FFF7B4FC0020F8BD08212046FFF7AEFC204601F041FEF5E7AC1E000810B54421095C0829A0 +:408C000006D0092908D00A2901D100F09BF810BD0B21FFF799FC10BD00F002F810BD000070B504460079052805D0062803D0082811D00C2070BD03220621204605F019FCB3 +:408C40000F480821428A2046FFF716F811212046FFF77AFC12E006215A200155204605F035FC05466220025B0A20424301212046FFF702F8002D01D109202071002070BD6E +:408C8000AC1E000838B5044600200090A17868460EF0AEFA002801D00D2038BD2046009D00F074FA08202071204601F071FA2946204605F034FB0021412001550F21204630 +:408CC000FFF742FC204601F0D5FD002038BD10B5024601F0B1F810211046FFF735FC10BD10B50446FEF794FA012809D04420005D112805D100231A4606212046FFF70EFE6A +:408D000010BD10B5FFF7D3FD10BD000038B5044600200090A17868460EF06AFA00280DD12046009905F0C7FB05480821428A2046FEF7A2FF0D212046FFF706FC38BD000083 +:408D4000AC1E000838B5044600200090A17868460EF04EFA002801D00D2038BD2046009905F09EFB05480821428A2046FEF784FF0C212046FFF7E8FB002038BDAC1E000812 +:408D8000007870477CB536490978814201D8002404E03449D022096A50430C18002C5DD0204601F052F8002858D0207903280CD005280CD06220015BA07804F0D7F82646FE +:408DC0004036B079012805D030E0042000E0062020712BE00021204604F069FD25468035A86A002804D0A1780EF094FA0020A8620020B071E87801280CD02046C030417B6A +:408E00007D22114041732046FFF71BFC2079072805D007E02046C030417B7E22F1E72046FFF746FC0221204601F03EFD0E48407BC00713D02079042810D120896946088079 +:408E40006034207A88702089000AC870A07A08716089000A487168460BF028FA7CBD0000CC1E00085C210008A021000810B55A22115400F05DF810BD10B50446FF21FEF782 +:408E80001BFF09202071A07804F0B2F810BD000010B512490978814201D8002404E01049D022096A50430C18002C15D0204600F0DDFF002810D10B480068C169204688473B +:408EC000E07EC00608D4BC20005D012804D10648006801682046884710BD0000CC1E00085C210008FC0100080802000810B504468079002809D022215A200155FF212046EA +:408F0000FEF7DAFE204600F013F810BD10B5037902464032002B03D09176092B02D003E0002100E02221917600F002F810BD0000FEB5044600890027009027812079254662 +:408F4000803500282FD001282DD002282BD0002005F00CFB0AE002AA01A9204604F044FC002808D1A17801980EF0C8F9204604F067FC0028EFD0FF212046FEF79DFE204642 +:408F8000FDF798FE3049AF70887B002804D0401E0006000E887306D1F9F7C0FC2A4840304770F9F7A5FC26466036B07FFCF70CFEA86A002803D0A1780EF0ACF9AF62E86A1C +:408FC000002803D0A1780EF0A5F9EF6225464035A97E002934D0009800F0B6F8F07FFCF7F3FD2046FFF74CF8A07802F0C1F8204602F0ACFEA0780AF0E1F8E87B02F0B8FB5C +:40900000A87BFF26FF2805D0104909680A6C00219047AE73EE73A07801F0D2FA0B20FEF7CBFD01F02DF9F9F793FC032807D10648807B002803D1FF20F530FCF735FFFEBD71 +:409040001F21A976C7E700005C210008EC010008FFB583B01E461746054606F0D7F804006AD020460C303146009001F079FF2046062200211830FBF745FA2046062200218A +:409080001230FBF73FFA2D48224600683946836A284698470190049820702846FEF7B8F8012148402E4640366070002D11D028896080F07920710498002811D16879607120 +:4090C000F08BE08028466030018821814088608109E01B488069C005C00F2071002060800498022824D02846062248300099FBF700FAFF2F11D0114801210068026C38463E +:40910000904710482C220068416838465043021D8A180A30085C114601E02079009903F075FD0546FF2801D003F034F8B773F573204601990AF0CFFD07B0F0BDEC0100084F +:4091400000103C40D40100080A4610B5014600200AF00AFF10BD000000B50146FEF756FF084A1278824201D8002004E0064AD023126A58431018002802D002898A4200D0D4 +:40918000002000BDCC1E00085C21000838B504468034E16A002907D1817868460EF03AF8002801D10098E062E06A38BD10B5014600F056FE012803D08878FEF733F810BD01 +:4091C0000348026A8878D02148438430105C10BD5C21000870B5054604468035A879012811D10948A178026AD02048438430165C3046FEF76DFB002805D10220A871A07894 +:40920000314603F0BFF970BD5C2100080EB500220A216B460292198100905A811046029B00990EF04CF90EBD70B5104DA87A00281AD00F4C217FFF2916D0608B01F036F89D +:40924000012811D10020A872401E6083FF20207701F0EAFD044601F021FF010002D0204600F0D8FBFEF7E4FB70BD0000A02100085C2100087047000070B5104AC0B2117803 +:40928000491E11700E490978814201D8002404E00C49D022096A50430C18A07900280BD025466035687FFF2806D02046FFF71EFE0020A071FF20687770BD00007A01000882 +:4092C000CC1E00085C2100087047490510B5490F0B0001F009FB060704080C0C0F073E21FFF7C4FD10BD0821FFF710FE10BDFFF71FFE10BDFFF7FAFD10BD0000F8B52B48F7 +:40930000002500904DE0A84201D8002604E02848016AD02068430E18F9F700FB30464030C48A078B0021C1820183F9F7E1FA304600F08BFD012831D1A00702D52846FFF783 +:4093400021FDE00602D52846FFF7A2FDA00602D52846FFF75BFF600609D5F9F7DFFA1449002040314870F9F7C3FA00F005FF200602D5284600F020F8600702D5284600F071 +:4093800043FCE00703D021463046FFF79EFFF80704D00849B0780968496988476D1C0098EDB20078A842AED8F8BD0000CC1E00085C2100080802000805490978814201D8B5 +:4093C000002070470349D022096A504308187047CC1E00085C21000810B50446054800680168204688470448006801692046884710BD0000FC01000808020008F8B5054673 +:40940000FF20694608702888FFF7A6FE040035D000F01BFD002831D0207909282ED002236A460021204600F076FD012828D02046FDF7EEFE0646E07920210843E07120468C +:4094400004F052FA002823D0294601F005FA02236A46FF21204600F017FD01281AD04620005D00281BD02325E079DF210840E0712946204604F08FFB2846F8BD0220F8BD63 +:4094800068460078012801D02A20F8BD2320F8BD0720F8BD02204034A0710020F8BD002E05D02046FFF72AF90500DDD1E4E70C20F8BD000070B50E460C2501F0EDF80400D8 +:4094C00013D00025228929460A480AF073F80123FF2202212046FFF7BBFDA07801F0F2FB2046FFF725FD022000E000203070284670BD00000E200000F8B5044601F0CCF86C +:40950000002801D00C20F8BD6079A11D00F0DEFDFF2801D00B20F8BD02216846FEF77AFD012859D13248017868460078814201D8002504E02F49D022096A50430D18002D07 +:409540004AD000212846FEF7FFFF2E46002040367071B0712848002100684268284690470620FEF729FB2F46208A60373880E289A189A87809F0A4FCF083608A78800420E7 +:40958000F0760320B0831B4806228778A11D2430FAF7AFFF2079012820D06079F0710121A01D03F007FCFB20074012488770217E012918D0C278FB210A40C2700F482146FF +:4095C0000068826828469047A978204603F0C2F82846FFF7ECF8F8BD0920F8BD0020F07104200743E1E7C17804221143C170E5E7CC1E00085C21000808020008EC010008E0 +:4096000070B5164602461B480D460078D0211A4B5143904201D8002401E0186A4418002C26D0204600F01CFC012809D1186A8431405C1146FEF74CF9002801D104F07AFE5E +:409640000E483146006882692046904700280CD0204680308178A94201D3491B00E000218170208929460AF0F4FB204601F002F970BD0000CC1E00085C210008FC01000869 +:4096800070B505460088FFF767FD040014D000F0DCFB002810D02079092822D0A97825464035A976204604F011FF0646A879012804D06220025B02E0022070BD6A8A0A20C3 +:4096C000424301212046FEF7D7FA01F055FB8021204602F059FD01F06BFB002E01D109202071002070BD0EB5002218216B460292198100905A810120029B00990DF0DFFE10 +:409700000EBD0000F8B5194E0025B07A002824D101F0C4FC26E001F0BBFC1549401801680068CCB287B22146384600F0BFFD012814D010480121478304774577B1720E49AE +:409740000978A14201D8002003E0006AD0214C430019002801D001F08DF8F8BD01F09EFC6D1CEDB20028D6D1F8BD0000A021000800103C405C210008CC1E000810B5044670 +:40978000C0060FD50C4900200B6A0C490A7807E0D021414359180979022909D0401CC0B28242F5D806480068C1692046884710BD00F050F8F6E700005C210008CC1E00081E +:4097C000EC01000810B50088FFF7C6FC040007D04420005D082805D00B2803D00C2010BD022010BD2046FFF71BFA002803D009212046FEF7A9FE002010BD70B50546008863 +:40980000FFF7AAFC040008D0264640363079082805D00B2803D00C2070BD022070BDAC20005910220830A91CFAF763FE2046FFF71BF83079082804D02046FFF783FA0028AF +:4098400003D00A212046FEF77FFE204601F012F8002070BD70B51E491E4D0978814201D8002403E0D0212A6A414354182179022904D0002901D003F0BBFB70BD01228321A4 +:409880000A5501F03FFC032020710820FEF794F900212046FEF758FE0121204601F004F8204647300121064601F078FB0A480068416A304688470246012300212046FFF736 +:4098C000C7FBA078FFF788FDA87B401CA87370BDCC1E00085C210008EC01000810B50C46002121700088FFF737FC03000BD000F0ACFA002807D00948F521807A0840C00684 +:4099000003D4112010BD022010BD022020705A8A188900210AF044FB002010BDAC1E000870B50088FFF718FC040008D000F08DFA002804D0E079C10903D0002070BD0220A8 +:4099400070BDC1068025002908DA2843E07108480221428A2046FEF78FF9EEE7204600F053FC0028ECD1E1792943E17170BD0000AC1E0008F8B50F46002569460D702E4628 +:409980000088FFF7E9FB040010D000F05EFA00280CD0E079410638D4E17E4A0708D48A074021002A1BDA0843E0712EE00220F8BD05F02CFC067021894180E1898180A17EC3 +:4099C0004170218A0546C180022038702978104809F002FF28460AF087FA0020F8BD0843E07102236A460C21204600F04DFA00280BD102236A46FF21204600F08CFA0028CC +:409A000003D1204604F090FD05462846F8BD00001D0400003EB500220F236C460292238100910190628169460EC900200DF047FD3EBD0000F8B50F46054600F04BFE04003A +:409A400052D0032020710026832006552046E6703146473001F0A2FA05F0EEFB25464035EA8B6179FEF716FB1030FF2281B249321346204604F094FD0920FEF79DF8A07884 +:409A800001F05CFB0021204600F00EFF00212046FEF75AFD6E710023AE713A4619462046FFF7D6FA1248002100684268204690471048817B491C8173A078FFF78DFC00F0DD +:409AC000EBFD040007D00B480021243003F072F9204600F0C3FCF8F73BFF032803D14034E08BFCF725FAF8BD284603F081FAF8BD080200085C210008F8B50446FF206946AD +:409B0000087000262088FFF727FB05001AD0FDF77FFB002812D02948807AC00710D0284600F093F900280DD0287903280CD004280AD0072808D0092836D103E00C20F8BDAE +:409B40001120F8BD0220F8BD4420405D01282BD02846FFF71BFB070028D00822211DFAF7C8FC3846A1782030017261881022090A417221460C311838FAF7BBFC02236A46C1 +:409B8000FF21284600F0C7F9012811D002236A460521284600F078F9012809D0284600F03FFC06463046F8BD0D20F8BD0720F8BD01212846FEF7C8FCF4E70000AC1E0008CD +:409BC00010B50E4AC0B21178491E11700C490978814201D8002404E00A49D022096A50430C18208B102108432083A07803F000FA08212046FFF78AF910BD00007A01000855 +:409C0000CC1E00085C21000810B517490978814201D8002404E01549D022096A50430C18002C1AD020464030417902290BD1002141718320005D012810D02046C030417B4E +:409C40007D2211404173207E0021C207D20FA07803F078FA2046FEF7F4FC10BD2046C030417B7E22EDE70000CC1E00085C21000870B505460E460088FFF76EFA04000BD0BC +:409C800000F0E3F8002807D01248F521807A0840C00603D4112070BD022070BD6020005B5E21095B401C48430004C10C6888884201D2122070BD60822079072802D1204699 +:409CC000FEF7F6FC02203070208900210AF090F9002070BDAC1E0008416A491C416204D1017F491C4906490E01777047016A491C016204D1417F491C4906490E41777047CB +:409D0000F3B506463D4881B00078B04201D8002404E03B48016AD02070430C18002C05D0FBF7FEFA807AC00702D00EE00220FEBD2546C0352F68F8F7F1FDD02200212046E3 +:409D4000FAF7E0FB2F60F8F7D3FD2E480299006882682046904705004DD1A6700026E676267131462046FEF7EFFB204600F064F8204603F05FFD244F6782862006551F48F0 +:409D8000F5212038807A084000D00120A07526830298002805D020462021C030FBF7A2FA85B2C020005920220021FAF7ABFB4C20A664065320464030C671FF21C1738173FA +:409DC0000122603042750275C27582754276027603228276C27606774277002022186032401CC0B251770328F8D305484030C07820736034E780E8B2FEBD0000CC1E000857 +:409E00005C210008FC010008FFFF000010B50020074B084AFF2119541418401CC0B221740428F8D31F2119541018017410BD0000A02100085C2100080021416201770162FA +:409E4000417740300170417070470079002805D0012803D0022801D0012070470020704780308079002800D00120704740300079002807D0012805D0052803D00E2801D05F +:409E80000120704700207047F0B5002405461470C07E0126C006002803DA0124142900D116702846FFF7E2FF002803D00124052900D11670E87E470708D480070ED5012469 +:409EC0000C290BD11670E87E400707D5E87E800704D4012B01D10C2905D001248320405D012802D008E00024F8E7A879800703D50124082900D11670012B02D1092900D1FB +:409F000000242046F0BD10B5807803F035FB002800D0012010BDFFB581B0019F04980026403714460D46022810D17879012803D1012D00D120700126B879022800D10126B7 +:409F4000019803F087FC012800D1012600232370797980208122022908D1012D02D0002D02D002E0227000E020700126B979012908D10126002D02D0012D02D002E02270E9 +:409F800000E020700198A030017F032902D0042908D003E0162D11D101262670007F022804D00BE0162D09D1002607E00126182D03D0162D01D0172D00D12270049802282E +:409FC00006D12078C00702D00120207000E02370304605B0F0BD000010B5084A1278824201D8002004E0064AD023126A584310184030C173084602F0CDF810BDCC1E000831 +:40A000005C210008F8B500240F4D104E17E0A04201D8002103E0D020316A604309180846FFF713FF002808D00F464037F87BFF2803D001F09DFBFF20F873641CE4B22878B3 +:40A04000A042E4D8F8BD0000CC1E00085C210008F8B5064600240F4D18E0A04201D8002104E00D48016AD020604309180846FFF7ECFE002808D00F464037F87BB04203D13E +:40A0800001F076FBFF20F873641CE4B22878A042E3D8F8BDCC1E00085C21000810B50449C0B20A78521E0A70FEF77EFA10BD00007A01000810B50449C0B20A78521E0A7098 +:40A0C000FEF78EFA10BD00007A010008F3B50024C70781B0134EFF0F1FE0A04201D8002504E01148016AD02060430D182846FFF7ACFE00280FD02946062248310298FAF76A +:40A10000E9F9002807D14035E879C007C00F874201D12046FEBD641CE4B23078A042DCD8FF20FEBDCC1E00085C21000830B50446FF281BD000210E4B0E4D14E0884201D8C3 +:40A14000002203E0D0202A6A484312181046FFF77CFE002805D04032907BA04201D1012030BD491CC9B218788842E7D8002030BDCC1E00085C21000810B500F055FE0446D0 +:40A1800000F08CFF010002D02046FFF743FC10BD70B5054604468035A879002827D1FF20E075174BA078D0225043196A85300A5CD026521CD2B20A54A078196A7043114E35 +:40A1C0008530768AB24201D300220A54A078D02250430246196A85328E5C84300E54A1783046FDF775FB002802D00120A87170BD0220A871A078314602F0C4F970BD000049 +:40A200005C210008F02100087CB50446FF206A46002110700191014602232046FFF77BFE01280FD002236A4608212046FFF72CFE012807D0A17801A80CF0DAFF002809D09E +:40A2400007207CBD68460078002801D023207CBD2A207CBD2046019DFCF7DAFF00280BD02946204604F016F804480221428A2046FDF702FD00207CBD11207CBDAC1E00088D +:40A2800070B50024074E084D07E0D020316A60430818FEF7D6F9641CE4B22878A042F4D8002070BD5C210008CC1E0008F0B50F46810785B0890F0291000A6946888055484A +:40A2C0000078B84201D8002404E05348016AD02078430C18002C26D000F0DAFE06466846808800280BD00298012840D002283ED0032809D04120005D01286ED085E047481F +:40A3000030180068608180E000200290A17802A80CF046FF002807D04120005D012877D12046FFF7D9FC73E06846029D82882946304602F095FF394830180068608120468A +:40A34000FDF7E6FF01AA21462846FDF7B9FE002807D0384600F0C0FCA17828460CF0B0FF28E0EF772946204603F094FC4DE00020009020890390A17868460CF0FFFE0028B7 +:40A3800002D0002005B0F0BD6846009D8288291D304602F065FF2148301800686081384600F09AFC2046FDF7B3FF8020005D00280FD106E03D205A2108552046FEF75CFD04 +:40A3C00026E001AA21462846029BFDF7B5FE002804D028460CF06AFFECE713E00298FEF700FA01460398287003980901000A0843687068468088A870000AE8702846FFF795 +:40A4000072F905E02046FFF767FC384600F064FC0120B7E7CC1E00085C21000800103C4070B501790546032904D0042904D0072908D109E0052400E006240121FEF716FB45 +:40A44000002805D00D2070BD0824FEF7EDFAF7E7284600F00FFA2C71002070BDF0B587B0054604F0D3FE044604F0C9FE019004F0BCFE009004F0CEFE029004F0DDFE0690D7 +:40A480000098207000982F46000A607000984037000C0590A07000982E46000EE070F87E20710198607101986036000AA07101984149000C0490E071387F2072B88B0522E1 +:40A4C000000A6072B87FA072F88B000AE072307820733088000A6073B078A0737088000AE073204610300391FAF703F80020E870A878039902F0C8FD0020687106980299B5 +:40A500004001084300216175A075000AE07504E0F98B288849004018288000F0A5FC2988042200F05FFE0128F2D023481038417C027C090211433182C17C827C0902114389 +:40A540007182007DB0820298307600983081059870810198B0810498F0811848298801601821204602F0A6F87088F98BC000F8F7CFFA124980B28860012183204155A878C6 +:40A5800000F07EFBB188A87802F0F8FBF98BA878042208F02BFAF8F71DFA0446A87808F0E7FC06494031086200F07CFB2046F8F715FA07B0F0BD00006C21000800123C4046 +:40A5C00010B50021FFF79CFB002801D0002010BD012010BDFEB50546803001908079002839D0AE780096D021294C4E433746206A8437C05D0099FDF780F9012828D0226A66 +:40A600002046D15D491CCCB22249498AA14200D80024019B002199713346FF218533D154026A8636D1550021006A0B4681550A46009802F0C7FAE97DFF2904D0284603F0EB +:40A6400064F8FF20E87503F075FE0026114F1AE0019803218171FEBD00200090224669462846FEF73BF80099002904D0FF231A462846FDF750F9641C788AE4B2A04200D8C0 +:40A680000024761CF6B2788AB042E5D8FEBD00005C210008F021000800B5022000F002F800BD000030B5044608480021036A0848027807E0D020484318180579A54204D012 +:40A6C000491CC9B28A42F5D8002030BD5C210008CC1E000800B50120FFF7E4FF00BD10B5044604F093FD218901808034E16A4160E16A2831816009F085FB10BDF7B50746CF +:40A700000C460879897882B0092807D0F9772046FFF7A6FB4D4E012806D00FE038460CF0EDFD022005B0F0BDA178D0204843326A8430105CFDF7CCF8012824D0A078FDF7FC +:40A7400067FE01281FD03D780121384603F0CCFC2046FEF72BFD0190A17802F07FFF002818D0204681213A4AC0300C2D3ED023DC26464036002D26D0012D27D0062D33D07D +:40A780000B2D4BD128E06846027C21463846FEF713F8C7E7A078D0225043316A85300A5C002A01D12B4A927C521E0A54A17838460CF0A4FD0720B5E7122D24D0142D25D07E +:40A7C000162D2BD104E00122B27101E002227271427B0A43427321E02046FCF719FD01281CD10020307019E00120FBE7E07E400704D4528A04212046FDF73EFAE07E022176 +:40A800000843E0760AE0528A102104E0E07EC00604D5528A40212046FDF72EFA009504AA21463846019BFDF7BFFC69460A7CA0780323019902F03CFCA0780199FCF70CFA8B +:40A84000A17838460CF05AFD00206BE75C210008AC1E0008F02100088A8802804A884280CA8882800A89C2808A890281498941817047000010B50246803293790021002BC3 +:40A8800003D19278002A00D00121064A927A002A00D000210279092A00D10121807802F085FC10BDA021000870B50C460546FCF7AFFC00280BD1012C06D92879092806D06D +:40A8C0002846FFF720FB0446002C02D004E0012402E0287EC007FAD1287E2146C207D20FA87802F02FFC70BD30B47446641E2578641CAB4200D21D46635D5B00E31830BCEC +:40A90000184700000B4B01280BD002280BD004280BD008280CD10748803002630548A83005E0202002E0382000E05020C01801607047000000103C400149886070470000A8 +:40A9400000103C4010B50446FF20F130012C04D0022C05D0042C08D105E0FF20D53004E0FF20D93001E0FF20DD30002202F074FD03490869034A80B2A0431080086110BD63 +:40A9800000103C40E2010008034A1169034B89B2814319801161704700103C40E2010008034A1169034B89B2014319801161704700103C40E2010008F8B5244F14243A680C +:40A9C000054665432C46936813341B5DF1269B0036019B191E4E9B1900931E68B6B2760876001E602C2306465E43002909D190685168035D301D08181649FF22C96902F027 +:40AA000007FB3868A91D80688022035D40181149896A02F0FDFA38680E498068096A035D4019202202F0F4FA38680A4980680C35035D4019496A402202F0EAFA3868012187 +:40AA40004068805B084300990860F8BDD401000800103C40F0210008F8B505460120A84086B214460F46012231467C2002F0F4FC3A463146782002F0EFFC607826780002EC +:40AA80000643E078A27800020243607923790002034307480C2180694D430649401944182660001D44182260001D40180360F8BDF021000800103C40401880B270470000EA +:40AAC00030B5124BCC061B7849095B0701255B0F640E0902ED02012B10D0022B0ED0032B01D0042B09D18007800FD2072843120E0243144306482143816230BD044321439D +:40AB0000D001084303492843886030BDF021000800F13D4080143C4010B5234A12785207520F012A29D0022A27D0032A01D0042A22D1421C13461C78007822465C782402D5 +:40AB400022439C78DB78240422431B061A431202164C0243A260481C024613780978184653781B0218439378D2781B0418431206104300020843E06010BD4278037812020B +:40AB800013430B4A1361C37880781B021843506148780B78000203439361C878897800020143D16110BD0000F021000800F13D4000143C400B4A12785207520F012A09D061 +:40ABC000022A07D0032A01D0042A02D1064A106051607047054A83B21360000C5060916070470000F021000800F13D4000143C40044A002180180268491C89B21029FAD3A2 +:40AC00007047000000103C4010B50C4602F08CFC01494018046010BD00103C40704770B50C46054600F018F821462846FFF7ECFF70BD0000002310B5F121064A09011846D3 +:40AC40008C182360091D401CC0B289B21028F7D310BD000000103C4070B50C46054602F069FC0549054A097D694309190902214389B28018016070BDF021000800103C40A4 +:40AC800010B504490863FF20012220211D3002F0E3FB10BD80103C400149086070470000C0103C4000B50549012088600449442008600420FFF774FE00BD000040123C40AD +:40ACC00000103C400349086302494520803908607047000080103C40054AD1687C2389B2994380000843D06002494D200860704740123C4000103C4070470000054B19688B +:40AD00000722920289B2002801D0114300E0914319607047001F3C4010B5094800784007400F012808D0022806D0032801D0042801D10DF067FA10BD02495420086010BD11 +:40AD4000F021000800103C4010B5094800784007400F012808D0022806D0032801D0042801D10DF057FA10BD02495320086010BDF021000800103C4000B503490888488003 +:40AD8000FFF702FE00BD0000E201000810B5F7F7A7FD012802D10320FAF756FD0120FBF72BFF02495020086010BD000000103C4000B502484088FFF7F3FD00BDE20100082D +:40ADC00010B5FAF779FD10BD03490868012280B2D203104308607047001F3C40884201D8081A03E00022D243101A401880B27047884201D9401A00E0081A044980B28842D4 +:40AE000003D901210904081A80B27047FF7F000000210170704710B50B4602460021F820FAF760FB10BD00000148006BC0B2704780103C4010B50A490978814201D8002443 +:40AE400004E00849D022096A50430C18F7F766FDC0342068C48BF7F74BFD204610BD0000CC1E00085C2100080148806880B27047C0103C400148406880B2704740503D4038 +:40AE800000280DD00C4A90690870000A4870D0698870000AC870106A0871000A48717047064A10680870000A487050688870000AC8709068F0E7000040103C40C0113C4048 +:40AEC00000B5024A00F004F800BD0000FF7F000000B51346FFF782FF984201D8022800D2002000BD0148006980B27047001A3C400148406A80B2704700103C40014840698E +:40AF000080B2704740103C400148006880B2704700503D400148C06B80B2704700103C40F8B50646002402F0EFFA0546304602F023FB064609480021878A0BE001208840A0 +:40AF4000034602462B403240134301D02043C4B2491CC9B28F42F1D82046F8BDF0210008002910D00B4B196B8AB2596B9B6B89B20270120A42708170090A9BB2C17003715B +:40AF8000190A41717047044B996A8AB2D96A1B6B89B2EDE700123C4040103C40012905D0054989690904C90F017070470249403189688907C90FF7E700103C40FFB581B095 +:40AFC00000242D4B2D4D0B9E002805D0022803D003283ED006281DD1A86B2F4684B2A004850E2007000F012802D0252D1AD916E00C2D14D106230021F820FAF773FA0623DB +:40B000000021F820029AFAF76DFA002E01D0B86B1DE0002304980480184605B0F0BDFFF7D3FEF9E706230021F820FAF75BFA062DEFD30A98002806D0AD1F0246ABB200214B +:40B04000F820FAF74FFAB86B002E80B2E1D03080DFE7A86B84B2A004800E0C28DFD106230021F820FAF73EFA06230021F820029AFAF738FAA86BCCE7FFFF0000C0103C40B9 +:40B08000024800684005C00F70470000001F3C400148C06870470000F02100080248806A8006800E7047000000543D40084910B58000084B4218D9687C2489B2A1430843D9 +:40B0C000D8600548101800688006800E10BD00003044010040123C4000103C400148406880B27047001A3C4010B5054B1A8A9C8A5443444398684A432018801810BD0000F4 +:40B10000F021000870B50B4908630B49D024444325460B6AFF2285355A5523460D6A8433EA54096A002286340A550123114601F049FD70BD80103C405C21000870B50B4A6C +:40B14000D02141430D46146AFF23853563550C46156A84342B55126A00238631535400220123114601F02EFD70BD00005C21000870B50B4AD02141430D46146AFF238535E8 +:40B1800063550C46156A84342B55126A00238631535402F0C3F90349C98D02F07BF870BD5C210008AC1E000870B50D460B490978814201D8002404E00949D022096A50435D +:40B1C0000C18F7F7ABFBC0342068C48BF7F790FB02222946204600F005F870BDCC1E00085C21000810B50023884201D8081A03E00024E443201A4018044980B2884201D83A +:40B20000824200D90123184610BD0000FF7F0000024840680006C00F70470000C0103C4070B55478157824022543D47888232602947834435679127936023243002900D02C +:40B2400098230449086303488038181805604460826070BD80103C40FFB581B015460E4607460A9CFFF740FF002C0AD022460B9B049902F021F90549B0004018C55505B066 +:40B28000F0BD0B9A049902F0FDF8F4E7C5210008F8B59C469308394D002403E0A600AF598751641C9C42F9D39207920F4B1C002A06D0012A15D0022A27D0032A39D13EE05F +:40B2C0001D7809782A465D782D022A439D78DB782D042A431B061A4312020A43A100425027E0A600AD590C78CB7822464C781B06240222438C78240422431A431202EBB24E +:40B300001A438251C978301812E0A200AB584C780D7824062D042C431D042D0E2D022C43DBB21C438450CB788C7819022143101841606046012801D1FFF7EEFCF8BDA40087 +:40B340002A59097815022D0E09062D04294315042D0E2D022943D2B2114301511A461B78194653781B0219439378D2781B041943120611430902090A2018D9E750F13D400C +:40B3800070B50C4D2A785407640F012C08D0022C06D0032C01D0042C01D100F00FF870BD02460B46044CA888082121620021FAF71FF970BDF021000880143C40F0B52B4A11 +:40B3C00008232A4E503A5363546B9C435463820703D000238F08BF001DE08C08002203E09300C558F550521CA242F9D3A30014E0C218521C144625782A4665782D022A43D8 +:40B40000A578E4782D042A4324062243C45C12022243F2501B1D9F42EAD88A0724D089070022890F012904D0022904D0032917D107E0C25C14E0C018417800780A0202437D +:40B440000EE0C01801460A7810464A78120210438A78C97812041043090608430202120A0248103818180261F0BD000050F13D4070B51A4909784907490F012921D0022911 +:40B480001FD0032901D004291AD10446FFF75CFC134D00216018401C02461378184653781B0218439378D2781B04184312061043625C000210434A191061091D1029E9D3EB +:40B4C00070BD212504466D01FFF73EFC1023224600212846FAF78CF870BD0000F021000800F13D40154909784907490F012918D0022916D0032901D0042911D1411C0A463B +:40B5000013780078194653781B0219439378D2781B0419431206114309020143084801627047417802780902064B0A439A63C178807809020843D86370470000F021000805 +:40B5400000F13D4040143C4008B5094A127D4243521812020A4380210A4369460A8001F0E9FF69460988034A8018016008BD0000F021000800103C40FEB5044600266846DD +:40B580000680868006810125A078FBF7DDFD0746A078FFF7C5FC0743A078FFF787FD0743A07802AB01AA694600F020FA3146264660363177002F55D12079092852D06846F3 +:40B5C000808800284ED0204602F03AF9002849D0684681882046C030002909D00168CA79022A05D0CA7AD30902D05206520ECA720068817A002905D0C17AC90902D1217EAF +:40B60000890600D50025214640318A79012A06D04979022903D0BC21095D02290CD1718BC08BFFF7DBFB69468988C91C884202D30D49884200D9002568468088002811D066 +:40B64000012D0FD10421204600F0B0FD01203077684681880422204600F0CAFD208B082188432083FEBD0000FF7F0000F8B5044680782521C001C9024018394940184069BB +:40B6800086B2F7F74BF9FFF7C3FD002864D0207E000761D420466030017F01295CD146210B5D00252146C0312A46012B07D1438B0868C08B834251D0401C83424ED0294888 +:40B6C00003689BB200938368FFF7CEFB5F06264B03D5009D2D1AED18ADB20F687988814201D2401A05E0814209D93F888F4206D2081AC01882B21D48824200D900221B4848 +:40B70000854229D8D00700D0521C50083146F7F7FFF907464800301A4004010C0A2901D9012300E00223581C704340000A30A84212D81021204600F039FDF81881B210226A +:40B74000204600F055FD204600F08EFC00F01EFC208B082108432083F7F7CAF8F8BD000000103C4000503D4000000100FF7F0000FF2806D0034B196A012289B28240914376 +:40B7800019627047801F3C4030B513490A680146C0310B689A80037902464032022B13D00B6800241B88958B6D00EB181B190C689BB223809279012A05D160304088096847 +:40B7C00000011818888330BD044B5B6A93830B6803249B88E7E7000080503D4040123C40F0B585B0002704460546C03403972068252201880291A978D202C90189182E466D +:40B8000040360191B17901297ED044494A68828088682168802208822068022781880291C17A1143C17203F007FDF28B6979FCF731FC0146284660300090C18203F0FCFCF0 +:40B84000B18BC9198AB26979FCF724FCB179344A012921685FD00B8AD31A1B18D833CB8103992F4B0918F07E5843081821688881B08B410002980818C01987B22068591EAA +:40B88000078020680290C089884210D9491CF7F73FF90299381A088027682149F889F7F737F9F9812068022901D20221C181B07901282BD1009920684988028809015118B1 +:40B8C000818300980321C08A09030005000D8843A035297D8907C90F09030143687D8007C00F42030A430F4901984018C26221688989C16320680B49028A0198403140185F +:40B9000042602168C98900E002E0C16005B0F0BD8089039087E7CB891B18A0E780503D407102000000103C40F8B52F4DAA6AEB6B92B29CB28378E606F60EB34214D12A4E7F +:40B94000034689074036C03300290EDA002160300177186801884180F06819680880A00602D41968A009C881F8BD1968CC8B641CCC83696A1C68A183E96A1C685704A18007 +:40B9800011061C68890FE17191041C68890EA1711968FF0FCC7AD20B3C43CC7219688A728321095C002910D11968002A07D10A884A80F1681A681180696B1A68D181296BBA +:40B9C0001A681182A96B1A68918119688A7A002A06D000224A830022042100F0BFFCF8BD4A8B521CF6E7000000503D4010B52524C001E4020019044C001944690C80816928 +:40BA00001180C069188010BD00103C402522C001D2028018024A8018406908807047000000103C403EB5044600F06EFD684606F0D5F9684600780022022836D26846817864 +:40BA40001B4803781B48994201D3002103E0D025036A6943591821604078430706D4800707D514482030007E800702D060318A8015E00A4660326846D388808883420DD9E2 +:40BA800083235B5C002B07D1C0310968C9890C2902D8012800D9401E908000E093800298002801D000F0F8FC3EBD22603EBD0000CC1E00085C21000802488068C006C00ED4 +:40BAC0007047000000503D4008B5034680786946FFF79CFFFFF7C8F9C0331968801C0988401A01210904401880B24910884207D2694609884900F7F70BF8401CC0B208BD10 +:40BB0000012008BD2522C001D2028018024A8018806908807047000000103C40F8B5054604464034A0792F462E466037C03601282AD13068798BC08BFFF750F92D49884244 +:40BB400005D2032803D24021284600F01DFBA079012819D13168788BC98B884214D18320405D0028284613D0FFF70EFE2021284600F00AFB284600F03DF9284600F0CEFA33 +:40BB8000E08A82210843E082607902280ED019E0FFF726FE4021284600F0F6FAF6F7D8FE0328E7D1E08BFAF7C3F9E3E73168788BC98B884206D1284600F006F9E08A042123 +:40BBC0000843E082BC20405D022811D13168788BC98B88420CD108480068416A284688471021284600F0D0FA208B012108432083F8BD0000FFFF000008020008F3B506460F +:40BC00000446C036306881B0818B0088FFF7E6F821792546204F4035032919D91921C902884215D9FFF720F93168898BFFF748F9717900290CD1002820D081004018C20831 +:40BC40002046A178154B7E30F9F75AFF012070718320005D00281DD1207903281AD90E4B0299703330685943AF238289DB00C91A8A420FD9A979012909D103E0E88A38430F +:40BC8000E882E3E76034C08B618B884202D0E88A3843E882FEBD000001020000C19B0010F8B582782523D201DB02D51876220446125AC03420684A43C1898918C1812068D0 +:40BCC00081898918818126682721F0890901884211D94F1C3946F6F71BFF3188081A308026683946F089F6F713FFF1812068022901D20221C1812068024980896918C863A4 +:40BD0000F8BD000000103C402521C001C90242180D4800211018016041608160C160016141618161C161016241628162C162016341638163C16304484030101801604160EA +:40BD40008160C1607047000000103C40F8B50446FFF712F88320A178005D06F039F91649086882B28868254680B246060023C035002E1CDAC006A478C00EA04217D1FFF7BE +:40BD800073F8101A01221204801880B201280ED90124CC60C8688007FCD56846FFF742FE0098002801D000F015F92C7100E02B71FEF7FEFFF8BD000000503D4010B500F04D +:40BDC000A3FB06F06DF910BD81782522C901D20289186030064A038A89180B62428A4A628A6A808A92B2120A120210438862704700103C4081782522C901D20289185E2219 +:40BE0000135A074A89184B610246603213888B615288CA61C0300068808B48637047000000103C4081782522C901D20289180A4A8918CA6A032392B21B039A43A030837D63 +:40BE4000C07D9B07DB0F1B038007C00F134340031843C8627047000000103C40F0B581782522C901D2028B1801466031244A0C899A1814604C8954608C89946004464034AD +:40BE8000E67ECD8936023543D560E48B54610C8894614C88D4610C8A14624C8A54620D7E46792D028C8A760335432543ACB294628324134E245C40360025C030002C0CD03E +:40BEC000D56200689B19808818600E4B0A2018628888106355639563F0BDCC8A03272405240D3F03BC43D4620468A489D4630468278A9C1967600768FF89E760E1E70000D2 +:40BF000000103C4000543D4030B581782522C901D2028C181C4962181368014660310B8153684B8193688B81D368DDB2CD811D0A03464033DD7615699D835569DD839369EB +:40BF40009BB20B80D5694D80156A0D82556A4D82926A92B2D5B28D82D504ED0E520B0D764271002B01D000220A770749403161180A68C03003689A804A6803681A82C9685B +:40BF80000068C18130BD000000103C4008B510490122086883B2886840060FD5FEF764FF181A01231B04C01880B201280ED90120C860C8688007FCD5002A07D06846FFF709 +:40BFC00031FD0098002801D000F004F808BD000000503D4070B581782522C901D2028B18144A9168490604D50121D160D1688907FCD50146C0310C46096809881160642170 +:40C000000D4D095A5B191963014680310B46C97800290CD000215160DB7881785B014024234319439160807806F0A2F870BD2168C989F0E700503D4000103C40044A1168AC +:40C04000FF23F13389B29943000101431160704740503D4003490869012280B21203104308617047001E3C40FEB5044680786946254648708035E8780870062027468870D6 +:40C08000C03738680088088102A9684606F08CF8002838D10520694688701E480126807A800603D5286B017E807A01E01B210846EA78002A00D102262246A032137D012B31 +:40C0C00022D089003C313B68527D9C890919012A1DD080003C30FF302D300F4F08183946F6F716FD801985B26846858060003946F6F70EFD401CA84201D96946888001A937 +:40C10000684606F051F8FEBDC9007031DBE7C0007030E0E7AC1E0008710200001CB581786A4651708321095C1170042191704030C08B908001A9684606F036F81CBD10B5EF +:40C1400086B081786C466175014680310A46C97821750821A17500212181A1725E231B5AA3810223E381D278A274012222700191C02109580988218280786075214605A833 +:40C1800006F012F806B010BD10B5807805F0F8FF10BD0000FF2806D0034B196A012282400A4390B218627047801F3C40C030026810290ED09179D18201680A884A800168FC +:40C1C000CA8B0A830168CA894A820068818981827047518AD18101688A8A8A8101684A880A8001688A7D8A710068018BC1837047F7B5064680780D46252288B0C101D2027D +:40C200008918039106AB05AA01A9FFF7EFFB3446C034374620686037798BC08BFEF7DEFD03462068798BC08B401980B2FEF7D6FD01460A98082828D1304640308279012A25 +:40C2400023D1444A914220D993421ED2002B1CD02268B97E927F891AC9B20091C08B029068466A1A8088049050430299F6F73AFD00994018401C85B202984200681A4243AF +:40C28000049840004843101803E0684680884000684321680A8810180880206800908179387E684308182521F6F732FC009881710A98082809D02068C18B4919C183803647 +:40C2C000F078254E00280DD033E03079032803D12068418B491941832A460821304600F03DF8ECE72168F88ACA8968431218CA8121688A891018888125682721E889090187 +:40C30000884211D94F1C3946F6F702FC2988081A288025683946E889F6F7FAFBE9812068022901D20221C1812068818903988019C1632068C17980798A07D20FC9079200CC +:40C34000090F1143000208430399891988630BB0F0BD0000FF7F000000103C40FEB50F460446002069460880888016460881A07801AB02AAFFF73AFB254620460123C0354E +:40C3800040302179042F02D003294AD053E0092902D0032908D030E0217EC9062DD4C18A01221943920226E029688A7A012A1AD18A8B002A10D1A2782526D201F602961960 +:40C3C000264A926862273F5B3F01BA1892B28A832249C03971184A63C18A02221143C1822179032909D12968498B062905D3C18AFF22194301321143C1822046FFF78EFB2A +:40C40000684601882046FFF7F9FB8320005D002806D168460089002802D02046FFF7ACF8FEBD2968498B062905D3C18AFF22194301321143C182002708E02868C18B491C3C +:40C44000C1832046FFF76AFB7F1CBFB2B742F4D3684601882046FFF7D1FBFEBDC0103C40F1B50B4F0025386A84B20A48406986B202E0A01984B20125012221460098FEF747 +:40C48000B1FE0128F5D0002D00D03C62F8BD000040123C40C0133C40F8B5002405F0F0FC0546174E174F27E0E80722D03078A04201D8002003E0D020396A60430818FFF710 +:40C4C00003FB01463078A04201D8002003E0D0203A6A604310180822FFF78AFE3078A04201D8002003E0D020396A60430818FFF7BBFD6D08641CE4B2002DD5D1F8BD00000D +:40C50000CC1E00085C210008FEB5684605F0E6FC68460078002830D00024184D184E29E0C00722D02878A04201D8002003E0D020316A60430818FFF7C7FA01462878A04221 +:40C5400001D8002003E0D020326A604310180822FFF74EFE2878A04201D8002003E0D020316A60430818FFF77FFD01984008641CE4B2019001980028D2D1FEBDCC1E000865 +:40C580005C21000810B50C4600F0C8FF06494018016889B20A091201FF21224301310A43C9008A43026010BD00103C4070B526490446097800204907490F40250346012963 +:40C5C0000FD002290DD0032901D0042924D100201E4E0146012C24D0032C1ED0052C25D122E000211A4E0A46012C08D0032C02D0052C09D106E0B56002210A2204E00421BE +:40C600000C2201E004210D223461306AC0B204460C42FAD03262336170BDB56202200A2104E004200C2101E004200D21F462726B14460442FBD07163706B0821884370635F +:40C64000F362D0B270BD0000F021000800F13D4080143C40F8B505460D48164600780F46A84201D8002404E00A48016AD02068430C187F20005DF9F7A7FABA1B0A20424351 +:40C680002046054B29467F30F9F73AFAF8BD0000CC1E00085C210008B5A00010044A106303488030816102494B2080390860704780103C40024610B50B460F20002180018A +:40C6C000F8F796FF10BD000013B50C46002269460F20F9F70FF869460978E0030843034980B208630249472008601CBD40113C4000103C407FB50E4604461D46002202A943 +:40C700000E20F8F7F7FF1048F10100780F4A4007400F03280BD0042809D0A00208436946097A084380B21063A009906307E0E80301436846007A014388B21063946304490C +:40C74000462008607FBD0000F021000840113C4000103C40017E012901D9012101764279C9B253000B430179CA001A4310210A4303498A6002880A604088486070470000DA +:40C7800040103C4006490978814201D8002004E00449D022096A50430818603043837047CC1E00085C2100080349884200D908460249486270470000FF0F000040113C4090 +:40C7C0000148806B80B27047C0103C402521C001C902401807494118086A1070000A5070486A9070000AD070886AC0B21071000A5071704700103C4070B50E4D14462A78D6 +:40C800005207520F012A09D0022A07D0032A01D0042A02D1224600F00FF870BD02460B46E8880021F8F7CCFE012CF6D1FEF774FA70BD0000F0210008F8B594461B4F8207B2 +:40C8400005D01A4F0023103F8E08B60015E08C08002303E09D007E5946515B1CA342F9D3A3000CE0DA191469C454240AC5186C70240A220AAC70EA701B1D9E42F2D88A07B9 +:40C880000DD00A4A103A9A18146900228907890F03E09D184455240A521C9142F9D86046012801D1FEF738FAF8BD000050F13D4010B5114909784907490F01290FD002295C +:40C8C0000DD0032901D0042908D10C49496A0170090A4170090A8170090AC17010BD084A11680170090A417051688170090AC170FEF712FA10BD0000F021000800F13D40C3 +:40C9000080143C400148806B80B27047C0103C4010B50A49F1240A681421414393681331595C24018B001B19102906D251682C225043085A02495918086010BDD401000873 +:40C9400000103C400121814010B589B200227C2000F082FD10BD0000FEB5FF210120FDF7F1FF3F210220FDF7EDFF1F210420FDF7E9FFFF210820FDF7E5FF3020FEF704F873 +:40C980007D48802101607D4C20784007400F032801D0042803D10BF03BFD0BF01FFC7748774E00784007400F022806D0032804D0042802D0012807D00BE00321316003281A +:40C9C00005D0042803D004E00020306001E00BF02FFC002211460320F8F78CFE69486A49028D4A61428D8A61828DCA610546624F00242035803709E03C636248818E62480A +:40CA000001632046FEF7B4FB641CE4B22878A042F2D85D480621C03881635A4C5A48218F816320460C30029000F0B0F9062268460299F7F75EFD69464879C02108436946D0 +:40CA40004871684600F0DAF900F0B0F8FFF702FB4A4800784007400F032829D0042827D0E08FB8634748444940304088C0314860E08D0121C903084343490862434901205A +:40CA8000086141498031C8683F2280B212029043072212021043C8603F20FDF781FF374C20784007400F022804D0012802D008E04820D6E7FEF748F9354907208861FEF72D +:40CAC0002BF9E020FEF794F8E820FEF791F8F020FEF78EF80020FBF7D3FA2C490020486110228A618915F96227494031C86022485B21016020784007400F032801D00428A7 +:40CB000001D10BF095FB20784007400F022806D0032804D0042802D001280AD00BE01D4830601D490869012280B252031043086101E01A4830601448C038416B0122114303 +:40CB400089B24163816B114389B2816314494015086014482978006805F0FEF906F00CFB00231846FFF7D0F85B1CDBB2042BF8D30D4900204870FEBD00103C40F021000844 +:40CB8000001F3C40AC1E0008C0113C40001A3C4080143C4003200000001E3C40E023000040503D40D00100089C21000804480021C1638163024974204039086070470000BE +:40CBC00040103C4070B51E4614460D4600F0A6FC0C49411808680122D20280B2012E09D0904300090001FF22284301329043002C04D005E01043044A1040F2E710221043AF +:40CC0000086070BD00103C40FFF90000F3B5254A84B0926900924A780B78120213430393CA788B78120213434A790979FF20120211438C461C499E46CA6B92B20292896B27 +:40CC4000742289B20191184940390A60174900220F7F24E00121144B9140009C403BE3181C6889B2A5B21C681B68A4B2039E9BB26E407546654064462E435C4026430CD129 +:40CC8000029B194209D00199D140CB070499DB0F8B4202D1104606B0F0BD521CD2B29742D8D8F8E7F021000840103C40CC1E000830B50A49FF20C96B094A8CB200210125B2 +:40CCC000137F05E02A468A40224204D0491CC9B28B42F7D830BD084630BD000040103C40CC1E000810B50446E020FDF781FF20782246401CC3B20021E020F8F711FC10BDAB +:40CD000042790021012A02D901214171090342790A430179042914D049001143827B032A01D8D2001143427B52010A43817909021143012252031143054A91610088D0615C +:40CD4000704711460122920211430222E5E7000000103C4000B50120FDF716FE01494120086000BD00103C4000B50120FDF718FE01494020086000BD00103C40024A1063EA +:40CD800001488030C160704780103C404178027809020A4306490A60C2788378120213434B604279007912021043886070470000C0113C404278130202781A4301290CD0D5 +:40CDC0000C498A62C278837812021343CB6242790079120210430863704707490A63C2788378120213434B6342790079120210438863704740103C4000123C404178027895 +:40CE000009020A4306498A61C278837812021343CB61427900791202104308627047000040103C404178027809020A4306494A60C2788378120213438B60427900791202B7 +:40CE40001043C86070470000001F3C40F0B50021FF2501350E4E0F4C15E0F1238A001B01D21893191A6892B2D7070AD0520852001A60884201D12A4300E0AA4301273A43AA +:40CE80001A60491CC9B2E27A8A42E6D8F0BD000000103C407C21000810B500222021302000F0DAFA05494320086001F009FDC007FBD10220FDF768FD10BD000000103C40A1 +:40CEC00030B591B0054640216846FDF7A4FF0A4C0849A1630220FDF763FD6A782021302000F0BAFA4220206001F0EAFCC007FBD011B030BDFFFF000000103C40017942792B +:40CF0000490011438279D2000A43FF2101310A4303490A6302888A624088C8627047000000103C4010B50446E820FDF761FE20782246401CC3B20021E820F8F7F1FA10BD2C +:40CF40004178027809020A430749CA63C17882780902054B0A4340331A60417900790902084358607047000000123C40024A1063014880304160704780103C40094810B529 +:40CF800081420DD8C8000521F5F7C2FD064989680818064980B2486003497220C039086010BD0000409C0000C0103C40001A3C4010B5074948200860064C206B4006FCD405 +:40CFC000002211461020F8F795FB606B80B210BD00103C4040113C400349732008600349042048637047000000103C4000113C4010B500F093FA0121490200F04BF910BD04 +:40D0000010B500F08BFA0121890200F043F910BDF0B515460F4604461E46FF2A04D000222946184600F0D6F86078237800020343E078A17800020143607922790002024336 +:40D040000C207043C419084827183B60241D23181960241D20180260FF2D04D001222946304600F0B7F8F0BD00103C40012808D8044A916901235B0299434002084380B2AD +:40D080009061704700103C40084A106348780B78000203439360C8788B7800020343D36048790979000201431161704780103C40F8B51C4615460E46074600F041FAA9009E +:40D0C000044A2143801801600349B0004018C455F8BD000000103C40D92100080149C86070470000C0103C40044A916B8905890D8002084380B290637047000080103C403D +:40D1000010B50E490B68142141439A681331515CF122890012018918094A89180A6892B2D40709D0520852000A605A682C235843105A01221043086010BD0000D401000852 +:40D1400000103C4038B5174B1B78834201D8002304E0154BD0241B6A60431B182024012906D0022904D0002A05D0002903D005E0188B204301E0188BA0431883187E8006A6 +:40D180000ED58320C05C00280AD198786946FEF7B9FC68460088002802D01846FEF766FA38BD0000CC1E00085C21000810B50C4600F0B4F90649401801688AB240218A43E4 +:40D1C000A10111430122D2029143016010BD000000103C40F12380001B01C018054BC3181868002A80B201D0084300E0884318607047000000103C4070470000F0B5174BE5 +:40D200008C07C318002C03D000209508AD0014E09408002003E01D6886008D51401CA042F9D3A0000BE01C680C54240A0E187470240AB470240AF470001D8542F3D89407BC +:40D240000AD01C6800239207920F03E0C5184C55240A5B1C9A42F9D8F0BD000000103C40134610B50A4A12785207520F012A09D0022A07D0032A01D0042A02D11A46FFF7F5 +:40D28000BDFF10BD0A460021F8F72CF910BD0000F0210008034A8018026892B20A4302607047000000103C40F0B5264BC518880703D000239708BF001DE09408002003E083 +:40D2C0008300CE58EE50401CA042F9D3A30014E0C818401C044626783046667836023043A678E4783604304324062043CC5C00022043E8501B1D9F42EAD8900721D092070E +:40D300000020920F012A04D0022A04D0032A17D107E0C85C14E0C81841780278080210430EE0C81801460A7810464A78120210438A78C97812041043090608430002000A81 +:40D34000E850F0BD00103C40F0B5424C00198C0704D000249D08AD00AC461DE09D08002403E0A6008F598751641CAC42F9D3AC0014E00D196D1C2E4637783D4677783F02B3 +:40D380003D43B778F6783F043D43360635430E5D2D0235430551241DA445EAD89B079B0F551C002B22D0012B31D0022B40D0032B1BD112780B5D1206134309198A784978E2 +:40D3C000120409020A43134303512B78EA7819466B7812061B021943AB781B04194311430902090A0019401C0160F0BD2B462D78127829465D782D0229439D78DB782D0492 +:40D4000029431B061943090211430151F0BD1678D578334656782D06360233439678095D360433432B431B020B430351D178D9E755780B5D2D062B431578091949782D04D1 +:40D4400009020D432B430351D178927809021143C8E7000000103C4070B5094BC5182868002384B2080003D104E040085B1C9BB2C607FAD08C439A40224390B2286070BDFB +:40D4800000103C40134610B50A4A12785207520F012A09D0022A07D0032A01D0042A02D11A46FFF701FF10BD0A460021F8F7A0F810BD0000F021000838B514460C4A1278FC +:40D4C0005207520F012A0BD0022A09D0032A01D0042A04D11B1F9BB22246FFF735FF38BD00930A4623460021F8F79CF838BD0000F0210008034A80008018405C8007800F43 +:40D5000070470000D921000800B500F00DF802494018006880B200BD00103C40014900014018704708420100014900014018704704420100A121000149024018704700009F +:40D54000034A928A424350180249800040187047F021000800410100054B02469B8AFF208B4203D9880003494018805C70470000F0210008C521000800B5FFF7DBFF024905 +:40D580004018006880B200BD00103C40F0B5304902460B680020002B14D10A6052070D26520F0024B601012A0DD0092503276D02FF020423022A1BD0032A2FD0042A2DD090 +:40D5C00012200C60F0BD112292018A80CA80032252028A600122D202CA6040220A8205224A828A82CC610C624C628E618C62F0BD8D80CD8001225203CF608A6012110A82E8 +:40D600004B828B82D2008E61CA61832252010A62432292014A628922520116E08D80CD800522D202CF608A60FF2201320A824B8229228B82D2028A61064ACA61054AC0323A +:40D640000A62054A4A62044AC0328A62F0BD0000F0210008C0480100404A010010B503460C460846FFF788FF02462046FFF74CFF012199400A4001400A4301D0002010BD12 +:40D68000012010BD0A4600B501461046FFF764FF00BD000010B50F4801680F480818846AFF2102310C4202D0F8F750F80DE0406B400F022801D1A00607D5FAF72BF9074867 +:40D6C0000069012180B201F071FA20460AF0E0FA10BD00006801000840F03D4000103C40F8B50446002000900E461546A178684609F07EFD002801D00720F8BD2B46324611 +:40D700002046009900F0A8FEF8BD38B50546002000900C46A978684609F06AFD002804D1009928464C7000F0F2FE38BDF8B5044600206A46107005460846FBF721FB0600AD +:40D7400004D0012806D0162E3AD10DE001236A46002102E001236A4619462046FCF7DBFB0546012804D02BE001236A461621F4E78320005D012811D1CD20005DC0070DD02F +:40D7800068460078C1090DD1C00701D0232200E02A2231462046FFF7A3FF11E068460078C0090DD068460078C10720464030002901D0232100E02A2181762046FBF75CFB8D +:40D7C0002846F8BD10B582790A4201D0FAF774FA10BD10B5044680780021FFF7CFFA01212046FDF761F810BD8030C368002B0AD00B60817A11700169C160C17A81720021D3 +:40D80000016108467047014870470000FFFF00008030C368002B04D00369002B04D004487047C160827201E00161C27200207047FFFF000000218030C160016170470000CF +:40D840008030C068002801D00020704700487047FFFF000070B505468035E8680024002806D0FBF78DFA002801D0012800D101242869002806D0FBF783FA002801D00128BB +:40D8800000D10124204670BD70B50446C0790E461546C1090AD04006400EE07101F0B6FC067021894180856006F0F1FA70BD70B50446C0790D46810601D43A2D13D13A2D7F +:40D8C00002D0DF210840E07101F0A0FC0570218941805E21095B818060342188C1806188018106F0CBF970BD38B54621095C04468034002910D1A16A00290DD18178684622 +:40D9000009F088FC002807D100980021A062C181A06A4185A06A4180A06A38BD01480078704700003C22000810B50446FCF798FA01280AD10648A178026AD020484384305B +:40D94000105CF9F7C5FF012801D000F0F3FC10BD5C21000870B50C460546F9F759FC012838D02879032803D0042801D0072830D1E079A67900020643A8783146FDF714FCFA +:40D9800001282DD0284660304683A17809020182627811430182217909024182E27811434182617981823246611C284600F09DFB02212846FAF7C2FD2846C030417B822282 +:40D9C00011434173287E0221C207D20FA878FFF7B9FB70BD01222421284600F04AFD70BD28215A2041552846FBF746FA70BD704770B50C460546FAF7E9FC00284FD120217D +:40DA00002846FAF759F9F4F789FF284661784030C176E17809028183A278114381836179C38B0A022179114320228B4203D0EB791343EB71C183E1792E460B02A179603611 +:40DA4000194333888B4203D0EB791343EB713180617A0B02217A1943738843828B4203D0EB791343EB717180C18B70888000F5F74FF8401E318880B2814200D93080012134 +:40DA80002846FAF75EFDC035687B822108436873E07AA17A000201437183F4F729FF70BD70470000F8B50D4606460027F9F7B0FB012845D0264CA07AC00707D04420805DAE +:40DAC000002806D0102803D01F212CE01A212AE001273046FBF75AFB002823D0344680340822691CE06AF6F704FDE06A697A20300172A97A4172E06A2946183008220B314A +:40DB0000F6F7F7FC29463046042213313830F6F7F0FC39463046FBF72DF8002810D1002F0FD012E007210322304600F0A2FC628A08213046FAF7A0F811213046FAF704FD61 +:40DB4000F8BD06213046FAF710FD01202070F8BDAC1E0008704770B50446403000790D46022813D126468036F06A08222030691CF6F7BFFC29462046042209313C30F6F7FC +:40DB8000B8FC2046FAF7A2FF0120307070BD10B5FBF732F810BD70B50E4605462021FAF78BF82C468034A06A002804D0A97809F0B1FB0020A06231462846FFF778FE00211E +:40DBC0002846FAF7BEFC2846FAF73BFD002070BD38B504460020009020790D46032803D0042801D007281CD12046F9F711FB012818D0A178684609F0FBFA002811D10C48B8 +:40DC00006A78807A00991040F5221040A075E07E08221043E076204600F05CFB2046FAF710FD38BD08222421204600F022FC38BDAC1E00087047000070B50D460446022126 +:40DC4000FAF73AF82046F9F7E3FA012805D009222421204600F00DFC70BD0C486978807A6A1C0840F5210840A075E07E08210843E076E079EF210840E07100212046FFF73D +:40DC800003FE2046FAF7DDFC70BD0000AC1E000870470000F3B581B004460298FBF770F805462046FCF7D1F800287DD0192D04D32046029900F0ABF976E0264640363079F1 +:40DCC000002700900300FCF70FFE0E1C1C1C08081C1C1C0808080808081C0298354A01780020135C8B4201D1012702E0401C0728F7D38320005D002801D1072901D0002F0F +:40DD000003D00098022816D02EE0A078FFF770F9002301223D212046FAF700FE3D20B0762046FFF756FDA178029809F0C9FA2046FBF7FEF8FEBDFFF7F1FD002814D1042D1E +:40DD400012D00D2D10D0112D0ED0152D0CD0072D0AD0092D08D0202217480299F6F7C9FB012000F003FC1FE020460299FFF7DEFC012819D0A8000F4D029908352A582046AE +:40DD80009047A178029809F09BFAFFF7C7FD0228D0D109480849007880002A5820469047002000F0E3FBFEBDA178029809F088FAFEBD0000D84600101C22000870B50D46EF +:40DDC00011490978814201D8002404E00F49D022096A50430C18002C15D0204600218030C1718079032802D12046FCF7F3FB2046FFF79AFD192D04D20549A80009582046AC +:40DE00008847FCF73DFA70BDCC1E00085C2100084447001010B50446403000790E2805D12046FAF72FFF01208034207010BD10B50446F9F7EDF9012802D1002040342070EA +:40DE400010BD10B5044640300179062905D00F2902D12046FAF73BFF10BD2046FAF748FE01208034207010BD70B50446054640342079072805D12846FBF7DEFF2846FAF738 +:40DE800031FE20790F2801D10020607070BD000038B5044600220E4800920D46807AF5210840C0060FD52046FBF7E0FF01280AD0A178684609F09CF9002803D12046009954 +:40DEC00000F0B4FA38BD2946204600F0A0F838BDAC1E000810B504461021F9F7EDFE2046FAF7E6FB10BD000070B5054610480C46807A400704D409782846FFF706FC70BD04 +:40DF00006078032803D1A1782846FAF75DFD6078122803D110212846F9F7CEFE60781628EDD10448A1780068C2682846904770BDAC1E00080802000810B5FAF7D1FE10BD84 +:40DF400010B54978FAF740FD10BD10B5FAF7C8FE10BD10B54421095C032901D1FAF7E8FD10BD012140304170704710B54421095C042904D00C2901D1FAF7C8FE10BDFAF7A1 +:40DF8000F5FD10BD10B50446F9F742F9014620464030012900D1417000790D2802D12046FAF7AFFE10BD70B502790D460446052A03D0062A01D0082A01D1FAF717FD687824 +:40DFC0005A21085509212046FAF7CFFAFCF7D4FE80212046FEF7D8F8FCF7EAFEA078FFF70FF82046FCF746FC70BD10B50446FF21F9F762FE16215A2001552046FAF798FF42 +:40E00000A078FEF7F5FF2046FCF734FC10BD70B50C460546FBF724FF002802D02078E87570BD21782846FFF770FB70BD70B5054648780C46032802D12846FAF7E3FC60786B +:40E04000122806D110212846F9F736FE2846FAF72FFB0748214600684268284690476078162804D10348006881682846884770BDFC01000808020008704770B50D460446B5 +:40E080000421F9F719FE6878A076E8780002E081A9780843E081687900022082297908432082E07E04210843E076800704D4204600F03AFA072815D0E079410612D5BF2112 +:40E0C0000840E07101F0A2F80021017021894180E1898180A17E4170218AC18005F004FFFCF7CEF870BD7047704770B50446C07815460A4600280AD00020E070C1B2A0783D +:40E10000FDF78EF8A0782946FEF7C8FA70BD0120F3E70000F8B5064601200C46087005221949601CF6F7E5F9B078FCF783FE0546B0786946FDF7E6FC684600880A214843CB +:40E14000114942191039887B002802D0401E4300C018101835460C30603568834A7C0B7C12021A432A82CA7C8B7C12021A436A82097DA982A071000AE07108223146204694 +:40E18000FCF7BCFAF8BD00006C2100087CB505468030866A0C46A878FCF74CFE014628465C30009001AB3246284600F031FAA878FCF740FE69468988FCF710FE69462846F4 +:40E1C0008988603041830021217029464031CA7E62700A7FA2708A8B120AE2708A7F2271C98B0C22090A61710178A1710188090AE1718178217240886946000A6072888885 +:40E20000A072000AE07229462046FCF777FA7CBD70B5054603200C4608702E4680360822601CF16AF6F765F9F06A08222030017A6172407AA072F16A204618310B30F6F70B +:40E2400058F929462046042238311330F6F751F9172229462046FCF751FA002070BD70B50546042008700C46AC20415908222031601CF6F73EF92946204604223C31093056 +:40E28000F6F737F90D2229462046FCF737FA002070BD000070B505460C46C07910210843E8710820207002460021601CF6F72AF90748F522817A11406170C07A0922C007A0 +:40E2C000C00FA07029462046FCF718FA002070BDAC1E000870B5054609200C46087008220021601CF6F70EF9A87D607005480922C07A2946C007C00FA0702046FCF7FEF91C +:40E30000002070BDAC1E00080B4610B501460A20187001221846FCF7F1F9002010BD0B4610B501460B20187001221846FCF7E6F9002010BDFEB50020694608720546334F4B +:40E3400060E03348016AD02068430E183046FFF777FA002854D18720805D002850D101AA69463046FFF740FA002849D100980478002C09D0012C16D00C2C23D0092C21D000 +:40E3800069460A79314629E0012302AA00213046FBF7C1FD012804D030460099FFF7F6FE2EE00C221FE0012302AA19463046FBF7B2FD012804D030460099FFF7ABFE1FE073 +:40E3C000082210E0012302AA21463046FBF75CFD00286846027906D131460098FCF78EF9022C05D00CE031460098FAF7E5F907E0B0780121FEF7DAFE09213046FAF7B5F851 +:40E400006D1CEDB23878A8429BD8FEBDCC1E00085C21000810B50B46122119708178D977014601221846FCF769F910BD10B50B46132119708178D9770649896AC90603D16F +:40E44000018B402211430183014601221846FCF755F910BD00113C4010B50C461121217062700146A37003222046FCF747F9002010BD38B50446002000900D46A1786846C1 +:40E4800008F0B6FE002801D0072038BD00980D210170457002222146FCF730F9002038BD0B4610B501460520187001221846FCF725F9002010BD0B4610B50146062018705F +:40E4C00001221846FCF71AF9002010BD38B5044600200090A178684608F08AFE002801D01F2038BD009D022028705A20005D6870A078E877208B1021084320832046FFF7AA +:40E5000068F9022221462846FCF7F8F838BD10B50B46072119708178D977014602221846FCF7ECF8002010BDF8B50546002000900D4EA9783488684608F05AFE002801D035 +:40E540000720F8BD00980C210170717941708470210AC170F2880271110A417106222946FCF7CCF80020F8BDAC1E0008094A1178002906D0012909D0022908D1002807D00E +:40E5800001E0012804D00021002900D0107070470121F9E73C22000800B500F016F800BD704770B50546FFF79FF9044602884188A87804F085FCA084E0886082A088208235 +:40E5C0006088E0812088A08170BD4018400870470246603000885E21895A401C4843C10800D101214008528A00E0401A8242FCD9704710B56021095A80780A01511A10311A +:40E600008CB2FCF717FC2146FCF756FA10BD0000FFB581B0054604464035288A69460A9F08801E46A078FDF76DFA694609880A20491C41431048807B002802D0401E420087 +:40E640008018081881B20298FCF736FA3080A07804F024FC06468320005D012804D1E98BA078042204F0C2F9A078314604F05CFD388005B0F0BD00005C210008F8B51546E8 +:40E680000E46074600F00EFA0446012804D02A463146384600F0B6F92046F8BD014600B50020890701D500F00BF900BD014600B50020890701D500F003F900BDF0B593B015 +:40E6C0000020FF210391059007901290012612A92F2005F008FD002804D000F097FD0446002600E0129CFEF76BF881040507890E40060891C00F891F2D0F06900491202949 +:40E7000031D2062D2FD800F0DBF8C0072BD03E2020700220A0700120E07003210420624F062D2DD0022D2ED0042D2ED025715E48417949084900417106986071A01D06216C +:40E74000FCF769FBFCF79CFC070006D0574A611D1268A01D126A904703900498012DC0B2029020D044E0002E02D0204605F0C2FC00F04CFD402102A8FCF74DFB13B0F0BDB4 +:40E7800002202071D3E72171D1E720717879C007CDD0002E02D0204605F0ACFC002600F035FD0446C3E70398FF280BD040482C220068416803985043095A4120884301D16A +:40E7C000012007903B48407E012804D10799002901D1012F02D0002F06D007E00120059020730D270B2006E00128F7D00020029020730D270220A0700898062824D0049812 +:40E800002746C1B20D373846FCF705FB0598012817D12948006B03A9C007C00FFCF730FBA07C8009012806D13946062203A8F5F751FE002805D10020203FF8770290022087 +:40E84000A07002980D30C7B2FEF75CF8694688806A4601A90620F6F74DFF69460878E0557F1E16486770407801280BD12A46A01D069900F017F9012811D02A46A01D0699EA +:40E8800000F0C0F8002E04D02046059905F018FC74E7054801224179114341716EE7204605F028FC6AE700005C210008EC010008D4010008A021000800103C407D2200089E +:40E8C0000248806B0004000E7047000000103C4010B50446000701D5FFF7F0FEE00601D5FFF7ECFE0248006881692046884710BDEC01000810B502460178FFF7E1FF814270 +:40E9000001D10C2010BD0D485378002443705470002908D000F06EF81046FEF7D1FA0420F9F74AF907E01046FEF7B6FA0520F9F743F903480476002010BD00007D22000801 +:40E940007C210008F8B50446FFF7BAFF002801D00C20F8BD6079164DFD2702260128E8781DD03840E87013480068416820468847A0790128A87814D03840A8702046FEF7D2 +:40E98000BDFA0B48218862882030914203D1017E0122114301762179012904D006E03043E0E73043E9E7017E314301760020F8BD5C210008EC01000838B5002001460090BE +:40E9C000684608F0FFFB002801D01F2038BD009C002161712171A1711021218020466180FEF78CFA204608F077FC00F003F8002038BD000002480021017007218170704706 +:40EA00007D220008F7B50C2082B0254D0F46002400902878E040C0072DD02148E10040380E18062230460299F5F754FD00280AD1B079B84207D1F079002801D0062802D167 +:40EA4000049804280BD02878E040C00713D0641CE4B2082CDDD300980C2803D00BE00420F07119E0A878401CC0B2A870082801D10020A870C4B20A48E10040380E180622D8 +:40EA800030460299F5F735FDB7710498F07128780121A14008432870002005B0F0BD00007D220008F7B5164E00243546403529780120A040014217D0E0008719B979019818 +:40EAC000814211D1062238460099F5F703FD00280AD1F879022810D004280ED001280CD0002807D0062805D0641CE4B2082CDED30020FEBD02980428FAD00120FEBD000075 +:40EB00003D22000801484078704700007D22000870B5064614460D46500702D5A8B2FAF72DFE200702D5B0B2FAF7E8FBA00702D5280CFFF7CDFEE00702D0300CF9F72AF99E +:40EB400070BD70B5044660C8F8F7C8FA2089C01F0300FBF7C9FE0C071A121E212412122712171312F3F7F4FE032801D1F7F76EF9294630466289FFF7CBFF70BD284604F054 +:40EB800063FD70BDFAF750FB70BD2846F8F74CFC70BDF8F74DFF70BDFAF76CFB70BDFAF793FB70BDE8B2FAF7ADFD70BDF3B5002189B0069105910C460391009101910291C7 +:40EBC000F74989688EB230400490B00618D5FCF74BF9F44908800120F6F7B2FEF24900200870F3F77DFE012802D10020F6F72CFE2020FBF7A1FE0420F7F75CF901200590EA +:40EC0000EA487107009024D5E5484030006987B20498400718D5F80613D5E5480021026A009800780BE0884201D8002502E0D0234B43D5182B79022B29D0491CC9B288426B +:40EC4000F1D8B80880000390394600220420FBF759FE300775D5D748406B80B20190D0488030806A87B2049800076BD5019804218843384367D0D048C06BC006C00E02906A +:40EC8000009801780298814211D8002515E02846FDF7E4F82846FCF777FD2846FDF74FFA40212846FDF770FAFDF770F9C9E7C048D022016A029850430D18002F05D02846C2 +:40ECC0004030C18A3C433943C18201988207B84801463C31403006910090002A3DDA2879002803D1C420405D002833D102212846FCF71AFE2846FDF7B7F907A90298FCF738 +:40ED000001FFA878012103F0A1F9002817D1FDF755F8002813D14620405D012807D1C0217A204959405BC98B401E884207D08320405D002808D16846808B002804D0012081 +:40ED400006E0ABE099E095E00698FCF76BFE0020009908700120F6F703FEF80657D52879002803D1C420405D00284DD104212846FCF7DAFDF3F7ECFD03280CD1C0204059BB +:40ED8000807A002810D18320405D00280CD101212846FCF785FFC0204059807A002803D18320405D00280DD000980078012809D0002810D17E480021C06B807803F046F9F9 +:40EDC000002808D02846FDF74FF90698FCF72AFE0099002008707648C06B002809D001216A465172017B1172FDF7F4F802A8F6F739FD28460A3009F015FA2846C0300179CC +:40EE0000002901D1012101710220F6F7A9FDF80705D07805400F022801D1F6F7A1FD28464030018B06912946C031CA88C08A824201D00443C880087B002805D1A035287F49 +:40EE4000012801D010208443600609D500984078002802D04020844302E0009801214170394600220820FBF74DFD544901980840504948633F2000028443019840070DD5EE +:40EE8000F6F71EFBF6F78CFF4A4904204863FCF7BFF9012802D10220F6F762FDB00719D53F48806B85B20498800709D50399280408430390FFF704FDC00701D00120059023 +:40EEC00081210398490488430390294600220220FBF718FDF0073AD03148006A85B20498C0072CD02804044329208001054206D033492846096849698847012864D005203E +:40EF000040068443A8071AD50220F6F729FD284F2037B87AC00712D0787B00280FD0387BF97A88420BD2274800688168387B14225043801D0818FDF775FF00207873812074 +:40EF400040048443294600220120FBF7DBFCF00605D50120F6F7F4FC1020FBF7EDFC700602D54020FBF7E8FC039806992043084301D00120059007206946088103980090B6 +:40EF80000194049848810598002807D069460EC90A98002850D0002008F04CFA0BB0F0BD00103C40E6010008CC010008CC1E00085C21000800113C4000503D40FBFF00006A +:40EFC000EC010008D4010008FBF784FB074600218030C170384640300090807BFF2808D138464830FBF7BCFF384600214730FBF7D5FF00983946C0794831FBF767F8FF2846 +:40F0000005D0292080058443FDF7AEFE7AE73846FCF77AFF3846FCF7E3FB3846FCF71EFF3846FDF78CF840213846FDF7ADF8FCF7ADFFFDF78FFE65E7002008F040FAADE7DE +:40F04000F0B587B0054605A81E461746019100900C9C04AB06AA02A903A800F0CFF92846FCF706FA21463046FCF78AF96846017A0398FBF79FFD05A904A8FBF74DFD68467A +:40F08000027E21463846FBF71BFD07B0F0BD000070B50948C4782046F8F758FE06462046FFF7FCFA05462046F9F7C8F9014630462843084370BD00005C21000870B5094885 +:40F0C00084782046F8F74AFE06462046FFF7EEFA05462046F9F7CEF9014630462843084370BD00005C210008F8B5069E1F463478042C17D3231FDDB23B460095FFF7A0FF62 +:40F100003819001FFCF7EEF90520FDF74FFA0446012229460798FDF76FFB3570E00701D00020F8BD1F20F8BDF8B51C46009301271346069E079D3A46FFF782FF2846FCF761 +:40F14000D1F90520FDF732FA0546012221463046FDF752FB2846F8BDF8B51D4616460F460024FCF785F931463846FCF709F90320FDF71CFA012231462846FDF73DFB2046CA +:40F18000F8BDF8B5069D089E2C780094FFF758FF0120FDF70BFA07463046FDF789FB0023224631460798FCF773F8241D2C70780701D41F20F8BD0020F8BDF8B51C4600932F +:40F1C00001271346079E069D3A46FFF739FF0120FDF7ECF90746002221462846FDF70CFB3046FDF765FB3846F8BD10B500F02CF90446F9F7B7F80128F8D1204610BD10B5B5 +:40F2000000F022F90002000A10BD0000004870478422000808B500F017F96B4600210090585CC006C00E421F0B2A04D9491CC9B20429F5D3EFE708BD08B56A4600210B203A +:40F24000F6F758FA6846007808BD0000FEB5064601200290042017460D46444C0090FBF703FE28802146FBF727FC3080F8070BD0FBF73EFE019028880199FBF721FEA04221 +:40F2800002D2044601983080B8070BD5FBF742FE019028880199FBF713FEA04202D204460198308078070AD5FBF728FE074628883946FBF705FEA04201D204463780F6F765 +:40F2C0000BF900280AD0FBF709FF074628883946FBF784FDA04201D2044637802448807B00283BD0FBF710FE074628883946FBF7E7FD0546A04231D2FCF7DEFB1D4909789A +:40F30000814201D8002004E01949D022096A504308180190F7F77CFF002817D101983D21C0300068C089F3F7F3FB401DC0B200900A280BD90A21F3F7EBFB0091854204D39A +:40F34000391A281A8FB285B200E0002537802C460198F7F75DFF002800D102900098FDF7BDFE0298FDF7C0FE2046FEBDFFFF00005C210008CC1E000810B50E4C0C492346DE +:40F380000833A160002142189278002A00D05A54491CC9B20429F6D3FF21A0689A314843A06000F051F8F8F7DDFF0128F9D110BD040302015C21000870B5059C049D207046 +:40F3C000060A6670060CA670000EE0704806D101400E0843207104221946601DF5F789F82046042229460930F5F783F870BD00000149086070470000E8010008F8B5079C76 +:40F400000E46E178069D09020160A77839430902016067783943090201602778394301602079611D4006400E30702079C009107004221846F5F75DF821460422093128469F +:40F44000F5F757F8F8BD000010B5FBF70DFD094A916848400849096848408108C3084409414063405940C30F59404008C9070843906010BD5C210008E8010008F3B5074669 +:40F4800081B00E4800240E4E0E4D10E031682C234A6821465943535CDB0706D01B315118029801F02BFB002805D0641CE4B2E97AA142EBD8FEBD3C70FEBD0000FFFF000054 +:40F4C000D40100087C210008FFB585B00C4600200090A004850E0E99684601810026FFF711FB6106C90F27073F0F0191012805D13A460798FFF7C2F8012849D069462F200E +:40F5000004F0F1FD002843D1009C3E2020700599022001290CD0A070A81FC6B20120E0703B00FBF7E1F907080A0C120E121012000B20A070F2E7002008E0012006E00320D7 +:40F5400004E0042002E0022000E0FF20207101986071A01D06220799F4F7CBFF0598012818D0267320460D30AA1F0899F4F7C1FFED1DEDB203AA02A90620F6F7BBF86846D7 +:40F58000007B60556D1E65702046059904F098FD09B0F0BD01202073E4E700000249014808607047A8470010EC010008704700207047FF2070470120704710B5400606D580 +:40F5C000FF210020FAF736FA0220F8F7F5FA10BD7047704770470020704770477047002070470020704700207047002070470020704700000249014808607047EC4700104A +:40F60000EC01000870B512248AB00D46064600292FD000200290039004900590102202A92846F4F757FF002823D00821684607F040FB6946487940214006400E08436946FC +:40F64000487103226C46C91C02A8F4F752FF0322E11CF01CF4F74DFF06AA294602A8F7F755F90404240C04D1032206A93046F4F740FF20460AB070BDF0B50546FF2129704E +:40F680000022144C144B072011462468DB7A0FE02C2766684F43F65DF60707D014274F43A6681337F75D0126BE403243491CC9B28B42EDD8D143002207E0CC0702D02A7060 +:40F6C0000020F0BD4908521CD2B29342F9D90029F3D1F0BDD40100087C21000870B50546FF210D4A297014680C4A0A480021D37A0CE02C2266684A43B25AD60704D052077A +:40F7000002D52970002070BD491CC9B28B42F0D870BD0000FFFF0000D40100087C210008F8B50C460546FF206946087068798009012807D022782946684601F063FA68463D +:40F740000078F8BD2946684601F092FA68460178FF29F4D00A4E2C22306851434068091D411806222846F4F7C4FE30682C2241686846007850430A30085C801C2070DEE79C +:40F78000D40100083EB50446FF206946087213480068C007C00F19D001216846FBF7E0FB684640798009012813D02278694602A801F028FA6846017AFF2907D008482C2240 +:40F7C0000068514340680A31405C20706846007A3EBD694602A801F04BFAF7E7001F3C40D4010008F0B589B01646044600256A461570FF201075CC48072700680278CB483D +:40F800000790C07A82426FD2204606F0C7FB07006AD10C27F7F7E2F8FBF732FC002804D0C248203840784007F2D1A27A211D684601F0E8F9BE490746884220D1684606902A +:40F8400000208446FF206946087007990727CB7AB5490020096807910EE007992C2249684243895CC907C90F614503D106990027087012E0401CC0B28342EED80DE0002E61 +:40F880000BD1A9486A46006881681078142250431330085C6A46107501252846384303D105A8FFF7E9FE0746002FB1D16846017D9D48142300688268684600785843133044 +:40F8C0001154012E11D098482C230068002241686846007858430A52934800684168684600785843801C0AE01AE18F482C220068062341686846007850430A5A1A400A52B4 +:40F900000020019002900390049087482C230068A27A41686846007858430A300A54824800684168684600785843002A03D00A5A10231A430A527C482C22006841686846FF +:40F94000007850430B300818214610220B31F4F7D0FD75482C22006841686846007850431B300818214610221B31F4F7C2FD6E482C2200684168684600785043001D0818BA +:40F980000622211DF4F7B5FD6748142200688168684600785043081806220021F4F7B2FD6148142200688168684600785043801D081806220021F4F7A5FD5B481422006895 +:40F9C00081686846007850430C30081806220021F4F798FD012E33D0534C2C22206841686846007850431B300818102201A9F4F771FD0223002820686946406809780FD00B +:40FA00002C225143425A1A43425220686946426808782C214843801C115A012319430EE02C225143425A9A43425220686946426808782C214843801C115A4908490011527D +:40FA4000394C2C22206841686846007850430B300818102201A9F4F73DFD0028206822D06946097842682C204143505A04231843505221682C234A6869460978594380235A +:40FA8000184350526946226808782C21414353680B315918142392685843801D1018FFF7B1FD074608E04168684600782C2250430A5A84239A430A5220682C2142686846CC +:40FAC00000784843011D0A305118105CFDF79EF80823FF28206869464068097804D02C225143425A1A4303E02C225143425A9A43425220682C2241686846007801235043BD +:40FB00000A5A1A430A52684600210078FAF754FF38462843304303D120680178491C0170384609B0F0BD0000D40100087C210008FFFF000038B50A461B4909784907490FE8 +:40FB4000022903D0032901D004292AD11749897A490626D50146684601F054F80006000E1FD1134C2C222068082341686846007850430A5A1A430A5268460078FAF7D6FAB9 +:40FB800000280AD020682C22416868460078012350430A5A9B021A430A5268460078FDF7AFFA002038BD0000F0210008AC1E0008D4010008F1B584B000260396FAF78AFD7C +:40FBC0000446FBF75DFA002830D0049880057DD5FF2069460870002101A8FBF7C1F96946487A8009012824D0022836D001273A4601A9684601F006F805000AD0012047405E +:40FC00003A4601A9684600F0FDFFB6490546884225D0B5482C2200684168684600785043085CC04380071AD4AE4D1AE0012005B0F0BD01A96846FFF721FC050011D101201B +:40FC40000390A9482C22006841686846007850430A30095C4720015503E00027C7E747200755F8F78BF8002D57D1012823D0042821D00220F8F75EF801281CD19A4D2C2160 +:40FC800028684268684600784843011D0A305118105CFCF7BBFFFF283FD028682C22416868460078082350430A5A1A430A5268460078FDF725FA039800281CD08A4D1422CC +:40FCC0002868816868460078504300E032E00818062201A9F4F70DFC286814228168684600785043024613328B5C08187F492022096AFDF78DF9684600784E2108557A4952 +:40FD00002C22096850434968001D0918204606224830F4F7EEFB012675E0754880694007800F012803D100217248FDF743F8FDF71BF868E00498400665D5FF2668466E49B4 +:40FD40000670684F0868012280B2920310430860002101A8FBF704F9FBF792F925464035AE73012600284ED06846407A8009012828D0002201A9684600F044FF002806D0E0 +:40FD8000012201A9684600F03DFFB8420AD056492C2309684A68694609785943515CC943890701D5002812D05448807AC0072AD00020FDF71DF94E4880694007800F0128C3 +:40FDC0001AD01DE001A9684600F052FFEAE768460078A87344492C230968584303464A680A33D25CEA714968001D0918204606224830F4F77EFB06E000213E48FCF7DAFF16 +:40FE0000FCF7B2FF0026049800053CD5FF2568460570344E002101A8FBF7A2F8002201A9684600F0EFFE002806D0012201A9684600F0E8FEB04221D02B492C2309684A68B8 +:40FE4000694609785943515CC943890716D428488169006A89B2C0050CD44807800F012803D100212348FCF7A5FF0020FDF7C0F8FCF77AFF4034A5730020D8E6002804D043 +:40FE80004034A57301263046D1E6174D2C222868022341686846007850430A5A9A430A522868142281686846007850431330085C00221946FDF78EF96846214600784031F3 +:40FEC00088732A682C256843054653680A355B5DCB715168001D0918204606224830F4F708FBCFE7FFFF0000D4010008F021000800103C40F0010008001F3C407C210008E6 +:40FF0000F0B500278BB004463E46FAF7E3FB08907A4D60057ED500200690059009A9039004900191009007AB03AA05A90320FBF745F86946898B4906CA0F002816D16846B9 +:40FF4000407C03A98009012802A815D000F05AFE6B4988420AD029682C234A686946097A5943515CC943890700D465486946497E8909012904D011E0FFF780FA0127F5E7A3 +:40FF8000002873D128682C2241686846007A50430B30091805A800F0B1FD0126002865D10120F7F7C7FE01281BD169460A7A28682C214A434068131DC1180A32805CFCF725 +:40FFC00025FEFF2852D028682C2241686846007A082350430A5A1A430A526846007AFDF78FF83800474F1AD02868142281686846007A50430818062203A9F4F77AFA286863 +:020000041001E9 +:40000000142281686846007A5043024613328B5C081800E02AE02022396AFCF7F9FF002E24D028682C2241686846007A402350430A5A1A430A522868142281686846007ADD +:4000400050430C300818062205A9F4F752FA2868142281686846007A5043024613328B5C0C3008184022796AFCF7D2FFE00606D525490868012280B2D20310430860E004D9 +:400080002AD500206946087209A90191009007AB03AA05A90320FAF791FF00281CD16846808B03A94006C20F6846407C8009012802A804D000F0A6FD002803D00CE0FFF7D8 +:4000C000DDF9F9E728682C2241686846007A5043085CC04380070ED509208001044201D1200508D508984030817B0020F9F7A2FC0220F7F761FD0BB0F0BD0000D401000806 +:40010000FFFF0000F0210008001F3C4070B50C24F6F764FCFAF7B4FF002803D00E484078400717D1FAF786FD0C4D002128680A4C01702034E27A2C214A4340680021F4F70C +:40014000E1F9E27A14204243286800218068F4F7D9F90024204670BD5C210008D4010008F8B5144800784007400F022803D0032801D004281DD11048807A400619D500244D +:400180000E4F08250E4E11E038682C21426820464843115A0B4BA94311523A681940526811522046FCF7ACFF641CE4B2F07AA042EAD8F8BDF0210008AC1E0008D401000813 +:4001C0007C210008FFFB0000F0B504468BB0AD48002607903546600605D4A00603D4E00501D4A00528D5FFF711F809A90191009008AB03AA05A90020FAF7E0FE0790600624 +:4002000001D4A006EED5002069460872FF2000900798002810D1088C41060007000F01906846407CCA0F8009012803A902A804D000F0E8FC002804D000E1FFF71FF9012659 +:40024000F8E76846407E904F8009012810D1019801280DD138682C2241686846007A50430B30091805A800F049FC01250028E3D186488078F8F7FEF801281CD169460A7A9B +:4002800038682C214A434068131DC1180A32805CFCF7BCFC0090FF28CED038682C2241686846007A082350430A5A1A430A526846007AFCF725FF019801283DD1002D3BD01A +:4002C0003868002E05D081686846007A1422504305E041686846007A2C225043001D0818062203A9F4F7F6F80006000E01D1002E24D168463A68007A2C23434351680B3361 +:40030000C9181423926858430C301018FFF77AF909903868142281686846007A504302461332801D8B5C081859498022896AFCF76FFE099800287DD1002E3CD03868142241 +:4003400081686846007A50430818062203A9F4F7D0F83868142281686846007A5043024613328B5C08184A492022096AFCF750FE0098FF281FD0386842686846017A2C202E +:400380004143505A430702D5019B012B01D1002D03D001235B021843505238682C2241686846007A202350430A5A1A430A526846007AFCF7A5FE002D40D038682C22416892 +:4003C0006846007A402350430A5A1A430A523868142281686846007A50430C300818062205A9F4F786F83868142281686846007A5043024613320C308B5C08182449402294 +:40040000496AFCF705FE21482030807A400715D50098FF2812D038682C2142686846007A4843115A4B0703D501235B0219431152684600E002E0007AFCF762FE200606D531 +:4004400014490868012280B2D20310430860E00501D4A00510D5002069460872079800280AD1088C4006C20F487C03A98009012802A803D000F0C6FB0BB0F0BDFEF7FEFF46 +:40048000FAE70000FFFF0000D40100085C210008F0210008001F3C4010B5054A01781175411C034806220E30F4F723F8002010BDA0210008F8B515461E46024600206B46E5 +:4004C0001870684600F09EFB0406240E02D002242046F8BD0948002E006881686846007802D01422504302E014225043801D091806222846F3F7FDFFEAE70000D4010008CA +:400500000148C07A704700007C210008F8B50646002768463C4D0770286802240078002818D0304605F03EFD040013D10C24F6F755FAFAF7A5FD002803D0344840784007CD +:4005400008D13278711C684600F05CFB0406240E02D002242046F8BD28682C2241686846007850430F5268460078FCF7D1F9296808780028EED06A461278431E93422AD042 +:400580004B682C2148432C3819182C20424398182C22F3F7AEFF2968142288680978142351436A461278143941185A4380181A46F3F79FFF28682C224168007850432C38BF +:4005C00008180021F3F79EFF2868142281680078504314380DE048682C214A4380180A460021F3F78FFF286814228168684600785043081814220021F3F784FF28680178E0 +:40060000491E0170A6E70000D40100085C21000838B50A46174909784907490F022903D0032901D0042922D11349897A49061ED50146684600F0E6FA0006000E17D10F4B56 +:4006400069461868097842682C204143505A0824A043505219682C234A68694609785943074B1840505269460878FCF749FD002038BD0000F0210008AC1E0008D401000816 +:40068000FFFB0000F0B58BB00446FF206946087200200A90A00605D4600603D4200601D4A0057DD5FEF7B2FD08A909900191009007AB03AA05A90020FAF780FC01908E4E4F +:4006C000A00601D460066CD50198002869D10025694600950D72888B4006C20F487C03A98009012802A804D000F08CFA070009D013E0FEF7C3FE070001D001250DE0012020 +:400700000A900AE030682C2241686846007A5043085CC043800700D4784F6846407E800901281BD16846808B0007000F012815D130682C2241686846007A50430B300918D4 +:4007400005A800F0DBF9002804D00225384304D0012703E001210091F8E70027002F7AD167488078FDF7A2FF01281ED130682C2142686846007A4843011D0A305118105C95 +:40078000FCF744FAFF2866D030682C2241686846007A082350430A5A1A430A52684601E0A5E06EE0007AFCF7ABFC30682C2142686846007A4843115A4B0707D501235B0247 +:4007C000194311526846007AFCF79AFC00984D4F002824D030686946097A40682C225143425A40231A434252306869468268087A142148430C301018062205A9F3F779FEE7 +:40080000306869468268087A1421484301461331535C0C3010184022796AFCF7F9FB0A98002818D03068142281686846007A50430818062203A9F3F75CFE30681422816868 +:400840006846007A5043024613328B5C08182022396AFCF7DDFB002D13D06846818B0807000F012805D12848407E012801D1022D10D06846008C009003AA0020099BFEF72A +:4008800023FEA00533D50020694608720198002807D015E06846008C009005AB03AA0120EDE7888B4006C20F487C03A98009012802A81ED000F0A6F96846007AFF2816D0D0 +:4008C00030682C2142686846007A4843115ACB439B070CD50A4B20339B7A9B0707D501235B02194311526846007AFCF709FC0BB0F0BDFEF7C3FDDFE7D4010008FFFF000061 +:400900005C210008F0210008A021000870B5054605F05AFB04000DD107484078400709D1F6F75CF8FAF7ACFB01462878884201D0FAF7E4F9204670BD5C21000870B50646DA +:4009400005F048FB040010D1094D287EF5F73CF900280AD132887D20EA82C00042432846044B00211830F5F7CBF8204670BD0000A02100085D0B011038B505460020694681 +:400980000C240870FAF77CFB002803D01E484078400708D12A78691C684600F033F90406240E02D00224204638BDE8790223174A002810684168684600780ED02C2568433E +:4009C0000D5A9D430D521068142281686846007850431330085C002211E02C256843851C4D5DED07DFD00D5A1D430D521068142281686846007850431330085C01220221FA +:400A0000FCF7E8FBCFE700005C210008D4010008F8B50024264E054600291AD00C213046F4F760FC0004000C40D1E9792C2041433068001DF4F756FC0004000C36D1E9797D +:400A40001420414330680830F4F74CFC0004000C2CD118484022817A002711438172E879154D2C21E87230680770EA7A40684A433946F3F747FDEA7A1420424330680021EE +:400A80008068F3F73FFDFF2007E014223168624313328968641C8854E4B2E97AA142F4D8E1200649AF728000C8820020F8BD0000D4010008AC1E00087C210008A021000847 +:400AC00070B5FF2815D00B4A0446126853682C2254431A5BD5070CD055070AD5002903D0012189020A4301E003490A401A53FCF707FB70BDD4010008FFFB000070B5164C4A +:400B000088B00E46050023D0002E21D0002000900190029003906879400619D5102269463046F3F7D7FC0006000E11D00322E91C6846F3F7DEFC04AA31466846F5F7E6FE4F +:400B4000032204A92846F3F7C5FC002800D10024204608B070BD0000FFFF0000F8B51E491F4B0878401E08701C480021C28A7D20C000424319481830F4F7C2FF0024194DBE +:400B800023E0194B20461A682C26516870430E5CF60718D00B30091820461423584392680746861D9019FEF72DFD0006000E0AD10D48133700680D498068896AC35D8019B3 +:400BC0008022FCF725FA641CE4B2E87AA042D8D801206873F8BD00007A010008A02100085D0B01107C210008D4010008F021000810B5014606220248F3F77BFC10BD00007A +:400C0000F0010008F7B582B016490091FF20029900240870144E154F1FE030682C21254640684D43291D401806220399F3F752FC002810D13068294640680A31425C049982 +:400C40008A4208D1405DC00705D0029804700020009005B0F0BD641CE4B2F87AA042DCD80098F6E7FFFF0000D40100087C210008F3B581B0FF200199114F08700024114D77 +:400C8000114E17E02868062281681420604308180299F3F71FFC00280AD1286841682C206043085CC00703D001980027047004E0641CE4B2F07AA042E4D83846FEBD00000E +:400CC000FFFF0000D40100087C210008FEB50446002069460190087007460646014606225448F3F70FFC5348FCF72AF96079524D022801D003287DD1A279E11D6846FFF7AC +:400D000081FF0606360E23D14C482C230168684600784A684343D25C120619D5142289685043801D0818FCF77DF84448142200688168684600785043024613328B5C801D55 +:400D40000818892180224901FCF762F9012001902079012801D0042815D168460078FF2811D036492C22096842434B681B329A1889681423584308181146FEF743FC0606FB +:400D8000360E0BD000260198002842D0A87A01210843A87268460078287345E0274F2C2238684168684600785043085CC043800702D5E01DFCF7C4F83868142281686846E8 +:400DC0000078504309180622E01DF3F792FB386814228168684600785043024613328B5C081817492022096AFCF712F938684168684600E014E000782C2250430A5A012360 +:400E00005B021A430A5268460078FCF779F90127B9E76079022801D0032801D1801E6071A87A40084000A872002F01D00120A0713046FEBDF00100087C210008D401000867 +:400E4000F0210008F3B587B00C46FF206946087000250595019508728548039060792F46022801D0032800D10127207E022801D0032800D10125FAF703F9002810D02079FD +:400E80007C4E012819D06279002F01D0921ED2B2A11D6846FFF7B6FE0390002816D0BEE0002F02D06079801E6071002D02D06079801E6071002009B0F0BD002DEFD002A846 +:400EC000FEF70CFC039000287ED0A8E06A482C230168684600784A6843431B33D31889681422504308181946FEF78CFB0799039040310491002836D0002D66D05E482C22F0 +:400F000000684168684600785043085C40075CD506220021A01DF3F7F5FA04986179C1710121A01DFBF746FF534D1422286881686846007850431330085CFBF787FF2868B7 +:400F40002C22416868460078032350430A5A1B021A430A5268460078FCF7D2F8B07A04210843B07279E04448142200688168684600785043024613328B5C08183F4920223F +:400F8000096AFCF745F806220021A01DF3F7BAFA04986179C1710121A01DFBF70BFF0120019035482C220068FF23416868460078013350430A5A1A430A5268460078FCF794 +:400FC0009FF82D48006801E01AE028E0816868460078142250431330085CFBF737FF002D1DD025482C2100684268684600784843115A4B0713D501235B0219431152A9E7E7 +:401000001D482C220068012341686846007A50430A5A5B021A430A526846007A9CE7B07AFB210840B072002D17D00598002814D1207E801E20766846007AFF280DD00E4925 +:401040002C2209685043496801230A5A5B029A430A526846007AFCF753F8002F05D00198002802D16079801E6071039823E70000FFFF00007C210008D4010008F0210008CB +:40108000FEB5054640790027424E022801D0032845D16846FEF722FB07063F0E12D13E4C6846226800782C21414353680B315918142392685843801D1018FEF7A3FA0706E6 +:4010C0003F0E05D06879022827D0032825D026E020681422816868460078504302461332801D8B5C08182D498022896AFBF790FF0120687120682C224168684600780123C6 +:4011000050430A5A5B021A430A5268460078FBF7F7FFB07A022108431CE0801E687101204002002401900FE01B482C22006862434168019B885A98438852C00702D02046E9 +:40114000FBF7DEFF641CE4B2F07AA042ECD8B07AFD210840B0720F49A8792039104A03280BD0022812D001280CD0002050768878FD22104088703846FEBD01205076A879F7 +:40118000801EA871887802221043F3E701205076F1E700007C210008D4010008F0210008A021000810B509490748096888420AD10748084BC28A7D20C0004243044800214B +:4011C0001830F4F79DFC10BDEC470010EC010008A02100085D0B0110F7B515460C46F9F74FFF0746FF2C3DD0002F3BD014212646687C4E432C2180094C4301281AD11C4893 +:40120000214600680A314268525C0099921C4031CA714168201D0918284606220C30F3F768F91348062200688068811928461830F3F75FF90098F5F7EBFF002815D0042031 +:401240000C49897A01420DD0094800684168095D490707D58068B61D8119284606221230F3F747F9F807C00FFEBD0120E8E70000D40100087C21000810B510490A781049B7 +:40128000824201D8002003E0D0230A6A58431018002812D00A6B138802468032146B23800B6B146B5B88A3810B6B126B19881289914202D05A8800F009FB10BDCC1E0008C9 +:4012C0005C210008024901484860704750480010F8010008F7B50D463449334F897A84B03E4689065DD52C468034216B0A8B2946C0310091824204D3886820308078002820 +:401300004FD0002A02D12A48006B828828460699F5F7A6FD0646B84208D12889002102F098FD069805F0D8FF00263AE00027FF2069460197087200988068203081780129F2 +:4013400003D1A178002900D0C170A078401CA070A878FCF711F90407240FA878FCF7D4F80007000F04430F2C00D00127002416E00120009002AB03AA01A92846F5F7B8FC2B +:4013800000280AD10199002907D06846037AFF2B03D0027B2846F6F7BEFA641CE4B2BC42E6D3304607B0F0BDFFFF0000AC1E00085C21000870B50446C034217B0546002969 +:4013C0000CD0284600F0CAFA072807D0207B152802D1284600F018F80020207370BD704700487047FFFF000070470120704770470020704700207047024901484860704755 +:4014000030480010F801000870B50646FDF7FEFE04463089354620808035286B4089E080286BC08A2081286B00896080286B808AA0803046F7F705F9204604F027FF70BDED +:40144000FEB5044600790D46C01E05280DD848482E78807A20278006002807DB31462046FCF753F9E07E3843E076FEBD40212046FCF7A8F9A8786946000288806978084346 +:401480006946888029790A026946CA80E9780A436946CA80A9790A0269460A8069790A4369460A80297A0A0269464A80E97925460A4369464A808035296BC88069460888CD +:4014C000296B88806946C888296B488269464888296B0882204600F099FA2046F5F798FE00281ED1FDF7A8FE5E210A5B6179F6F7D1FD22460146A032507D0128286B408988 +:4015000026D080003C3083B2107D0128286B008B21D080003C3082B2103189B22046FDF73FF86420015BA078FBF728FC142E15D00F49A07D897AEF2239400843E17E384346 +:4015400011403943E176A0752046FFF75DFFFEBDC0007030D7E7C0007030DCE71521CC200155A07D3843A0752046FFF723FFFEBDAC1E0008014A526812691047F801000876 +:40158000014A526812691047F8010008F3B585B0FF206A460024107301941472184A2046927A920628D5059EC036B26820329578002917D1002D14D0009003AB02AA01A9B4 +:4015C0000598F5F795FB07466846037BFF2B06D00199002903D0027A0598F6F79CF9002F00D00124B0682030C178002904D0002D02D00124491EC170204607B0F0BD0000E0 +:40160000AC1E000870B504464878142801D015283BD1E07EEF21084020210843E076A07DDF210840A07540212046FCF7CBF82046F5F7EEFD002820D1FDF7FEFD5E210A5B9B +:401640006179F6F727FD22460546A032517D204680300129016B498918D089003C318BB2006B117D008B012913D080003C3082B21035A9B22046FCF793FF6420015BA0785F +:40168000FBF77CFB2046FFF7BFFE70BDC9007031E5E7C0007030EAE710B5044604F036FE00280CD106490A6B928822800A6BD28862800A6B1289A280096B4989E18010BD01 +:4016C0005C21000810B5044604F026FE002806D103490A6B12882280096B4988618010BD5C21000870B5054604F01CFE002817D12888F7F731FD040013D0F8F7A6FB0028D1 +:401700000FD0207909280ED02046F8F7AFFB01280BD0F5F763F9AA886988204600F0D6F870BD022070BD0C2070BD2A2070BD000010B5044604F0FCFD002806D10349228853 +:401740000B6B1A80096B62884A8010BD5C210008F3B5064631480025807A83B080065AD53746C0373868344680340090206B0290B8680190F1F7D2F8D02200213046F2F7A7 +:40178000C1FE029820630198B86000983860F1F7AFF8049801280FD130462421C830F3F7A1FD05042D0C36D130461A21B030F3F799FD05042D0C2ED11A220021206BF2F791 +:4017C000A1FE3046049900F05DF81549226B086B80881080086B226B00895080226B1B209080226BD080226B1081226B50810A6B236BD2889A81096B226B4989D181FF21B5 +:40180000226B49311182226B5182226B9182226BD182216B0883284605B0F0BDAC1E00085C21000810B504460020002906D00C211248F3F757FD0004000C1DD10F491B226A +:4018400030390B6B1A80FF220B6B49325A800B6B22889A8022880B6BD2007032DA800B6B62881A816288096BD20070324A81044920238A7A1A438A7210BD00008C210008D4 +:40188000AC1E000870B50546C03500290FD1A86820308678002408E0A868E1004058002801D005F019FD641CE4B2B442F4D324220021A868F2F726FEA868FF2120300170A9 +:4018C000A86800212030417070BD000070B5064604468036306B03898B4206D1838A934203D11D4B1B78002B07D0E37E9D0606D5A57DAD0603D41A2070BD002070BDDB067A +:4019000028D483891546AB4200D91D460180306B82812046F5F77CFC00280ED1FDF78CFC5E210A5B6179F6F7B5FB316B1030CB8981B22A462046FCF733FE6420015BA078FF +:40194000FBF71CFAE07E10210843E0761420C0342073D2E7232070BDF801000838B50546002000900C46A978684605F041FC002807D0142C03D1E87EEF210840E8760720B9 +:4019800038BD0098092204702C468034216B89784170216B4988090A8170216B897BC170216BC989090A0171216B09784171216B0988090A8171216B097BC171216B898951 +:4019C000090A01722946F8F799FE38BD70B504460088F7F7C1FB014680310B46096B2289CD89AA4203D1E5884E88B54206D0CA811A6BE1885180044A01211170A28861883A +:401A0000FFF764FF70BD0000F801000830B50024002835D0014680310A6BD3881588AB4200D32B4615899D4201D0138101240A6B538A9589AB4200D32B46958A9D4201D0DC +:401A4000938201240A6B958853889D4200D22B4655899D4201D053810124096B0A8ACB899A4200D31A46CB8A934201D0CA820124B421095C012200F007F802490020087010 +:401A8000204630BDF80100088030006B0129838A09D099080F39038989B28B4200D21946002A03D005E0D9080E39F4E7028B8A4200D901837047000070B504461B3CE12CD4 +:401AC0001CD2104C246BA588854217D30E4DA94214D8FF204930814210D3E6888E420DD3FB2A0BD81B2A09D32189914206D3AB4204D8834202D36089984201D2122070BDCA +:401B0000002070BD5C21000848080000F0B5314A0446314B002110465D5C491CC9B2A542FAD1A3009E462D4B491EDB7DCDB29C462A4C00216B003434E45A284B4E003433EC +:401B40009E5B254B5B5C9F00244BDF59BF897F00F619B6B2B44202D90020614625E0B24200D932460E46491CC9B2AE42E5D11CE01A4B4D0034335B5B1E1B052E09D2164D90 +:401B8000164E6D5CAF00F559AD896D005B199BB206E0124F75467F59FF89FF1CBE4217D39A4200D91A46491CC9B28C45E0D8094988420CD1101B04280AD9084A71465158CD +:401BC000C01E897C80B2002901D1401E80B2F0BD0020F0BDFFFF000000020008B4220008F7B50546002082B0164604460090F9F73BF90346002015E081006A581278002AED +:401C00000ED0062A0CD0464A670010556958098ACA1A012109045118424A641CD153E4B2401CC0B2697D8142E6D8012021E0014611E03C4B94467246DA53019B6246DA8352 +:401C4000374A575C5318BC46203BDF7F57546746491EDF77C9B2002909D0324B4F00DA5BFB18203B0193DB8B9E467245E1D3401CC0B2A042DBD300200399641EA446294CC5 +:401C8000086015E026494200095CA35A8F00EF591219FF895288DB19DB1C93420AD9039A136801228A4013430399401CC0B20B606045E7DB0399096800290BD0184A125C35 +:401CC0000120904001430398016001200090009805B0F0BD124801788A00A858807C3070B170002801D00128F1D1AA5821889289638852008A1892B2934204D9511A05E01F +:401D0000491EB180E3E7591A042905D9C91E89B2B1800028F4D0DAE70020B080D7E7000000020008E822000870B50A46034641780024007800F010FA264DFF2847D09E78C5 +:401D400025493300F8F7D0FD09060A0F13171B1F242943008000085800781CE0800008584068106034E08000085800890EE080000858807A0FE080000858808906E080001B +:401D80000858C08902E080000858008A10801FE080000858807C10701AE080000B581B7813700B585B6853600B581B8913810B589B7A93720B589B8993810B58DB89D381A9 +:401DC0000B581B8A13820858807C907400E02C46204670BD01001600B4220008F8B50446002020606060254EA060F07D002809D001280CD0224669463046FFF7F1FE012834 +:401E00001AD031E005202070FF20A070F8BD307E2070317DA170002801D00128F6D1317D8900715889894900C91E89B2A1800028ECD1491EA180F8BD0127104867701C30C5 +:401E4000009905F0B1FB054680003058807C2070B17D2846A94207D9FFF758FEA080A5700098AF40B843A06020783076A0783075A178A088890071580881F8BDB422000835 +:401E8000F8B5154F05460026387D344600901EE0E80716D0009880003858018AA0003858008AF8F79BFF0121C903884201D3002807D1094821461C3005F0EAFB0120A0402D +:401EC0000643641C787D6D08E4B2A04201D3002DDED13046F8BD0000B4220008F8B505460020287068602872F8F7BEFF0746F8F7C1FFFF213931884201D2022600E003266C +:401F0000002420E0A00010580178002919D0062917D0008A0121C01B0904401880B24910884201D8B0420CD801202870917DA14203D96968A040014369602146054805F0F7 +:401F4000A7FB641CE4B2034A1C3A507DA042D9D8F8BD0000D022000870B51C4DFF222A7505222A7600266975EE75A975334606E014225A4312189C005B1C2A51DBB28B4219 +:401F8000F6D30C4603E0A200641CAE50E4B2052CF9D314224A4310180A4601460B481C3005F09BFA00280FD100240AE0A000285821460670012000F00BF8002804D1641C21 +:401FC000E4B2A97DA142F1D870BD0000B4220008F3B583B0002668461A4C0671607D0D4600282BD069464D70039808702946039800F0B2F80746FF281ED0024601A968466A +:4020000000F060F9B8002258711E51602258090C118122589672225891812258D18121582A460E8220580521817420461C30039905F07EFA05B0F0BD0348FBE70248401CEE +:40204000F8E70000B422000801001600F8B50F4606460024F8F708FF0546F8F70BFFFF213931884201D2BF1C00E0FF1C0B48B2008258F9B2107800280ED006280CD0108A27 +:402080000122401B1204801882B20120C003824201D88A4200D801242046F8BDB4220008F8B52B4D0024E87D022801D20020F8BDF8F7DAFE264F264B002134370126360463 +:4020C0005D7D11E08B00D2581378002B0AD0062B08D0204B1955128A6300121A9219641CFA52E4B2491CC9B2194A8D42EAD8012117E008460AE07B53164BF2831A18203A61 +:402100001D5CD67F1E54401ED577C0B2002806D04500EE19203E7A5BF38B9A42EBD3491CC9B2A142E5D30B49388809787B888A0007498A58D2898218D21C9A4206D80A7DBB +:4021400092008958C989C91C8842AFD80120F8BDB422000800020008022804D20348807D401E884200DAFF2108467047B422000810B50146014805F0FBF910BDD022000854 +:402180000A4610B50146024805F066FA10BD0000D02200080A4610B50146024805F04CFA10BD0000D0220008F3B500980C46417800250078FFF7D0FF06463F48FF2E78D0C0 +:4021C00000993E4F89783E4A0B00F8F78DFB09060F161D242D34393E72002178062968D232462146009800F06DF863E0216891425FD8B000385841605CE02188914258D882 +:40220000B0003858018155E02178022951D2B000385881724EE021881922D201914248D8B0003858818145E02188914241D8B0003858C1813EE0B10079582088088239E04C +:402240002178052935D2B0002FE02178062930D2616891422DD8218991422AD8A17A022927D2A3891921C9018B4222D8E18991421FD8A17C05291CD232462146009800F0DD +:4022800021F8B0003A58616851603A58218911813A58A17A91723A58A18991813A58E189D1813A58218A1182A17C3858817401E0FFE705462846FCBD01001600B42200080F +:4022C000FF18000010B51A4B92009A58097814781170002C0BD0002917D1D87D401EC0B2D875012811D1194600204B7D1DE0012901D0022909D1D97D491CC9B2D975012904 +:4023000003D1417819750078187610BD82008A581278002A07D0062A05D082008A58927C0A76087510BD401CC0B28342EED810BDB4220008A03001777047000002490148E8 +:402340000860704798480010080200087047704770477047704770470249014808607047704800100802000870B5224DA030447E6E7D002334404476067E2D7D2E400676EB +:40238000857E2C400C70047EC57E2C4014700D780224032D00D30C701578032D00D31470447E0025012C02D0022C04D00CE0047E012C03D008E0047E022C05D10C78167869 +:4023C000B44201D00D701570047D0E78344200D00D70447D1678344200D015700978002901D0012381751178002901D00123C175184670BD7C2100081CB50400684681701A +:4024000008D020896A4610802046A030417D1171007DD0702146C031487B820701D57D2202E0C20702D07E221040487303496846096888472046F6F704F91CBD54020008A6 +:4024400010B541780078491EC9B2FAF73DF9024904200876002010BD5C21000810B5C1780278491ECBB281784078FAF743F9024903200876002010BD5C210008F0B587B08A +:402480000026694600960E740E75054605AA04A9FFF76AFF2C46A0340746012814D1A07D022602282AD000200290E07D022827D0002001902846FCF79CF80090A878009B7B +:4024C000019A0299FAF75EF91F48807A800604D5A17D00222846FFF7D7FA03966846007C009E00906846007D019000200290A97802A804F07DFE002818D103E00120D3E7C1 +:402500000120D6E702981823019A0099037041708270C670310A017105222946F8F7EEF880212846F5F7C8FB03982077002F08D1607F002805D10320607700212846FFF7FC +:402540005BFF07B0F0BD0000AC1E0008014A12689269104708020008F8B50F460546F4F757FE214EF17AC907C90F12D02C467978A0342176B97801276176677700280DD0D0 +:402580002846FFF77BFFC035687B822108436873F8BD39462846FBF73AFDF8BDB07A800604D5002201212846FFF76EFA00200090A978684604F01CFE0028E4D10098172248 +:4025C00002700A4A2946537D4370127D82700322F8F794F8728A80212846F5F74DFB042020776777CFE70000AC1E00087C21000870B506460E480C46C07AC007C00F30469E +:402600000DD0F4F705FE00280CD035466078A0352876A07868763046FFF730FF70BDFBF7F6FC70BD172224213046FBF722FF70BDAC1E0008014A1268D269104708020008C7 +:40264000014A1268126A10470802000870B517490978814201D8002504E01549D022096A50430D18002D1FD02C46A034207F02281AD1E07D60750E48A17D21752030027D69 +:40268000E276407DA07609482038807A800603D501222846FFF7F8F9002020770320607700212846FFF7A8FE70BD0000CC1E00085C210008FEB50C460746F4F7A9FD0128EA +:4026C0001DD080213846F5F7F7FA2E48A578017D407D667805400E402079E1780002014330463C462843A0340191002804D0B878F8F75AFD012808D0002E0FD00FE0182208 +:4027000024213846FBF7B5FEFEBD28215A20C155002020773846F6F7AFFBFEBD667D002D00D1257D207D28420ED0607D30420BD000200090607F00281BD1032060770021C6 +:402740003846FFF759FE14E0022D17D00021022E16D0002202200090B878019BFAF712F80948807A800604D5002229463846FFF78BF9E675A57500982077FEBD0121E6E731 +:402780000122E7E77C210008AC1E000870B50C46F6F7E2FC0546002060702070002D0BD02846F7F752FB002806D0A035687D6070287D2070002070BD022070BD10B501785C +:4027C0004478CA078378084903D14A7D224009D08A750078800703D4087D184002D0C875002010BD112010BD7C210008F8B50746FF2168460170FE783D793888F6F7ACFC1F +:4028000004000FD0F7F721FB00280BD0B9782148CA0709D0B422175D89070AD4067D2E4005D008E01E20F8BD477D3740F4D11120F8BDB520065D2546A035687D304209D07D +:40284000287D384206D00320687700212046FFF7D3FD14E002236A4618212046F7F75BFB01280ED002236A46FF212046F7F70CFB012806D0AF76EE76204600F07FF800209C +:40288000F8BD68460078002801D02320F8BD2A20F8BD00007C21000870B50E4605468021FAF790FF2C460020A03420770C48017DE176407DA0760B48807A800604D5217D80 +:4028C00001222846FFF7E0F82846F4F7A1FC002805D10320607731462846FFF78DFD70BD7C210008AC1E000870B505468021FAF769FF2C460021A03421770C49087DE076E9 +:40290000487DA0760A48807A800604D5217D01222846FFF7B9F8607F002803D100212846FFF76AFD0320607770BD00007C210008AC1E000810B50F490978814201D800207C +:4029400004E00D49D022096A5043081800280FD00949A03020318A7D037D9A4203D1CB7D447DA34204D08276C97DC1760121017710BD0000CC1E00085C210008F8B5054647 +:402980002C460020A0346077207F012801D1022060772846F4F73CFC134F00281AD0032600200090A978684604F022FC002810D1009816220270A27E4270E27E82702946AA +:4029C0000322F7F79BFE7A8A80212846F5F754F92677F8BDB87A04268006E1D5A17E00222846FFF751F8DBE7AC1E0008F7B54804040C82B0384801900178029816468142F6 +:402A000005D919200002844201D8082E01D9334C52E0029F0620474331483D182879012801D0022802D1029800F0C8FB2C48C4536E71C45B408B84421ED22146F0F768F861 +:402A4000002919D10094019800240078019011E006202146414322480E183079012801D0022804D170880099F0F752F87180641C0198E4B2A042EBD8029800F033F8174999 +:402A8000044688421DD0164E6C80F15B708B814206D2F0F73DF8002902D1029800F000FC718BF05BF0F734F8002908D0022028710B48017F491C0177204605B0F0BD012096 +:402AC000F5E72879002803D06888801C80B200E00A2068800320EAE7CC1E0008FFFF0000F2220008F0B50646AFB00020039001200690E0480090E048089030460622DF49B6 +:402B00005043002501904018029050E028460621DA4A4843811804910979012901D0022943D1B54241D0039F14214F430BACE5550199105A515A00F0A3F93F1904467860ED +:402B400001282AD0049802994079497905914118A14204D90020B860F860069015E00499201A49880919081A04912146EFF7D0FFB96004990598081A2146EFF7C9FFF96036 +:402B80000098844201D2A0B20090F868A04201D9012000E00020387403E00020B860F86006900398401CC0B203906D1CEDB208980078A842AAD8069800280ED00398002801 +:402BC0000ED000200490AD490198085A01900020044605900546039045E00020C04343E1A64806760199415A418300203CE1284606214843A14907904018069000790128A7 +:402C000001D002282DD1B5422BD01420214641430BA80F18B8680099EFF77AFFB960F8680099EFF775FFF9600698069940884979A70042181FA9CA510099EFF769FF27A872 +:402C4000C1518E490798095A019800F019F901901FA8C0590099EFF75BFF1FA8641CC151E4B26D1CEDB208980078A842BFD8601E054681B20A901FA800F0FAFAA9B227A869 +:402C800000F0F6FA002729E00898002500780790B80006901DE0062029464143774808180179012901D0022911D1B5420FD04188407908180099EFF72BFF0A4606981FA994 +:402CC0000858824203D106982BA90D5004E06D1CEDB20798A842DED87F1CFFB2A742D3D3002559E0AE002BA806968059062148436249401840880099EFF70AFF1FA88059EE +:402D00000F4686B209902146681CEFF701FF880008902BA907900858062148435749401840880099EFF7F4FE07981FAA105A012C82B223D9B94201D3B1420ED9BA4201D326 +:402D4000B2420AD9914214D3B24201D2B94201D8012000E00020002810D08F420ED196420CD10A98854209D0069923AA0998505010E0B942EED8B242ECD3E9E7089827A906 +:402D800009580198401E08180199EFF7C1FE069823AA11506D1CEDB2A542A3D300205BE000991FAA8900555823AA535800202E461F469D424DD0002122E0142251430BAA09 +:402DC00089188A680020B24205D3BA4203D8AA4200D915460120C968B14206D3B94204D8994200D20B46012007E0002805D18A4214D99642F7D88F42F5D36146491CC9B2E4 +:402E00008C46A142D9D3002823D0AB4210D30399581B884207D8002905D01AE0964218D98F42E0D315E003905819400804900EE0019803991818401B88420AD903900198ED +:402E40005919081840080199EFF762FE0491012005900098401CC0B20090A042A0D30598002800D1B9E6049802994880029840882FB0F0BDFFFF0000CC1E0008F2220008D4 +:402E800010B50C46002807D0002C05D0EFF740FE20460C00FAD110BD002010BD014606225143064A04488A181179012901D0022900D1508870470000FFFF0000F222000875 +:402EC000FEB5284B1B780293834209D91923DB01994205D89A4203D8062901D3062A01D22148FEBD914201D10846FEBD49040E0C51041E4A0F0C117F002905D0012906D1B0 +:402F00001146097E814202D1F0198008FEBD3D4624E001200024019016E0204606214843124942181279012A0CD1085A29460090EFF7EEFD002905D028460099EFF7E8FD1C +:402F4000002909D1641CE4B20298A042E5D80198002801D06808FEBD6D1EADB2B542D8D2D2E70000CC1E0008FFFF0000F2220008FEB5062107466A4E4F43BC1921790129E8 +:402F800006D0022904D0F7F76FFF6188401860E0337E0121062283426ED1624B00241D780BE0062363439B191B79012B01D0022B01D1844203D1641CE4B2A542F1D8A542B5 +:402FC00003D1F7F751FF0A3043E06846447101718271694601A8FEF7A7FE06204443A019418868460088411A68460180F7F73CFF0546684601882846F7F7FAFE04466846C2 +:40300000018803222846F8F7EDF8002823D06846018801222846F8F7E5F8002812D0778B20463946EFF774FD7819401A01E0708B001984B2032221462846F8F7D3F80028B7 +:40304000F5D16BE0768B20463146EFF761FD4819801984B262E0718B2046EFF759FD481901E0708B001984B2032221462846F8F7B9F80028F5D151E0684643710171827101 +:40308000694601A8FEF750FE684661880088091868460180F7F7E8FE0546684601882846F7F7A6FE02902079022817D0768B6846018803222846F8F795F800281FD0684668 +:4030C000018801222846F8F78DF800280298314610D0EFF71DFDA819401A02E0F65BE6E7A01984B2032221462846F8F77BF80028F6D113E0EFF70CFDA8190818A9E731460A +:403100000298EFF705FD481900E0A01984B2032221462846F8F766F80028F6D12046FEBDF2220008CC1E000810B50B460621104C484302191179012906D0022904D0205A36 +:403140004008F3F777FE10BD0A498B4206D15188022903D3C8031904401807E0215A50880818C01A801EEFF7D3FCC803000C10BDF2220008FFFF0000F0B500200E4A84469E +:40318000014606460A4B0B4CFF20157809E006270A467A43A352121953801671491C5071C9B28D42F3D82076638326776046F0BDFFFF0000F2220008CC1E0008F8B50146E0 +:4031C0000020009026480078844688421AD9084606225043234F8646C0190279002A11D000220271204B7246BB52FF2643804671387F1C46401E3877387E354688422CD18A +:40320000002019E01948009027E0062201465143CA191279012A02D0022A06D00AE0795AA14207D20C46064604E0795A994201D20B460546401CC0B28445E6D8FF2E01D0A2 +:40324000304602E0FF2D03D0284600F029F804E0FF2038760020C04378830098F8BD0000CC1E0008F2220008FFFF000001001600F0B58C4600230FE00022C91A491E08E05C +:403280009600371884597D68AC4201DD85517C60521C9142F4DC5B1C61466345ECDBF0BDFEB5064615480621374606764F43C15B41830146002479181148009100780190C1 +:4032C00016E006200D49604345182879012801D002280AD1B44208D06888C95B421800984088101AEFF7FEFC6980641C0198E4B2A042E6D8009800214180FEBDF22200088D +:40330000CC1E00080348C078002801D000207047012070478025000810B5012200F046F810BD000010B5054802780121002A017002D10120F2F734FB002010BD0C02000888 +:4033400070B5144D297803200129287002D10120F2F726FBEDF7CFF8EFF7E0FA00246C60FF22813221460C48F1F7CCF8F02200210A48F1F7C7F80948F030C47004704470B4 +:40338000C47304734473EDF7B2F8EFF7B1FA002070BD00000C020008102300089024000810B5002200F002F810BD0000F8B515460C460646EDF79FF8EFF7B0FA264A1078E8 +:4033C000012808D01078022805D0EDF790F8EFF78FFA1120F8BD0C20464320483018C1788378994205D3EDF782F8EFF781FA1220F8BD46780C277E43416867687118266851 +:40340000A4684F600E608C60C178431C491CC1704178491CC9B219708078814201D1002018705068401C50601078012805D0EDF75EF8EFF75DFA0020F8BD02201070EDF7D6 +:4034400056F8EFF755FA002D03D00020F2F7A8FAF1E70120FAE700000C0200088025000810B51248002101704160FF2281321048F1F748F8F02200210E48F1F743F80D48DA +:4034800018220021F030F1F73DF80A482021F03081701421817306494160064901610649816006494161F2F761FA10BD0C020008102300089024000843EB0010456C0110C7 +:4034C000F8B50025164C01262F462078002815D0012813D0022802D003281CD11AE000F021F8EDF708F8EFF719FA6068002800D12670ECF7FCFFEFF7FBF90CE0ECF7FBFF7F +:40350000EFF70CFA2078002802D020780128F0D10125EEE72770002DD7D00020F8BD00000C020008FEB5214D214E0027FF24ECF7E2FFEFF7F3F900200C2141438919C97816 +:40354000002901D0044602E0401C0228F4D3FF2C2AD00C204443A41921780C2260685143081801460EC9029301920091076047608760E078401EE0702078401CC0B2207038 +:40358000A178884200D127706868002802D06868401E6860ECF7ABFFEFF7AAF9A1680029C4D068468847C1E7FEBD00000C0200088025000810B5830A082B04D03F2B05D0E9 +:4035C00004F078F810BD00F025F910BD01F0A8FB10BD10B50C460146207800F02BFE0028204603D003F0DFFA002010BD00F082FD1F2010BD38B504460020009069460520FF +:4036000000F071FD00280AD101200099052C07D010220A708C704870FF20FFF7DAFF38BD1A220A708870F6E710B5820A082A04D03F2A05D004F0F0F810BD00F015FA10BD8F +:4036400001F072FB10BD0000F8B5044640782578000205430020694608702846FFF7E4FF01282BD16946A0780978884226D022498D420CD0891D8D4209D0C91C8D4206D0E0 +:40368000C91C8D4203D01C4925318D4204D11221284600F0A1F80CE00022022805D32079E178000201430A05120D12212846FFF781FF204603F0C8FD1220F8BDA80A0F4E59 +:4036C00008280ED03F282A46314610D0E01C04F0EDF8204603F0B8FD3146284600F010F8F8BD2A463146E01C00F0CEF9F1E7E01C01F070FBEDE700000D2000009825000889 +:40370000F8B50D4604460020694608702E48871D844212D0BC4210D0F81C84420DD0C01C84420AD028481830844206D0401C844203D025482530844201D101200870A00A3F +:4037400008280ED03F280A46294620460FD004F0FFF806466846007800280BD001281FD116E00A462946204600F0C2F9F1E701F051FCEEE70022002D05D0687829780002FF +:4037800001430A05120D31462046FFF713FF07E0BC4201D13A2E05D03146204600F01CF83046F8BD68782978000201430805000DF5F7D2FC05460021204600F00DF83A21F5 +:4037C0002846FAF774F8EBE70D2000000148007B70470000A0210008F8B5054600200E4600906946082000F07EFC002801D00720F8BD009C0F202070A670FFF7E7FFE0700C +:403800002571280A6071042060702146FF20FFF7E0FEF8BDF7B584B00546002002900420694608718649874B681A0C22EE1806278D423BD010DC8449681A8D4230D006DC79 +:40384000002E28D0012E28D0052E13D128E006282AD009280ED120E0172829D006DC012824D0022819D0162804D11FE019281FD01A281DD07549284609688847694609794C +:40388000401869460871724928460968884769460979401805E0781C03E06846027107E005206946087103E00B20FAE7684607716846007902A9001D00F015FC002802D0E6 +:4038C000072007B0F0BD029C29462046059A00F001F90420694608715949491C681A8D420AD005DC5B48281806D005280BD103E0072801D0152806D10699A171069968462B +:40390000090AE17107710598002821D14C49491F681A8D425AD009DC4F4F002E20D0012E2FD0052E44D00D2E06D148E003285CD0072866D01B286FD0484B01AA1B682146C5 +:4039400028469847464B01AA1B682146284698476846007960702146FF20FFF73AFEB0E769460979387D6118887069460979000A6118C87069460879801CC0B20871797D55 +:403980005BE06946087908222018801C0021F0F7B9FDB87AF52108406946097961188870F87A6946C0070979C00F6118C87023E0F3F708FC05E069460879401C1FE0F3F779 +:4039C00021FC6946097961188870F4E7684600792118891C0698F3F700FC002801D06071B6E769460879401D09E06946087908212018801C03F05DF9694608790830087170 +:403A0000A6E76946087914492018801C08221831F0F76FFDF0E7FFE7124A694612680698904760716946087809796118887069460879401CC0B20871497820188170BAE726 +:403A40001A200000FEDFFFFF0F2000004C0200083C020008EBDFFFFFAC1E0008480200083802000858020008064AC0B21378834206D3401E1269C0B2105C087001207047E4 +:403A8000002070471402000830B4074BD2B21C78944206D39B689200D218403AD26B30BC104730BC704700001402000807484E21017007494160FF3139318160FF313931A5 +:403AC000C160FF313931016170470000140200084449001070B504460E2016460D462070FFF774FEA070E570280A2071667170BDF8B50D4D16460F46C1B22A780120914206 +:403B000010D88C00E868314620184038C26B38469047002806D16868314620184038C26B38469047F8BD000014020008F8B5054600260D4F69460620009600F0D4FA002802 +:403B400001D00720F8BD009C324639462046FFF7C1FFA571280AE071062060702146FF20FFF737FDF8BD00001F20000070B50446054640220021F0F7C5FC40222349284695 +:403B8000F0F7B7FC2249F522887A20341040C0060028207802DA3022104301E0CF2210402070887AC2070720002A2A7F01D0024301E0D208D2002A778A7A93060122002B96 +:403BC0000ADA6378C0252B436370A37808251343A370E3782B43E3708B7A5B060AD5A378F8252B43A370E3780343E370E07904231843E071C87AC00706D0E078F021084362 +:403C0000E07020791043207170BD0000654E0010AC1E000810B50022F3F776FB10BD10B5F3F7D0FB10BD002070470120704710B5F3F74AFC10BD0020704710B5F3F746FC66 +:403C400010BD0000044A0178D180407800020143D180002070470000A021000810B5F3F7E3FC10BD10B5F3F7FBFC10BD10B5F3F703FD10BD10B5F3F70DFD10BD38B5044669 +:403C80000020009069460E2000F02DFA002801D0072038BD00993E200870032088702078C870A07808716088000A487120798871A088000AC871A0790872E088000A4872F9 +:403CC000207A88722089000AC8720A2048700320FFF77FFC38BDF8B50546002000906946232000F000FA002801D00720F8BD009C3E2020700A2100F09DFA014601200029B2 +:403D000046D001260A20A07007462878E070A978217169880622090A61716878A0712879E0712046294608300C31F0F7E2FB0C20002E0ED0204629460E3006221231F0F790 +:403D4000D8FB20462946143006221831F0F7D1FB1820AA7921188A70EA88801C120ACA702A7A21188A702A89801C120ACA70AA7A21188A706A89801C120ACA70221869796D +:403D80009170401C607021463846FFF722FCF8BD0026A0700127B8E7F8B5044600200E46009015466946082000F09DF9002801D00020F8BD0099082008708E70CC70200A0D +:403DC00008714D7104204870FF20FFF702FCF8BD38B50C460021054600916946072000F082F9002801D0002038BD0099302008708D70CC70200A087103204870FF20FFF730 +:403E0000E8FB38BD38B50546002000906946112000F069F9002801D0002038BD009C3E2020700520A0702878E07028880822000A2071601D6968F0F75CFBA9680D200A7812 +:403E400062734978A173607021460520FFF7C1FB38BD38B5054600200C4600906946092000F041F9002801D0002038BD00991320087001208870CD70280A08714C71200A1F +:403E8000887105204870FF20FFF7A3FB38BD38B50546002000906946102000F024F9002801D0072038BD009C3E2020700420A0702878E070A87820716888000A60712878D1 +:403EC00000280BD0A01D08220021F0F71BFB0C20607021460420FFF77CFB38BDA01D0822A968F0F706FBF2E738B504460020009069460C2000F0F7F8002801D0002038BD69 +:403F000000990C20087020788870A078C8706088000A08716078487120798871A088000AC871A0790872E088000A487208204870FF20FFF74EFB38BD38B504460020009092 +:403F40006946062000F0CFF8002801D0072038BD0099572008708C70200AC87002204870FF20FFF736FB38BDF8B5064600200C46009015466946082000F0B5F8002801D0E2 +:403F80000020F8BD0099052008708E70CC70200A08714D7104204870FF20FFF71AFBF8BDFEB507460020009010480E46019015466946082000F097F8002801D00720FEBD27 +:403FC000009C324620460199FFF784FDA771380AE0710620002E03D1290A25726172082060702146FF20FFF7F4FAFEBD7B0C0000F8B5054600200E4600900C4F69460620F6 +:4040000000F071F8002801D00720F8BD009C324639462046FFF75EFDA571280AE071062060702146FF20FFF7D4FAF8BD7C0C000010B5F5F7E3F910BD10B5F5F73BFA10BDE5 +:4040400010B5F5F759FA10BD10B5F5F7BBFB10BD10B5F5F7D2FB10BD10B5F5F761FC10BD10B5F3F7C7FA10BD10B501220A70F5F743FD10BDF8B505460020074600900D4E2D +:404080006946142000F02FF8002801D00720F8BD009C3A4631462046FFF71CFD1022A01DA918F0F726FA142060702146FF20FFF790FAF8BD1720000010B5F3F799F910BD6E +:4040C00010B50029014601D00B2000E00220FFF780FA002010BD10B5FAF70CFC10BD10B5FAF730FC10BD0A4610B5C1B2104603F02BF810BD10B503F0C3F810BDF8B50546FD +:40410000C078AE78154C00020643A07C27468000C03FC019403004222946F0F7EAF9A07C238A8100C81940302A1D102B15D07D50A17C00234900C91980310E80A17C0B55CF +:40414000A17C491CC9B2A174102900D3A374218A491C2182114602F017FDF8BD9C2600083EB5134C0025E07C21460555E07CC0398000085803F09AF8E07C401CC0B2E074AF +:40418000102800D3E574208A401E20820948807A00280CD00095019511206A4602951081558129460A460020029B03F088F93EBD9C260008A021000870B5184C0025207AD2 +:4041C000002825D1F1F764F915488574C574058225726572A572A5821DE0A07A00280DD0401EA0720D4A0006410DC03A8818515C4068022907D0042907D101E01920F0E77C +:4042000003F03EF801E0FFF7ABFFE07A401EE072E07A0128E1D80348057070BD702700089C2600082802000810B5FFF7C5FF002010BD00001C4B13285A7A31D00EDC0E2803 +:404240002ED006DC052820D0082827D00C2829D11DE00F2824D0102824D11FE03E280AD004DC1A2817D030281CD112E0572814D0FF2817D114E0500614D5491E0120884023 +:40428000D98880B201420BD10CE0012006E0802004E0202002E0022000E00420024201D00120704700207047A021000838B505460020009069460920FFF715FF002801D03D +:4042C000072038BD009CFF2020700320A0702878E07028880422000A2071601DA91CF0F708F9072060702146FF20FFF772F9002038BD03B583B0002069460090888001AAA9 +:4043000004A91220F1F7F6F969460320FFF7EBFE00280ED10099FF2008700620887068468088C870000A087103204870FF20FFF750F905B000BD03B583B00020694600905B +:40434000888001AA04A91120F1F7D4F969460320FFF7C9FE00280ED10099FF2008700720887068468088C870000A087103204870FF20FFF72EF905B000BD000038B50446E1 +:4043800000200C4900900878401E087069460520FFF7A9FE00280CD10099FF20087002208870200ECC70087103204870FF20FFF710F938BD2802000810B50B4C617E0029BB +:4043C0000BD00A49884209D1F2F7D8FB607E022801D1F0F76FFF0020607610BD02F0F4FB607E00F031FF10BD5C210008C0FD0000FEB5044600200290607F0F46401CC6B298 +:4044000002A9301DFFF76FFE002801D00720FEBD029D21463931E81D019100902246637F1E3229392046F2F727FA0C49884204D12846FFF75FFE1220FEBD002208492846C0 +:40444000FFF748FB607FA871361D6E70022038702946FF20FFF7BDF80020FEBD01001600A9FD0000FEB5044600200290607F0F46401DC6B202A9301DFFF735FE002801D06D +:404480000720FEBD029D2246A91D481D019100902146637F1E3210312046F2F715FA0C49884204D12846FFF725FE1220FEBD002208492846FFF70EFB607FA872361D6E701C +:4044C000022038702946FF20FFF783F80020FEBD01001600A8FD0000F8B5044600200E46009069462420FFF7FEFD002801D00720F8BD009D002225492846FFF7EBFA2146CB +:404500002046AA1D20311030F2F700FA002804D02846FFF7EFFD1220F8BD2178A97521882846090AE97521681C30090C29762168090E69762179A976A188090AE976616843 +:40454000090C29776168090E6977217AA9772189090AE977A168090C0171A168090E4171217B001D8170A189090AC170E168090C0171E168090E41712420687002203070B4 +:404580002946FF20FFF725F80020F8BDADFD00000120704738B500200D46009069461020FFF7A1FD002801D0072038BD009C00220B492046FFF78EFAA11D0020F6F760FC6E +:4045C00021460C310120F6F75BFC10206070022028702146FF20FEF7FCFF002038BD0000A1FD00007CB500200D46009069460620FFF779FD002801D007207CBD009C002243 +:404600000B492046FFF766FA01A8F1F7D7F868460079A07168464079E07106206070022028702146FF20FEF7D4FF00207CBD0000A2FD000010B5012008700024034803F064 +:40464000BFFA002800D00C24204610BDF342011010B5012008700024034803F097FA002800D00C24204610BD37430110F3B5044683B000200190207D002601461131CAB20B +:40468000332802D9122005B0F0BD01A9101DFFF72AFD002801D00720F5E7019D002232492846FFF717FA2068FAF7A2FE277DAF710520009009E080194019801C394602F016 +:4046C000F8FA0836083FF6B2FFB20098082FF2D880194019801C394602F0EBFA217D009822790818C1B268188270A288091D120AC2706268C9B2120C02716268120E427186 +:40470000227A681882702289091D120AC270A268C9B2120C0271A268120E4271227B68188270A289091D120AC270E268C9B2120C0271E268120E4271227C68188270228A7C +:40474000091D120AC2702269120C02712269120E427169700498022101702946FF20FEF738FF00208FE70000ACFD0000FEB50F460546FF2069460871002000902888F4F764 +:40478000EBFC060027D0F5F760FB002823D069460720FFF7A8FC002801D00720FEBD009C00220E492046FFF795F92878A07128880223000AE07101AAFF213046F5F7ABFBB5 +:4047C000207207206070022038702146FF20FEF700FF0020FEBD0220FEBD0000AAFD000010B500240C708179002904D0012905D01224204610BDF8F7C9FAFAE7F8F7FEFA4F +:40480000F7E70000F8B505460F460088F4F7A4FC04006FD0F5F719FB00286BD00020009069460620FFF75FFC002801D00720F8BD009EF6F7A1FA2046F2F7EAFC00283FD156 +:40484000FAF7FAFC5E210A5B6179F3F723FC2246A0320146537D2848012B837A05D09B060DD5B0231B595B890AE09B0603D5B0231B595B8900E01B23DB00703302E01B23D3 +:404880009B003C33127D807A9BB2012A05D080060DD5B0200059008B0AE0800603D5B0200059008B00E01B20C000703002E01B2080003C3082B2103189B22046F9F770FE08 +:4048C00068886034E080F6F773FA00220B493046FFF700F92978B17129880620090AF1717070022038703146FF20FEF772FE0020F8BDFFE70220FBE7AC1E0008B0FD0000AD +:4049000010B500240C70F0F787FF0349884200D11224204610BD000001001600F8B504460E460088F4F718FC05002AD0F5F78DFA002826D0A178A878FDF72CFC002801D08E +:404940001220F8BD0020009069460620FFF7CBFB002801D00720F8BD009D00220A492846FFF7B8F82078A87120882946000AE8710620687002203070FF20FEF72AFE0020CD +:40498000F8BD0220F8BD0000B2FD0000F8B504460F460088F4F7E0FB050043D0F5F755FA00283FD00020009069460620FFF79BFB002801D00720F8BD2879009E09280CD066 +:4049C0002389E288A1886088FDF776F8002806D03046FFF78FFB1220F8BD0C220FE0E87E810604D5A97D890601D41A2207E0C00604D42046FCF7EAFF024600E023220A4923 +:404A00003046FFF767F82178B17121880620090AF1717070022038703146FF20FEF7D9FD0020F8BD0220F8BDB1FD0000024600200870024912784A7370470000A021000855 +:404A4000F8B504460F460088F4F786FB060026D0F5F7FBF9002822D00020009069460620FFF741FB002801D00720F8BDA178B078009DF8F7C1FB00220A492846FFF72AF8F0 +:404A80002078A87120882946000AE8710620687002203870FF20FEF79CFD0020F8BD0220F8BD0000ABFD0000F3B5044683B000200090054621786A46517101202056032617 +:404AC0001071002809D0042807D0821D05D0921D03D0121D01D0143007D101290FD001A8F0F7C0FE2949884200D112256946301DFFF7F9FA002830D0072005B0F0BD608806 +:404B0000FF2811D0F4F728FB070000D10225F5F79CF9002806D0002DE8D1EDF7FFFE6078387317E00225E1E7EDF7F8FE0020184B184A08E0D027196A4743C91901D0677874 +:404B40000F73401CC0B211788142F3D8104861784030C170EDF7CCFEC8E7009E2A460E493046FEF7B7FF2078B071A078F07160880221000A307207207070049801703146A5 +:404B8000FF20FEF726FD2846B7E70000010016005C210008CC1E0008A5FD000010B5044602200870F7F7D8FE207800F04DFB10BD7CB505460020184C009020780E461228C2 +:404BC00007D22979154B01A82A68F0F727FF002801D00C207CBD20786946401C20700620FFF781FA002801D007207CBD009C00220B492046FEF76EFF2879A071684600795E +:404C0000E07106206070022030702146FF20FEF7E0FC00207CBD0000280200087D430110C1FD0000F8B505460020154C009020780E4600280FD06878F0F776FF002802D1C7 +:404C40002078401E207069460520FFF74CFA002803D00720F8BD0C20F8BD009C002209492046FEF737FF2878A07105206070022030702146FF20FEF7ACFC0020F8BD0000E5 +:404C800028020008C2FD000038B500200D46009069461020FFF727FA002801D0072038BD009C00221C492046FEF714FF1B48016B0978A171016B0988090AE171016B897846 +:404CC0002172016B4988090A6172016B0979A172016B8988090AE172016B89792173016BC988090A6173016B097AA173016B0989090AE173016B897A2174006B214640896D +:404D0000000A60741020607002202870FF20FEF760FC002038BD0000A7FD00005C21000810B502F0C7FC10BD10B5264B0022C41A98423CD01FDC244BC41A98423CD011DCAF +:404D4000224C031BA0422AD007DC214BC01822D0012822D0C92832D12EE0012B2CD0022B2DD129E02300F5F7BFFD092A271618272A2A181E2A002300F5F7B6FD18211B1ED7 +:404D80001E0D1D151E13212121212121212121212113170F132104220EE002220CE007220AE0012208E0032206E0052204E0152202E0302200E00A220A70012010BD002036 +:404DC00010BD0000ACFD0000A3FD0000A0FD00009A03FFFF10B53D4BD41A9A425AD01CDC3B4BD41A9A4240D00FDC3A4C131BA2422FD005DC384BD31825D0012B20D125E0E4 +:404E0000012B29D0022B1BD12CE0641F2300F5F76BFD062F3217383B3E17092C52D007DC2300F5F761FD080D40430D0D461C490D152C23D0162C30D0172C31D0182C3ED0CB +:404E400000F0B2FF10BD00F022FD10BD00F040FC10BD00F053FC10BD00F026FD10BD00F02AFB10BD00F0B0FC10BD00F0FEFA10BD00F04CFB10BD00F010FB10BD00F051FBFB +:404E800010BD00F039FA10BD00F016FA10BD00F0E5FA10BD00F031FB10BD00F045FB10BD00F053FB10BD00F08FFA10BD00F03CFA10BD00F0E5FA10BD00F0F4FA10BD00F06B +:404EC00019FB10BD00F046FB10BD0000ABFD0000A0FD000049FD00009A03FFFF3EB50020009001900290012008700D4602A90C20FFF7F9F8002801D007203EBD029C002262 +:404F000010492046FEF7E6FD01A96846F2F7D6FB0098A071010AE171010C2172000E60720198A072010AE172010C2173000E60730C206070022028702146FF20FEF749FB42 +:404F400000203EBDB3FD0000F7B582B006460027012000971070154669460620FFF7C3F8002802D0072005B0F0BD009CF00701D01220F8E73A4620460399FEF7ABFD084895 +:404F800030180068A071000AE07106206070022028702146FF20FEF71CFB0020E3E7000000103C4010B50A4600880249FFF7CCFF10BD000067FC0000FEB5064600270120FD +:404FC000009708700D4669460820FFF78CF8002801D00720FEBD009C3A460D492046FEF779FD01AA31460520F0F784FB0198A071010AE171010C2172000E607208206070B4 +:40500000022028702146FF20FEF7E3FA0020FEBD49FD000070B5674B0E460024C11A664D984270D020DC654BC11A984257D013DC634BC11A984238D007DC6249411825D088 +:40504000012928D0E3296ED12AE0012932D056293BD0572967D13DE00B00F5F745FC08A6454A4F555F656AA60C240B00F5F73CFC1A9D6B70752B2B7A267F93989D9D9D9DC7 +:405080009D9D9D9D9D9D9D5184898E9D1146304600F09AF816E011463046FFF783FF70BD11463046FFF788FF70BD1146304600F0BFF870BD3046F7F769FE04E011463046D1 +:4050C0006A682EE00446204670BD11463046FFF787FBF7E711463046FFF75CFAF2E711463046FFF77FFAEDE711463046FFF7B0FAE8E711463046FFF79DFAE3E711463046A1 +:40510000FFF7D2FCDEE719E011463046FFF7F8FBD8E711463046FFF741FDD3E71146AA6830469047CEE740E011463046FFF79AF9C8E711463046FFF75BF9C3E7114630469F +:40514000FFF714FBBEE711463046FFF779FCB9E711463046FFF78AFAB4E711463046FFF7BBF9AFE711463046FFF74CFBAAE711463046FFF7D3FBA5E711463046FFF718FD2E +:40518000A0E711463046FFF74DFD9BE711463046FFF74CFC96E711463046FFF79FFE91E71146304600F01EF88CE7314600F01EFE88E70000AAFD000028020008A2FD0000C9 +:4051C0004AFD00009A03FFFF0188CA0701D012207047034A40888918086000207047000000103C40F8B5064600200090012008700D4669460C20FEF776FF002801D007203E +:40520000F8BD009C002209492046FEF763FC3078F2F75CFAA07105206070022028702146FF20FEF7D6F90020F8BD0000B4FD00000EB5017800914068019002AA69460420F3 +:40524000F0F758FA00200EBD38B505460020009069460520FEF747FF002801D0072038BD009C002207492046FEF734FC064821464576A57105206070FF20FEF7AAF9002013 +:4052800038BD0000C0FD00005C21000803480249416081607047000091450110280200080348024941600349816070478D49011028020008894C011070B50D4604460146AC +:4052C00010222846EFF715F92146284610310D221030EFF70EF9214628461D3104223930EFF707F92120225C214628466A7722311E30EFF7FEF870BD70B50D4604460146E8 +:4053000010222846EFF7F5F82146284610310D221030EFF7EEF8627F214628466A771E311E30EFF7E6F870BD70B50C46054601461022A018EFF7DDF829462046103110228E +:405340002030EFF7D6F82022A818C1780902216083781943090221604078014308022060A95C0843242120606818C2781202626083781A4312026260407802431002606057 +:40538000695C0843282160606818C2781202A26083781A431202A260407802431002A060695C08432C21A0606818C2781202E26083781A431202E260407802431002E0601D +:4053C000695C0843E06070BD10B5C27812020A6083781A4312020A6043781A4312020A6003781A430A6002790A75037A1B024B60C47923431B024B60827913431A024A6044 +:4054000043791A434A60037B1B028B60C47A23431B028B60827A13431A028A60437A1A438A60037C1B02CB60C47B23431B02CB60827B13431A02CA60437B1A43CA60037D09 +:405440001B020B61C47C23431B020B61827C13431A020A61407C02430A6110BD427812020A80007802430A80704770B50C460546014606222046EFF73CF8A879A07170BDFA +:40548000427812020A8003781A430A80C27812024A80807802434A80704702780A70407848707047427812020A8003781A430A80807888707047427812020A8003781A43B0 +:4054C0000A80C27812024A8083781A434A80427912028A8003791A438A80C2791202CA8083791A43CA80427A12020A81007A02430A817047007808707047427812020A8095 +:4055000003781A430A8080788870704702780A7042784A70C27812024A80807802434A807047007808707047C27812020A6083781A4312020A6043781A4312020A600378DE +:405540001A430A6000790871704702780A7040784870704700780870704710B50B460178401C197001460622581CEEF7C2FF10BD034610B5084608221946EEF7BAFF10BDDF +:40558000427812020A8003781A430A80C27812024A8083781A434A80427912028A8003791A438A80C2791202CA8083791A43CA80427A12020A81037A1A430A81C27A1202EF +:4055C0004A81837A1A434A81427B12028A81007B02438A81704770B5054640780C46000208802978062208432080E87800026080A978084360802879207168796071A91D6D +:40560000A01DEEF776FF287B2076A87B0002A081697B0843A081287C0002E081E97B0843E081A87C00022082697C08432082287D00026082E97C08436082A87D0002A0826F +:40564000697D0843A082287E0002E082E97D0843E08270BD7047427812020A8003781A430A8080788870704770B50D460446014610222846EEF73DFF214610221031A81811 +:40568000EEF737FF70BD034610B5084640221946EEF72FFF10BD427812020A80007802430A80704710B50B4641780A021A800178801C0A431A8001461022981CEEF719FFB4 +:4056C00010BD427812020A80007802430A807047427812020A80007802430A807047427812020A80007802430A8070477047427812020A80007802430A80704700780870DE +:405700007047427812020A80007802430A807047427812020A8003781A430A80807888707047007808707047427812020A80007802430A80704710B50B460178401C19708A +:4057400001460622581CEEF7D4FE10BD10B502780B460A701F2A03D8411C581CEEF7C9FE10BD00780870704770B5054640780C46000208802978062208432080E878000289 +:405780006080A978084360802879207168796071A879A071E91DE01DEEF7ABFE687B6073A87BA07370BD0022835C0B70521C491CD2B2082AF8D37047034610B508460522F3 +:4057C0001946EEF796FE10BD034610B5084606221946EEF78EFE10BD034610B5084606221946EEF786FE10BD02780A7040784870704702780A71827812020A8043781A430A +:405800000A80027912024A80C3781A434A8042794A7180798871704710B502780B460A701F2A03D8411C581CEEF763FE10BD70B5054640780C4600020880297808220843D8 +:405840002080A91C201DEEF754FEE87A102200026080A97A08436080294620460C310C30EEF747FE70BD02780A7042784A70807888707047427812020A8003781A430A801D +:40588000C27812024A80807802434A807047427812020A8003781A430A80C27812024A80807802434A80704702780A70027912024A60C3781A4312024A6083781A43120293 +:4058C0004A60407802434A60704710B504460088F2F774FB00280AD0A07815280FD008DC05280CD013280AD0142806D107E0022010BD1A2803D03B2801D0122010BD002028 +:4059000010BD012070470078012801D912207047002070470020704710B50446012008702088F2F74BFB002822D06188A08881421CD8114A891F914218D2511D884215D86A +:4059400021890D4B0A460A3A1B1F9A420ED2E288FF23F4339A4209D8521C4243C9005000814203D9A0896189884203D2122010BD022010BD002010BD7B0C00000020704795 +:4059800010B501220A700179037E0A46194303292FD8002A02D1417903292AD8018842888A4226D8154B091F994222D2042A20D38289C1898A421CD8114B921F9A4218D249 +:4059C0005A1D914215D8428A0D4C13460A3B241FA3420ED2038AFF24F434A34209D85B1C4B43D20059008A4203D9C18A808A814201D2122010BD002010BD0000FD3F00001C +:405A00007B0C0000002070470020704710B50088F2F7D4FA002801D0002010BD022010BD10B50088F2F7CAFA002801D0002010BD022010BD10B50088F2F7C0FA002801D0A0 +:405A4000002010BD022010BD10B501220A700088F2F7B4FA002801D0002010BD022010BD002070470078272801D912207047002070470078012801D9122070470020704781 +:405A800010B501790388428804291BD801290AD0934217D80124A403A24213D8202B11D3827B032A0ED8012901D0042902D18179032907D84179032904D8407B410701D0FA +:405AC000C00800D0122010BD00781F2801D9122070470020704741780A09817812011143C2780A430179114342790A438179C0791143084300D01220704701794A090AD1FA +:405B0000027843781A438378C07803431A430A4301D0002070471220704700207047017840780143012901D91220704700207047017901290FD8018842888A420BD8084B2F +:405B4000091F994207D2042A05D34179032902D88079032801D912207047002070470000FD3F000010B501220A700088F2F726FA002801D0002010BD022010BD00207047EA +:405B80000178272902D88078072801D9122070470020704710B50088F2F710FA002801D0002010BD022010BD0120704710B50088F2F704FA002801D0002010BD022010BD8B +:405BC00010B504460088F2F7F9F9002804D0A078012803D9122010BD022010BD002010BD0020704710B504460088F2F7E7F9002804D06088002803D0002010BD022010BD4D +:405C0000122010BDF8B50E460021054600910120307069460820FEF766FA002801D00720F8BD2868009C056800220A492046FDF751FFA571280AE071280C2072280E607286 +:405C400008206070022030702146FF20FDF7C1FC0020F8BD26FD000010B50020F1F7C2FC002010BDC27812020A6083781A4312020A6043781A4312020A6003781A430A605D +:405C800002790A71407948717047C27812020A6083781A4312020A6043781A4312020A6003781A430A60007908717047C27812020A6083781A4312020A6043781A431202FC +:405CC0000A60007802430A60704710B5C27812020A6083781A4312020A6043781A4312020A6003781A430A6002790A71182A01D918220A71002205E083188C185B79521CE2 +:405D00002372D2B20B799342F6D810BDC27812020A6083781A4312020A6043781A4312020A6003781A430A60C27912024A6083791A4312024A6043791A4312024A60007990 +:405D400002434A60704700003EB500200290012008700D4602A90820FEF7C5F9002801D007203EBD6846029CEFF7EAFA00220D492046FDF7AFFE68460078A0716846407819 +:405D8000E07168468088207268468078607208206070022028702146FF20FDF71AFC00203EBD00002FFD00000F4B00B5D2181300F4F79AFD0B070A0D090916101309070A2D +:405DC0000900FFF762FF00BDFFF77FFF00BDFFF749FF00BDFFF76AFF00BDFFF797FF00BD0078087000BD0000E002FFFF10B50C4601460F4B0020C9180B00F4F775FD0D0C2E +:405E00000D0C080C1717171717170C12170011462046FFF7F7FE10BD11462046FFF71CFF10BD11462046FFF78FFF10BD012010BDDD02FFFF70B5054600780C468872691CD4 +:405E40000622201DEEF755FB2046E91D10221B30EEF74FFB29462046173110220B30EEF748FB70BD704710B50B460178401C197001460622581CEEF73CFB10BD10B50B4684 +:405E80000178401C197001460622581CEEF731FB10BD704710B50B460178401C197001460622581CEEF725FB10BD007808707047427812020A80007802430A80704770B5C1 +:405EC000054600780C460870691C0622601CEEF710FBE879E07170BD7047002070470000F8B50D46114914781646411808D0104807460E37007D012908D002290BD10CE0C0 +:405F0000FAF7FEFA29198870641C03E02A19921C012305E0E4B23470F8BD2A19921C00233946FAF7C7FA6871A41DF3E7D6DFFFFFA02100080649401805D0012805D0022819 +:405F400003D00020704701207047062070470000D6DFFFFF10B50022F9F744FCC0B210BD10B5FAF7D3F810BD10B5FAF795FA10BD10B5FAF791FA10BD0020704710B5FAF7BE +:405F8000C5FA10BD10B5FAF7C1FC10BD10B5FAF7D5FC10BD10B5FAF7EFFC10BD10B500F025F810BD014A12681269104734020008014A1268D269104734020008014A126885 +:405FC000926A104734020008014A1268D26C104734020008014A1268926D104734020008014AD2685268104734020008807A012801D912207047002070470078012801D913 +:40600000122070470020704700207047002801D000207047122070470078012801D91220704700207047000000880449401E884201D312207047002070470000B8A10000EB +:406040000178012902D8C079012801D91220704700207047014A12681268104734020008014A12689269104734020008014A1268D26B104734020008014A1268126B10474E +:4060800034020008014A1268526A104734020008014A1268D268104734020008014A1268926C104734020008014A1268526D104734020008014AD2681268104734020008F3 +:4060C00004480349016004494160044981607047084F001034020008D95E0110DB5E011006480549016006494160064981600249C031C16070470000A84E00103402000828 +:40610000E15E0110355F0110014A12689268104734020008014A1268126A104734020008014A1268526C104734020008014A1268926B104734020008014A1268D26A104779 +:4061400034020008014A12685269104734020008014A1268126D104734020008014A1268D26D104734020008014AD268926810473402000870477047427812020A80037805 +:406180001A430A80C27812024A8083781A434A80427912028A80007902438A807047427812020A8003781A430A80C27812024A80807802434A8070470749401805D0012830 +:4061C00005D00D2805D0002070470220704704207047082070470000DEDFFFFF0020704770470000FEB50D4627491646147840180022002802D00C2844D115E06B461A71C1 +:4062000001A96846FBF75EFA6B461988281981701988A41C090AC170E0B25A8829188A705A88120ACA702BE069460A7202A96846FBF732FA6946898828198170694689884D +:40624000A41C090AC170E0B269462A18C98891706946C988801C090AD170C0B269462A180988917069460988801C090AD170C0B2694649882A18917069464988090AD17027 +:40628000801CC4B23470FEBDDDDFFFFF38B504460020009069460F20FDF725FF002801D0072038BD00993E200870072088702078C8702088000A0871A07848716088000A75 +:4062C00088712079C871A088000A0872A0794872E088000A8872207AC8722089000A08730B2048700720FDF774F938BD10B5FBF7D3F910BD10B5FBF7E5F910BD10B5FBF71D +:40630000F1F910BD10B5FBF713FA10BD014A1268926A104744020008014A12681269104744020008014A12685268104744020008014A1268D269104744020008002801D008 +:406340000020704712207047002801D0002070471220704710B504460088F1F72FFE002816D0618808461B38E1280FD2A0880A4A90420BD8FF224932904207D3074A126B2F +:406380009388994202D8D188884203D9122010BD022010BD002010BD480800005C21000810B50021002815D0028813461B3BE12B0FD24088084B98420BD8FF2349339842F5 +:4063C00007D3064B1B6B9C88A24202D8DA88904200D91221084610BD480800005C210008014A1268526A104744020008014A1268D268104744020008014A1268126810477A +:4064000044020008014A1268926910474402000804480349016004494160044981607047804F001044020008E1610110DD6101100448034901600449416004498160704742 +:40644000B04F001044020008E5610110B9610110014A1268D26A104744020008014A12685269104744020008014A12689268104744020008014A1268126A10474402000828 +:4064800002780A7042784A7080788870704702780A7042784A7082788A70C078C8707047427812020A80007802430A80704702780A7042784A708078887070474278120217 +:4064C0000A8003781A430A8082788A70C278CA7002790A7182791202CA8040790243CA8070470000014A1268926A104750020008014A1268526B104750020008014A126890 +:406500005268104750020008014A12681269104750020008014A1268D2691047500200080178272907D84178012901D0022902D18078012801D912207047002070470178C0 +:40654000272907D8C178012901D0022902D18078072801D9122070470020704710B50088F1F72CFD002801D0002010BD022010BD017803290FD84278032A0CD8807803284C +:4065800009D8CB0701D1002A05D0890701D4002801D0002070471220704710B504460088F1F70CFD00280BD0A078032812D8E17803290FD82279032A0CD8C30702D003E0EA +:4065C000022010BD002905D0800701D4002A01D0002010BD122010BD014A1268526A104750020008014A1268126B104750020008014A12681268104750020008014A126891 +:40660000D268104750020008014A1268926910475002000804480349016004494160044981607047E04F00105002000835660110D166011000207047044803490160044988 +:4066400041600449816070471C50001050020008596601108D27011038B504460020009069460A20FDF73FFD002801D0072038BD00993E2008700C208870A078C8702078A9 +:4066800008712088000A4871E07888712079C871062048700C20FCF79CFF38BD014A1268D26A104750020008014A1268926B10475002000800207047014A12685269104773 +:4066C00050020008014A1268126A1047500200080020704710B50B48017A01290ED0C17A00290CD001210172407A064BC000C03BC1184A884968185CEEF7CEFE10BD0021D2 +:40670000017210BD7027000870B503461448C47A192C0BD3022B05D0042B02D10846FDF7E9FC70BD0846FDF71BFD70BD847AE5000B4CC03C6355837ADB001B195960817AC2 +:40674000C90009194A80C17A491CC172817A491CC9B281721929E8D30021817270BD00007027000810B50F4CE17A002918D0617A2246C900C03A515C022904D0042904D1A6 +:40678000FDF7B8FC01E0FDF7EBFCE07A401EE072607A401CC0B26072192801D30020607210BD000070270008F7B5A14C84B02046E030039009380090401E0E46C0340190A0 +:4067C000E07B354601281CD0A07B012836D0A18A4A19082A02D90822511A8DB2002D0CD0002833D0A18A206A4018401E2A460499EDF77FFEA08A4019A082207C012829D085 +:406800002FE0A08A618A42198A4204D280B28019A08207B0F0BD081A0021A18280B26182E173002807D004992A1A091815460498EDF75FFEAEB2002EC2D1EAE7618AA28AD5 +:40684000891A8DB2B542C9D93546C7E7A18A01980818CBE700F068F90028DAD000202074E073608A002802D0A18A8142D1D3A08A0028CED000200290A07D01280CD0022850 +:4068800065D00220FCF7B6FE012020740021E173A1736182A1821DE0A08A03281CD9A07B002824D100270098F0F704F9002801D10420A0823A460120039900F00EF90128D7 +:4068C0000BD00420FCF796FE012020740021A173A1826182FCF78EFE9EE00120A073A28A012A04D9521E206A0099EDF702FE216A8F78381D6082502F10D9487802020878D1 +:40690000012110430022FCF755FEA07B012802D1216A00F0F8F80020A07331E0A28A82427AD3121A1206120EA28206D00918491E0198EDF7DEFD01200290FA1C216A0120C4 +:40694000069B00F079F80020A073608260E0A08A052861D33648D130C1798279080210430205A07B120D002815D10220039900F0B4F8012807D00520FCF73CFE009820620F +:406980000120E07348E00120A073A28A206A521E0099EDF7AEFD216A264AC8788F7800020743781D80B26082127DBA4213D20820FCF720FE012020740027A7826782E77391 +:4069C000FCF718FEA07B012803D10220216A00F09AF8A77320E0A28A82421DD3121A1206120EA28206D00918491E0198EDF781FD01200290E07B002806D13F1DBAB2216A0C +:406A00000220069B00F018F80020A0736082E0730298012800D12DE7B54200D3F9E60498721B16464119EDF764FDB6B2C8E60000B0260008AC1E00083EB5044600200D4640 +:406A4000009001900290012C14D0022C11D108206946088100954A81002B69460EC90BD0002000F0E7FC002803D02946204600F04AF83EBD1220EBE7002000F020FDF2E7FC +:406A800070B5047800250E2C03D10179C57809020D43FFF767FE0E2C02D12846FDF78CFC024800210172FFF715FE70BD7027000810B5FFF729FEFFF70DFE10BDF8B5154633 +:406AC00007465C1B2046069EEDF713FDA81982B221463846FFF7ECFFF8BD10B50B46012802D002280BD103E0084600F013FB03E01146184600F066FB0006000E01D0002030 +:406B000010BD012010BD10B5012805D0022802D1084600F0E1FB10BD084600F095FB10BD10B5FCF767FD10BDFCB514A00068009013A0144E0068019031460020C0316C46CA +:406B4000012711E03318C0339A7D255CAA4209D001AD2D5CAA4205D000228A829A7D012A00D18F82401C80B28A8A8242EAD890B2042801D00020FCBD0120FCBD01030C00ED +:406B800001091000B026000808B50B46C17882780902891889B20091014604220220FFF78DFF002008BD3EB54178002217236C46029223810090891C61810120029B0099CE +:406BC00000F07DFC00203EBD06480021017241728172C17201748182016241828173C1737047000070270008002210B511461046FCF7E0FC10BD0EB50021019102911921C7 +:406C00006B461981009001205881002A69460EC902D000F00FFC0EBD012000F050FC0EBD10B5FFF7D1FF034B034A04490448EEF721FC10BDF76B0110A9670110396A011039 +:406C4000E96B011010B50189032913D0172907D018290BD0192902D10068FFF711FF10BD428901680420FFF723FF10BD0068FDF745FA10BD03C800F015F810BD3EB500227F +:406C800003236C460292238101910090628169460EC9012000F0CEFB002801D000203EBD01203EBD10B5052802D10020EFF78AFD10BDF8B50E460546F8F7C6FB0023009061 +:406CC0006C46AB20E15C002900D1E0545B1CDBB2042BF7D32A463146204600F001F8F8BDF7B58AB03A480890001D054606900898019038480F460168069800910291039002 +:406D0000012600241835042233A10898EDF7F1FB0099069880310A7902704979417006980422801C0A99EDF7E4FB8E206946087530460899303048702819049001A800F0C4 +:406D40004FF8002021186A5C002A01D130226A54401CC0B21428F5D31434761CF6B2E4B2032EE5D9281D029000200390019568460475174E0024082F1DD9082730190490BF +:406D800001A800F02DF8002030222118735C002B00D17254401CC0B21428F6D36946097D3120685469461434087DE4B2401CC0B2087500212954BC42E0D3002004E00C996F +:406DC000325C0A54401CC0B2B842F8D30DB0F0BD942700085C0200083030303000000000F0B5BD4E07463446C56885B04034BB482060BB486060B948C043A060B848C04327 +:406E0000E060B8482061387C362801D8402104E0762801D8802100E0C021019104280AD23968042208180021EDF76CFB3A7C3968802088541CE088280DD279680422081816 +:406E4000001F0021EDF75EFB3A7C796880208918203908770CE0B9680422081888380021EDF750FB3A7CB96880208918A039087600200090387C694640098870387CC0004B +:406E8000C8700198800903900020D2E00020844602988001864660467146800009183A7CC9B28A421AD3042901D23A6806E0882902D2091F7A6801E0BA68883951180A7894 +:406EC000120232504B781A43120232508B781A4312023250C9780A43325016E0019A083A8A4201DB00210FE06A4611780902315052781143090231506A469278114309022D +:406F000031506A46D278114331506046401CC0B284461028BFD32068286060686860A068A860E068E86020692861002084460007000F86466046102817D37046C01E000778 +:406F4000800E3158704608300007800E305841407046801C0007800E32587046800033585A4051401F22D14131506046142809D26968AA6808461040EA688A431043E0614C +:406F800059481EE0282807D2A96868684840E9684840E061554814E03C280BD2A868EA680346696810430840194611400843E0614F4806E0A96868684840E9684840E06161 +:406FC0004C48A061E0692969A269411828681B23D8411018091870468000305808186061E8682861A868E86068680221C841A86028686860606928606046401CC0B28446D2 +:40700000502894D320682968401820606068696840186060A068A9684018A060E068E9684018E06020692969401820610298401CC0B203990290884200D227E7F968207800 +:40704000C8702088F968000A88702068F968000C48702068F968000E0870F9682079C871A088F968000A88716068F968000C48716068F968000E0871F968207AC872208976 +:40708000F968000A8872A068F968000C4872A068F968000E0872F968207BC873A089F968000A8873E068F968000C4873E068F968000E0873F968207CC874208AF968000A95 +:4070C00088742069F968000C48742069F968000E087405B0F0BD0000F02700080123456789ABCDEFF0E1D2C39979825AA1EBD96EDCBC1B8FD6C162CA30B500224B1E4C083D +:4071000005E0815CC55C8554C1545B1E521C9442F7DC30BD10B5044608484068EFF75CF92060002807D00649087B002801D0401E0873002010BD034810BD0000600200082D +:40714000A0210008FFFF000070B50A4D0446302905D8E868EFF740F92060002805D1A868EFF73AF92060002801D0002070BD024870BD000060020008FFFF000010B5044682 +:4071800005480068EFF728F92060002801D0002010BD024810BD000060020008FFFF000010B50446880005490858EFF715F92060002801D0002010BD014810BD70280008D9 +:4071C000FFFF000010B504460846F0F71FFF064980000858EFF700F92060002801D0002010BD024810BD000050280008FFFF000010B50446880005490858EFF7EDF8206096 +:40720000002801D0002010BD014810BD60280008FFFF000010B50446880005490858EFF7DBF82060002801D0002010BD014810BD80280008FFFF000010B5FCF711F9FCF7E7 +:4072400071F8002010BD0000014610B509484068EFF752F9002801D0074810BD0749087B401CC0B20873042801D904200873002010BD000060020008FFFF0000A02100088E +:4072800070B5084C05460146E068EFF735F9002806D02946A068EFF72FF9002800D0024870BD000060020008FFFF0000014610B502480068EFF720F910BD00006002000819 +:4072C0000246880010B5034908581146EFF714F910BD00007028000810B504464078217800020843F0F792FE0349800008582146EFF702F910BD00005028000802468800E1 +:4073000010B5034908581146EFF7F6F810BD0000602800080246880010B5034908581146EFF7EAF810BD000080280008F8B5040076D03C4E20783075A078F07520797075BE +:407340006079B0753546A07B20352870EBF740FBC0B2022801D0032805D1707D042802D12079401E707500242EE081070DD08107890F401A0C3082B22B48A700717D381860 +:40738000EFF750F800284BD101E00830F3E726482022103038180221EFF744F800283FD121482022203038180221EFF73BF8002836D11D484022303038180221EFF732F84B +:4073C00000282DD1641CE4B22878A042307DCCD881070BD08107890F401A0C3082B2B17D1248EFF71FF800281AD101E00830F5E70E4850220421001DEFF714F800280FD1A0 +:407400000A48482201210830EFF70CF8002807D10648302208210C30EFF704F8002800D00348F8BDAC1E00085028000860020008FFFF00001FB50446EBF770FA01A9204639 +:40744000FBF76AFF0446EBF753FA204604B010BDF8B5154CA068EFF7FDF8E068EFF7FAF86068EFF7F7F82068EFF7F4F800240F4F0F4E14E0A5007859EFF7ECF80B481030A3 +:407480004059EFF7E7F8094820304059EFF7E2F8064830304059EFF7DDF8641CE4B23078A042E7D80020F8BD6002000850280008CC1E000810B5FBF743FF002010BD1FB5A8 +:4074C0000446EBF72BFA01A92046FBF769FF0446EBF70EFA204604B010BDF8B5054600202870F02316466B800246034607E00C245C439F0064187F195B1CDBB27C60B342DD +:40750000F5D3344604E0A1004919641CE4B24A60052CF8D3002408E022460121284600F007F8002803D1641CE4B2B442F4D3F8BD70B50B460546002411461846FAF70CFE5A +:40754000FF2810D0800040194268FF2111704268002151704268917042681181426851814068416000E0014C204670BD0100160010B50C4B89001C7800220818002C01D059 +:4075800041680A8144686189002901D0491E618140688178002902D0491E817000E042701A7010BD70020008F0B500230746FF209C461C461E4D1A4621E0CE071CD09E00C4 +:4075C000F6197668B6467678A64201D934461846002C11D176463678AE420DD8AE4208D105460120A840104301229A400243D2B200E00022184635465B1CDBB2490800293E +:40760000DBD1002C10D1002A0ED0D30708D08B00DB195B681B89634502D3D8B284460846491CC9B25208F0D1024A01211170F0BDFFFF00007002000803460020052906D254 +:40764000002B04D08900C91849680A70704701487047000001001600034610B5002005290ED2002B0CD08900C9184B685C78944208D25A70802A02D1496806228A7010BDDD +:40768000024810BD0148FE3010BD0000010016000246890089184A68002053891B1D53814A6813895B1C138149684A68521C4A6070470000F7B5054682B000205249534A20 +:4076C00000900427681AAE188D421BD00ADC002E1AD04E2E1AD04F2E18D0F5208000301A15D10DE001280BD0032807D0072803D0474940180BD107E00A2708E00B2706E06E +:407700000C2704E0442702E0072700E006276946381DFCF7E8FC002802D0072005B0F0BD009C294667702046039AFCF7D3F90398002864D1344B2A465B1CE81A049F049D04 +:4077400034493F0AEDB29A4238D008DC002E23D0F5208000301A3CD0012850D14CE002280BD0062804D02A49491C401847D11BE0A11D0020F3F784FB41E0087DA071000A08 +:40778000E071087D2072487D6072000AA072487D21460931E0722CE0214608310498EFF76DFD06E060712AE0214608310498EFF751FDA571E771002821D0F3E7251DA01DCD +:4077C00008220021ECF79EFEA87960210843A87115E00879A0710889E071000A2072487960720888A072000AE072C88821460A312073000AC87002E0A01DFCF7B7F92146B3 +:40780000FF20FBF7E6FE89E702100000D3F3FFFFFDFBFFFFAC1E000830B51E4B0224C21A984235D015DC1C4B0325C21A984225D008DC1A4A801826D0172826D0184A8018E6 +:407840001AD11DE02A2A1ED0602A19D0782A13D11BE0144BD01A9A4210D007DC124810180CD001280AD0022806D107E0042805D001229202801A08D0002030BD002000E082 +:407880000820087002E00D7000E00C70012030BD0420F6E77C0C0000030C0000FAFBFFFF05F8FFFF890300007BFCFFFF10B5224C131BA2423CD016DC204C131BA24228D01F +:4078C00008DC1F4BD2182DD0172A2ED01D4BD21808D121E02A2B22D0602B1DD0782B01D1FDF7EFFE10BD184C1A1BA34211D007DC164A9A180DD0012A0BD0022AF2D108E0F8 +:40790000042A06D001239B02D21AEBD1FDF7F9FE10BDFDF79FFE10BDFDF72AFE10BDFDF7F7FE10BDFDF797FE10BDFDF7FDFE10BDFDF7A0FF10BD00007C0C0000030C00001C +:40794000FAFBFFFF05F8FFFF890300007BFCFFFF70B50C460146304E01208B1B0546B1424ED01DDC2D4E8B1BB14238D00CDC2C4BC91839D017293DD02A4BC91803D111468D +:40798000204600F055F870BD2A2B23D0602B3DD0782BF8D115701146204600F091F870BD214D591BAB4213D007DC204959180FD001290DD00229F2D10AE0042908D001236D +:4079C0009B02C91AEBD11146204600F088F870BD002070BD1146204600F085F870BD1146204600F088F870BD15701146204600F05BF870BD15701146204600F078F870BD72 +:407A000015701146204600F082F870BD1146204600F036F870BD00007C0C0000030C0000FAFBFFFF05F8FFFF890300007BFCFFFF10B5104B0422597A3024114059720E4AFE +:407A40000168114001600D4A416811404160026850080843810A2140C00D422420400143587A120989242240104301435972002010BD0000A021000890880002008000205B +:407A8000084AFB23517A1940517201230168DB0519400160507A490D042319400843507200207047A021000870B50C460546FDF70CFF002803D121462846F1F7E1FD70BD76 +:407AC00070B50C460021217005462146FEF762F8002803D121462846F1F700FF70BD10B5FEF764F810BD10B5FEF76AF810BD10B5F1F740FF10BD70B50C460546FEF770F8D3 +:407B0000002803D121462846EFF76CFD70BD70B50C460021217005462146FEF763F8002803D121462846F2F7A3F870BD10B5F0F74FF910BD10B5F0F7B7F910BD10B5F0F7B5 +:407B400051F910BD10B5F0F7F9F910BD7047000010B50C460088044948430449EAF7D8FFBD21081A208010BD4B2800001027000010B50C460088AE214843034940180A2171 +:407B8000EBF7B0F8208010BD91FCFFFF70B5094C054621780648002909D1074A0321074800F0C2F9002802D102212170656070BD02001600740200086D7D011004080000E7 +:407BC00070B50A4C05462178074800290AD10F21074A0902074800F041FA002802D101212170656070BD00000200160074020008A17C01103B08000001484078704700006E +:407C000074020008F8B506461920694608702020487001248C700220C8706846EAF704FB002805D01449884202D013481230F8BD022000F0FFF8114F2F253D630A20EAF7BC +:407C400053FE304600F08EFC0D4E304600F018F9802188430146304600F026F900F076FC00F040FA3D6307488460012000F0D8F900F07EF9F8BD00000300160040F03D4096 +:407C80000E1E000040003C4010B5EAF76DFA10BD10B5400701D500F08BF910BD7047000010B5034A0321034800F03EF910BD0000B97C01100408000010B5034A08210348DB +:407CC00000F01CF910BD0000D17C01100608000010B5034A0821034800F026F910BD0000E97C01100608000010B5034A0721034800F01AF910BD0000017D01103C08000038 +:407D000010B5034A0221034800F0A8F910BD0000197D01103A08000010B50249024800F063F910BD2D7D01101B0A000010B5C80704D00549054800F057F910BD00210846AA +:407D4000FFF7EAFF10BD0000517D01101A0A000010B5054CC9B26268002A01D00020904700206060207010BD7402000810B5034A0821034800F0C2F810BD0000857D01103C +:407D80000608000010B5034A0821034800F0CCF810BD00009D7D011006080000032110B58902034B0A46034800F090F810BD0000B97D01103D08000010B5034A01210348C8 +:407DC00000F04CF910BD0000D17D01103A08000010B50249024800F007F910BDE57D01101B0A000010B5880704D50549054800F0FBF810BD00210846FFF7DEFF10BD0000AA +:407E0000097E01101A0A000010B5054C090A6268002A01D00120904700206060207010BD7402000802480168490049080160704700003C4070B50446002500F091F80128CE +:407E400002D1002000F0ECF80B4A11680B48012301433F20400381431B039943012C08D960033F24640300194003400B0843184301461160284670BD00003C40040A00806D +:407E80000121C9030843074A0004D061054840300168C907FCD00168012319430160D06A80B2704700003C404004400808430649C861054840300168C907FCD001680122BB +:407EC000114301607047000000003C4070B5094C054626780648002E08D1032020706360218162810449284600F07EF870BD00000200160090280008A980011030B5084B4F +:407F000004461D780548002D07D1022018705A6059810449204600F067F830BD0200160090280008A980011010B5074B1C78002C01D0064810BD01241C705A60598104497C +:407F400000F052F810BD00009028000802001600A980011001490120087070477C02000802480068C007C00F7047000000013C4000B50023FFF7F4FF012801D0084B0CE052 +:407F800008490C20086188610748012101700021064A4160116051609160184600BD00000200160000013C407C020008902800080A48C16901610A480A0701D5416802E053 +:407FC0004A0700D50168074A0123137088B25268090C002A00D010477047000000013C4040013C407C02000810B50A4A034614780020012C01D0084810BD022414705160A5 +:4080000006494B60054A403A116808231943116010BD00007C0200080200160040013C400D490A68D207D20F824205D001220028086802D0104308607047022318430860E2 +:408040000868C007FCD10869104308610248C038016811430160704700013C4010B50A4B090401431C780020012C01D0074810BD02241C705A60064A1160054940390A689C +:4080800004231A430A6010BD7C0200080200160040013C4003480078012801D001207047002070477C020008F0B50D4C012622465389277800259E405268012F0AD0022FB8 +:4080C0000BD0032F05D12689B1431943FFF7C6FF2570F0BD0E43B1B2F8E7B143F6E700009028000810B517493820886116484860144A1648C03210611648154A4260174B31 +:40810000154A9A61164A0260144B164A803B9A63154A13680124640223431360134A022313630269082492B222430424CC601A4319030A4381158A4341210A43026100F0B7 +:4081400017F810BDC0103C4037D70000308A000058480000001E3C40FF0F000040123C400524000020FF000040503D40C0F03D4070B51849002548681C2210434860154886 +:408180004038416A826AC9B2D2B2C06A51180002000E4018001DC10700D0401C01264408B6020A2C12D90A212046EAF7B1FCC0B2072800D907200A214143A14204D2611AB6 +:4081C000CDB21F2D00D31F2544012C4302483443846370BDC0F03D4080103C4010B5FFF7BFFE012802D10020FFF71AFF044C2046FFF746FE8104890C2046FFF755FE10BDB2 +:40820000021E00000248416B022291434163704740F03D400248416B022211434163704740F03D40014909680180704780F03D4010B50C4C2F202063FFF754FF9A20E0629E +:40824000FFF78EFE002809D107480068002802DB0220FFF7EFFD0120FFF7E2FEFFF788FE10BD000040F03D4000003C40F0B58C4600881749884202D11648006880B28104D8 +:408280000C0D0004800F10D0012810D0862600202F230246262C10D30F4FD018400841007D5AA54205D140B207E05726EFE77026EDE7991A012905DC50B22030801B614643 +:4082C0000870F0BDA54201D20246E6E70346E4E7FFFF000080F03D40E05000100449002802D0012008567047002008567047000084020008F1B51B4FFD6A1A484030406B17 +:40830000C0072DD0386BC0072AD0FFF7C3FE012826D0102128468843F86200211248FFF763FE124C20690007FCD5104840304068060C08206061FFF70DFE0320400386434F +:40834000009800224003304381B20748FFF786FE20694007FCD504206061FFF7FBFDFD62F8BD000040F03D400F1E000000013C40F8B52449496BC90743D022494039096BA9 +:40838000C9073ED04178002912D01F4D1F492C1D002282560527FF43931D0026BA4214D00CDC0E331ED0042B17D0082B0AD10FE0154D1649083D2C1D491EE9E7002A01D035 +:4083C000042A14D00E70042714E00F70032711E00B22D2430A7002270CE00F22D2430A70012707E01322D2430A70002702E004220A70052700214156084600F01BF82F6063 +:408400002660F8BD80F03D40B8113C408502000810B5FFF7A5FD012802D10020FFF700FE03492F2008630220FFF704FD10BD000040F03D40F8B5314C0646E56AFFF72AFE57 +:40844000012859D01021284688432146C8622B484030006A2A4C2B4F00072BD52A48A178042E02D0042913D043E0042941D0A188802291430722120211430022FFF7EEFD38 +:4084800038694007FCD504207861FFF763FD1CE0A1880F22D20191430322520289180022FFF7DCFD38694007FCD504207861FFF751FD0FE0A078042E02D0042807D018E0A8 +:4084C000042816D00720EAF78DFAB02103E00320EAF788FA98210C4800220930FFF7BEFD38694007FCD50420786104498862FFF731FD0248A670C562F8BD000040F03D408E +:408500008402000800013C40071E000070B5084980200860074C0025E562FFF779FFFFF75DFE262020636563FFF77CFC70BD000000103C4040F03D4010B503490020C8624F +:40854000E9F766FE10BD000040F03D4010B50348FFF796FC0249888010BD0000071E00008402000810B5044600F0D4FC204600F035F900F015F80849012000F0E5FB074CED +:40858000FF214131204601F025F865218901204601F020F810BD000088090000021E0000F8B5002469462046009400F0F9FF00980321C008C000084381B20090002001F0F3 +:4085C00009F80126760269463046009400F0E8FF009902200143009189B2304600F0FAFF4C494D4800F0F6FF4B4D6946ED1E2846009400F0D5FF3F210098C9018843FF214D +:408600008131084381B20090284600F0E3FF424F6946843F3846009400F0C2FF00980125284381B20090384600F0D4FF3A486946801F009400F0B4FF03210098890288432E +:4086400081B200903448801F00F0C4FF6946B81C009400F0A5FF0098A84381B20090B81C00F0B8FF6946B81C009400F099FF0098284381B20090B81C00F0ACFF2648012199 +:40868000001F00F0A7FF00946946244800F088FF0098C007F8D0FF200021013000F09AFF1D480021813800F095FF69463046009400F076FF00980221884381B2009030461E +:4086C00000F088FF69460020009400F069FF00980721C008C000084381B20090002000F079FF0F4E45218901304600F073FF65218901304600F06EFF69463846009400F0B1 +:408700004FFF009938462943009189B200F062FFF8BD0000665E000088080000110A0000021E000038B50B21002000F053FF012464020721204600F04DFF1421224800F0A8 +:4087400049FF214D2049AD1C0939284600F042FFE91F284600F03EFF1B481C49483000F039FF19480121343000F034FF164801213D3000F02FFF21200121800100F02AFF13 +:40878000114813494A3000F025FF0021114D00916946284600F004FF00994907F8D50021204600F017FF0F21002000F013FF0A4C45218901204600F00DFF652189012046A3 +:4087C00000F008FF38BD00000408000042020000BD6E0000110A0000021E0000F1B58AB00A98012842D110216846E9F737FF00283CD168460088A249884237D16A46518873 +:4088000048409188D288514048406A46118948405189484091894840D189814226D1FFF781FF68464188974800F0D4FE684681889448401E00F0CEFE6846C1889148801E91 +:4088400000F0C8FE684601898E48C01E00F0C2FE684641898B48001F00F0BCFE684681898320400100F0B6FE0BB0F0BD8648069086480990EAF734F8012810D04120C001E7 +:408880000790834869465A380882012065244002E4014882401088827D4D662015E0EAF721F8002803D07A4D7A4C2D1D02E0F925794CED0079480790794869460882FF2062 +:4088C000C3304882C82088827020C8827548066A00273007002811DA08A97348089700F05FFE0F210898C901884307210902084381B208906C4800F06DFE02E00720EAF752 +:4089000071F8694808A90930089700F049FE0898782188433821084381B208906248093000F058FEC820E9F7DFFF2946204600F0EBFC544D6C466D1EA11C284600F030FE48 +:4089400068464088810602D1401C69464880E9F7C9FF002808D16846408880090A2803D98320800069464880300712D54E4E08A93046089700F014FE0F210898C90188431D +:4089800003214902084381B20890304600F022FE02E00320EAF726F8434E08A909363046089700F0FDFD0898782188431821084381B20890304600F00DFEC820E9F794FF09 +:4089C0000699079800F0A0FC211D284600F0E8FD68468288900602D1521C6846828004A8099900F063F8A11D264C204600F0D8FD02A9284600F0D4FD02A9A61E0231304607 +:408A000000F0CEFDE71E03A9384600F0C9FD68464188204600F0DEFD68468188284600F0D9FD6846C188304600F0D4FD68460189384600F0CFFD68464189201F00F0CAFDF5 +:408A400068468189601F00F0C5FD0A98012800D00AE70B486A461080518848409188D288514048406A46118948405189484091894840D08110216846E9F720FFF4E6000022 +:408A800082030000651000008202000082040000C6070000D4300000952E0000841C0000DC05000080F03D40071E0000F3B581B00024054669462046009400F071FD0098A4 +:408AC0000321C008C000084381B20090002000F081FD012069464002009400F061FD00980721C008C000084381B200900120400200F070FD834F69463846009400F050FD54 +:408B000000980126304381B20090384600F062FD69463846009400F043FD00980221084381B20090384600F055FD69463846009400F036FD00980421084381B200903846CC +:408B400000F048FD69463846009400F029FD00981021084381B20090384600F03BFD6946B81C009400F01CFD00980627B84381B200906448801C00F02DFD62486946801C72 +:408B8000009400F00DFD0098B843384381B200905C48801C00F01EFD5A4F694648373846009400F0FDFC00980221084381B20090384600F00FFD69463846009400F0F0FC59 +:408BC00000984021084381B20090384600F002FD69463846009400F0E3FC00987102084381B20090384600F0F5FC464F694634373846009400F0D4FC0098304381B20090AA +:408C0000384600F0E7FC3F4F69463D373846009400F0C6FC0098304381B20090384600F0D9FC7F1E69463846009400F0B9FC0098304381B20090384600F0CCFC3148FF21BD +:408C4000CA31623000F0C6FC2E480299643000F0C1FC2C4829885D3000F0BCFC294869885E3000F0B7FC2748A9885F3000F0B2FC2448E988603000F0ADFC224822494A3054 +:408C800000F0A8FC214D00946946284600F088FC00994907F8D51B480221633000F09AFC00946946284600F07BFC00998907F8D501256D0269462846009400F071FC0098EF +:408CC000C108C900009189B2284600F083FC69460020009400F064FC00980721C008C000084381B20090002000F074FC084C45218901204600F06EFC65218901204600F046 +:408D000069FCFEBD04080000BD6E0000110A0000021E000010B50A4A02280AD0012807D1084808188001C01C81B2104600F052FC10BD7D200001081A80013D30F4E7000099 +:408D40004E0800002FF8FFFFF3B5002583B000287DD0FF240026163401A92046019600F01FFC0198022180088000084381B20190204600F02FFC614F01A93846019600F00B +:408D80000FFC032101980903884381B20190384600F020FC01A92046019600F001FC0198302188431021084381B20190204600F011FC534E002402200499FFF7ABFF002096 +:408DC000019001A9304600F0EBFB01984006F8D54B486946083000F0E3FB68460088641C2D180A2CE7D3E9F77BFD07006AD00A212846E9F78DFE6946088068460188FF20E3 +:408E0000143000F0E7FB0020FF241634019001A9204600F0C5FB019830218843084381B20190204600F0D6FB00252C4602200499FFF770FF0020019001A9304600F0B0FB2C +:408E400001984006F8D52E486946083000E037E000F0A6FB68460088641C2D180A2CE5D3002F3DD00A212846E9F752FE6946088068460188FF20153000F0ACFBFF240025C2 +:408E8000163401A92046019500F08AFB019902208143019189B2204600F09CFB01A92046019500F07DFB019930208143019189B2204600F08FFB65218901124800F08AFBCB +:408EC00005B0F0BD2846EBF757F90F4A0F4BEAF74FFB00220E4BEAF735F8E9F755FF8AE72846EBF749F9084A084BEAF741FB0022074BEAF727F8E9F747FFB7E703020000D3 +:408F00001D0A0000021E00009A9999999999244000005940F8B5E9F7E3FCE94D0746002469462846009400F03BFB03210098890388430121C903084381B20090284600F0FF +:408F400049FB6E1C69463046009400F029FB032500986D03A843284381B20090304600F039FB69463046009400F01AFB00981C2188430421084381B20090304600F02AFB57 +:408F800069463046009400F00BFB0098022180088000084381B20090304600F01BFBC84E694609363046009400F0FAFA0098A84381B20090304600F00DFBB021701C00F0C2 +:408FC00009FBBF4865218901001F00F003FBFF25173569462846009400F0E2FA00981021084381B20090284600F0F4FAB54DFF202946313000F0EEFAFF202946323000F090 +:40900000E9FAFF208021333000F0E4FAB1218900012000F0DFFAAC49052000F0DBFA8125ED00AA4E002F7DD0C1218900022000F0D1FA3146032000F0CDFA3C210B2000F020 +:40904000C9FA2946072000F0C5FAA0490820FF3900F0C0FA39210C2000F0BCFA00210A2000F0B8FA40210D2000F0B4FAFF207021133000F0AFFAFF262D211636C901304625 +:4090800000F0A8FAFF27FF2134370902384600F0A1FA8F498F4800F09DFA8E488E49401C00F098FA8B488D49801C00F093FA272181200901800000F08DFA41208849C000FA +:4090C00000F088FA83488749001D00F083FAFF25804801352946401D00F07CFA03203A21400200F077FA78497F480E3100F072FA7D487E49401C00F06DFA7B480621801C7C +:4091000000F068FA78480321401D00F063FA61207749000100F05EFA7348FF21103000F059FA00E0B5E07048C821083000F052FA6D480121093000F04DFA6B483C21113045 +:4091400000F048FA684801210C3000F043FA664868490D3000F03EFA634867490E3000F039FA41206946C000009400F019FA0721009889028843E900084381B2009041202D +:40918000C00000F027FA5D49384600F023FA69463046009400F004FA0F21009809028843084381B20090304600F014FA0421880200F010FA1021524800F00CFA50480E21B5 +:4091C000401C00F007FA4E4840210F3000F002FA4B488021103000F0FDF949488621113000F0F8F93B486946401C009400F0D8F90098382188432021084381B200903548E1 +:40920000401C00F0E7F9812069468000009400F0C7F903210098090388436901084381B200908120800000F0D5F9812069468000009400F0B5F903210098890288430843A5 +:4092400081B200908120800000F0C4F921486946001D009400F0A4F90721009809028843284381B200901B48001D00F0B3F919486946001D009400F093F900980121000927 +:409280000001084381B200901248001D00F0A2F9F8BD2946022000F09DF93146032000F099F93B210B2000F095F90E4907200A3900F090F91349082000F08CF93321CAE679 +:4092C000061E0000808000000DB00000013E000030480000010200009426000043430000D4D20000190800000106000036790000FF0D00008CC800004698000034CA0000DA +:4093000001100000023A0000F3B581B0002469462046009400F044F900980321C008C000084381B20090002000F054F901277F0269463846009400F033F900980625C0084D +:40934000C000284381B20090384600F043F969468E48009400F024F900980126304381B200908A4800F036F969468848009400F017F900980221084381B20090834800F0B2 +:4093800029F969468148009400F00AF900980421084381B200907D4800F01CF969467B48009400F0FDF800981021084381B20090764800F00FF975486946801C009400F0F3 +:4093C000EFF80098A84381B200907048801C00F001F96E486946801C009400F0E1F80098A843284381B200906848801C00F0F2F8664D694648352846009400F0D1F800989B +:409400000221084381B20090284600F0E3F869462846009400F0C4F800984021084381B20090284600F0D6F869462846009400F0B7F80098384381B20090284600F0CAF8EC +:40944000BD1D69462846009400F0AAF80098304381B20090284600F0BDF84C48632149017E3000F0B7F849480521343000F0B2F8474E69463046009400F092F80098032106 +:4094800080088000084381B20090304600F0A2F83E484049623000F09DF83C480299643000F098F8394801995E3000F093F8374800215D3000F08EF8344800215F3000F05A +:4094C00089F832480021603000F084F82F4832494A3000F07FF800946946304800F060F800984006F8D529480221633000F072F800942A4869460C3800F052F80098800700 +:40950000F7D569463846009400F04AF80098C008C00081B20090384600F05CF869460020009400F03DF800980721C008C000084381B20090002000F04DF8154F45217F1F2C +:409540008901384600F046F865218901384600F041F869463046009400F022F80098022180088000084381B20090304600F032F869462846009400F013F800984108490004 +:40958000009189B2284600F025F8FEBD04080000071E0000C9050000BD6E00001D0A000010B50C4601210903FF22411A0232914208D201460548FEF777FC0121C802FEF7D9 +:4095C00073FC0348FEF75CFC208010BD01080000080A000010B5FEF767FC10BDE897FE7F010000000000001000000008C000000004960110C0000008B804000028190008A5 +:40960000740F000000127A0000127A0000093D0000093D0000093D0004000000A00F00000000D0070700000002000000030000000F00000000000000000000000300000015 +:409640000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000019000050A0000000E4450010A5 +:40968000DC450010404600100000614002FF0000891F00100100000006000000841E00080000000000000000000000000000000000000000000000000000000020000000B8 +:4096C00000FFF40100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076 +:40970000000000000000000000000000000000000001000000000000000000000000000000000000FF0000000000000000000000A84700100000000000000000000000002A +:4097400050480010000000000000000098480010000000000000000021000000C04800103C4D0010C04D0010444E0010000000009145011091450110084F0010D95E011043 +:40978000DB5E0110744F0010804F0010E1610110DD610110E04F001035660110D1660110585000100000000000000000000000000000000000000000000000000000000020 +:4097C00000000000000000000000000000000000E9000010C100001000000000F7B50D00019000F04BF9060003281FD12D4B1B69002B19DB002000F051F92B4FB84213D034 +:4098000000232A4A1900012000F020F9041E0BD1002000F043F9264BB84203D09C4203D00134F5E79C4201D1224D39E000F02EF9214A04000121214800F010F900282DD19C +:40984000019B002B16D1ADB2ED0001D11C4D18E03E221C4B06211A601B4A1C4B1A60A3221B4BD20099501B4A9D50995899580029FCDAEBE7114A1369002BFCDB00F016F94A +:409880000500032E03D0200000F0D8F808E00121002000F0EBF80028F9D1F4E7054DF0E72800FEBDC00023400101880048010008F049020005005200401E00080000234090 +:4098C00001005000040126401E1F000008012640000026401C05000010B54378FF2B0DD100F0D4F8064BDB685A68012311681943116011681942FCD100F0A0F810BDC04679 +:409900008000234070B52B490A682A4B002AFBDA0221DA680A43DA60DA68D2071BD5264D264CD9682A69266889B2360A36060E43FF21120209040A4032439026DA602969FD +:409940001F4A360111403143296121680A40324322602A692268002204241A495A605A680A6922430A61012801D030BF00E020BF1A68104D002AFBDAEA68D20712D5FF24EA +:409980000D4E0F4A3069E9682402090A1040214001430A4831610668E9683240090C0C40224302600221DA688A43DA6000225A6070BDC046E000234000002140900021408E +:4099C000FF00FFFF00ED00E00421134A13690B431361012801D030BF00E020BF0F4A1368002BFCDA0E4B19691A00002910D10D490D4B196006210D4B19600D4B3831196008 +:409A00000C4B0631196019680029FCDA0A4B13610022024B5A60704700ED00E0E0002340FC0025401E1F00000801264018052640040126401C052640AAAAAAAA01B40248BD +:409A4000844601BC604700BF531F001001B40248844601BC604700BF1911001001B40248844601BC604700BF890E001001B40248844601BC604700BFA90F001001B402480B +:409A8000844601BC604700BF0504001001B40248844601BC604700BF4B1F001001B40248844601BC604700BF2110001001B40248844601BC604700BF611700100000000099 +:409AC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066 +:409B00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025 +:409B400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E5 +:409B800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A5 +:409BC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065 +:0200000490303A +:02000000C887AF +:0200000490501A +:0C0000000005E20721002101E296E987DB +:00000001FF \ No newline at end of file diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/hex/psoc63_m0_default_1.01.hex b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/hex/psoc63_m0_default_1.01.hex new file mode 100644 index 0000000000..d605fa34de --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/hex/psoc63_m0_default_1.01.hex @@ -0,0 +1,150 @@ +:020000041000EA +:4000000000000108310100100D00000095010010000000000000000000000000000000000000000000000000000000009101001000000000000000009101001091010010DC +:4000400091010010F10700109101001091010010910100109101001091010010910100109101001091010010910100109101001091010010910100109101001091010010FA +:400080009101001091010010910100109101001091010010910100109101001091010010910100109101001091010010910100109101001091010010910100109101001020 +:4000C00010B5064C2378002B07D1054B002B02D0044800E000BF0123237010BD4804000800000000541F0010084B10B5002B03D00749084800E000BF07480368002B00D1AD +:4001000010BD064B002BFBD09847F9E7000000004C040008541F001044010008000000007047EFF3108072B6704780F310887047FFF7F6FF72B6104C104DAC4209DA2168D4 +:400140006268A368043B02DBC858D050FAE70C34F3E70B490B4A0020521A02DD043A8850FCDC094809490860BFF34F8F00F0ECF800F01EF8FEE70000581F0010701F0010D1 +:4001800048040008380700080000000808ED00E0FEE7FEE700B504207146084202D0EFF3098001E0EFF30880043001F08DFAFEE710B500F0A5F962B6064B5B689B0301D517 +:4001C00001F044FA044800F02FF9002001F090F9FBE7C0460000264000000810F8B5E023504C9B00E2580F231340D022990092000919885807224C4D0240032A05D0042A73 +:4002000005D0002A0FD0494811E028680FE0C022920089581F220A40112A01D0132A04D18020000203E0424801E0FA20C001002B27D1B223B1210322DB00C900E65863588A +:4002400067581B0F3F0F1340174205D0354F7958090F0A40012A01D1F20701D4032B3AD1B023344ADB00E658A158E758C904C90C01F050FDB603F901B60BC90F7043013158 +:4002800027E0012B27D1C823C0210322DB00C900E658635867583F0F174205D0214F7958090F0A40012A01D1F20703D49B009B0F032B10D1C0227F23D200A758A1583B40BD +:4002C0001F27A658090A3940584301F023FD310C394001F01FFDE0239B00E3589B069B0FD840154B68601C691969240A090E013101F010FDE1B2A860013101F00BFD0F4BBF +:40030000E860286104000E49C01801F003FDFA210C4B28758900E01801F0FCFCA861C003E861F8BD00002640C000000800366E0100127A0084050000000021403F420F00AC +:4003400040420F00E7030000B021E02010B530241F4BC9005A588000520052085A501A58A2431A50802252045A501A491A4A80209950A021043289019950FF21174AC005FA +:40038000995081315A5892009208024380205A505A580006024301205A505A5882435A5000F054FAFFF71AFF00F02AFA00F032FA00F0B8FEB0235B055A78002A02D05B7855 +:4003C000212B03D10022064BDA605A6010BDC0460000264001000200840500008C050000E0002340024BD86F032318407047C0460400214010B5FFF794FE074A074BD16F79 +:400400000B4007490B43D367102306490A681A42FCD0FFF78AFE10BD04002140FCFF00000100FA058800214070B50F4C0600FFF778FEE36F0500DB439B0701D1FFF7DAFF3F +:40044000B0230A4A9B00D650E26F094B09491340094A1343E36710230A681A42FCD02800FFF763FE70BDC0460400214000002140FCFF0000880021400300FA0510B5040063 +:40048000007B00F0F3F8606010BD10B50400007B216900F0B5F8606010BD10B5037B0169180000F0CDF810BD10B50400C06800F009F9606010BD10B5C06800F017F910BDF0 +:4004C00010B50400C06800F023F9606010BD10B5C06800F037F910BD10B504000C23C05E00F056F8606010BD10B50C23C05E00F06FF810BD10B5C06800F036F910BD0000A8 +:4005000010B500221849042000F0A4FC01221749042000F09FFC02221549042000F09AFC03221449042000F095FC04221249100000F090FC05221149042000F08BFC0622E9 +:400540000F49042000F086FC07220E49042000F081FC08220C49042000F07CFC09220B49042000F077FC10BD7D0400108B0400109B040010A9040010B7040010C104001062 +:40058000CF040010D9040010E9040010F504001070B507260512EDB206400D2D11D801F0F8F80A4901224B5D1C003441144003D1B24013434B5501E00124644201F0EDF8D2 +:4005C00001E001246442200070BDC0466404000870B50412E4B20D2C0FD80725054001F0D8F8064901220B5D1E002E41164202D0AA4093430B5501F0D0F870BD6404000862 +:40060000F8B50C00050001F0C4F80C2301225D431300A3401A00094E71198F683A4008D13B43AD598B60631C4B60AB4202D94A6000E0FF2401F0B1F82000F8BDE0000008BD +:4006400070B50C00050001F0A4F801210C23A1406B43054AD3189A680A4201D08A439A6001F09BF870BDC046E0000008F0B50C2485B0019001F08DF8019B114D5C432B192A +:400680005B68029003932E1971680198FFF7B8FF0700FF280DD173682A59934201D9002373602A1953680399994202D001335360E9E7029801F071F8380005B0F0BDC04648 +:4006C000E000000810B5040007280AD801F061F8054B0E331A5D002A01D101321A5501F05CF80120404210BD6404000810B5040007280AD801F04DF8044B0E331A5D012AE1 +:4007000001D100221A5501F048F810BD6404000870B505001F280ED801F03BF8084B30335C5D002C02D101225A5501E00124644201F033F801E001246442200070BDC04666 +:40074000E000000810B504001F280AD801F021F8044B30331A5D012A01D100221A5501F01CF810BDE000000870B5B024C025144B144A15496405ED00E35CA25C615C665D18 +:400780003F251F242A400C4024039201224311002B407F2219430B003240520413430B4A1C0A110050310B701B0C8B7000234C7011005031595CC1540133062BF8D170BDDB +:4007C000040600000506000003060000E000000810B50248583000F051FB10BDFC04000810B50248B03000F049FB10BDFC04000810B5024800F042FB10BDC046FC0400083C +:4008000010B5034A80216032042000F001FA10BDFC05000870B500F0BCFF0500094800F08BFA094C200000F0B9FA2000343000F0B5FA2000683000F0B1FA280000F0ADFFA1 +:4008400070BDC046FC040008881E0010F0B5962191B0002000F050FF00F026FF002801D100F014FF012000F09FFDE821724C734B626C89011A400A436264626C0193120A04 +:40088000D2B23A2A04D1636C6D4A13400B4363643422002103A801F0D2FA03AA0021694800F06EFC3422002103A801F0C8FA03AA0121644800F064FC082204262368624DA7 +:4008C000134323602369334207D1002D04D0012000F0D2FE013DF5E701E0002D00D1FEE7A02603220127594CF600A35903AD93433B43A351D2195649280001F097FA280088 +:4009000000F0FAFF534901980B68534A03400B608021136949041B021B0A0B4313611369019902200B401361E0230F219B00E2588A433A43E250E25821318A438021E250C6 +:40094000E25809060A43E250002100F0D3FA0021032000F0CFFA0021042000F0CBFA0321002000F0C7FA0321380000F0C3FA384B0522191D280001F059FA2900380000F03F +:40098000DBFA002800D0FEE73449380000F026FB002800D0FEE7324B324AE1580A403A43E250E158304A0A408021E250E25809060A43E250A2592D4B1340A351A2592C4BF3 +:4009C00013408022920113438022A351A35912021343A351184B1A68264B1340164A136000F0DEFEC0235B00E3583B4204D1224AA3585B005B08A3506421002000F07CFEEF +:400A000024220021280001F01AFA29000D4800F031FC2A000E4B0C3313CB13C213CB13C213CB13C22900154800F024FC144A154B1A6011B0F0BDC04600002740FF00FFFF06 +:400A4000FFC5FFDF0000324020A1070000002640241F001090002140000021401027000004050000FEFCFFFFFFFF00FFFFF0FFFFFF8FFFFFFFFCFFFF0C0500000003324062 +:400A800001001180000E1F41030010B5FF24800882009B1ADB009C409940E243214007282DD8174B01F02CF904090E13181D2227186A02401143196221E0586A0240114332 +:400AC00059621CE0986A02401143996217E0D86A02401143D96212E0186B0240114319630DE0586B02401143596308E0986B02401143996303E0D86B02401143D96310BDD7 +:400B000000002140064B10309A68064B9A4203D183009858995002E0034B8000C058704700ED00E00000000800000010F7B5051E01913DD00023C05E002802DBA978FFF735 +:400B4000A3FF6A680023E85E9201002812DB1A4B81088900C918FF2303271C00C0250740FF00BC401A40BA40AD004E59A64332434A5113E003250F2381B20B402940A9404B +:400B8000FC352F002A408F408A40083B9B080B4C9B001B19DE69BE433243DA61074B00259A68074B9A4204D10199FFF7ABFF00E0044D2800FEBDC04600E100E000ED00E070 +:400BC00000000008010056000369002B03DA89B24160002000E001487047C04601008A000368002B01DB034803E089B2C26081600020704701008A000369002B03DAC368D6 +:400C000000200B6000E001487047C04601008A0070B5040010000F2C2BD8002A07D1002927D1154B6401E418144B1C6022E000291FD01F260E401CD1104D0F4B6401E418D0 +:400C40006960AA60CA0831002C6001F0F8F831002000FFF7B9FF31002A1D2868FFF7C0FF011E04D12868FFF7AFFF011E02D0044900E00449080070BD00002340EC06000850 +:400C800001018A0003018A00194BF7B51A680193D76804003B680E00834223D90025A94202D100F076FD0500019B18680368002B01DB104C10E063095A01A41A0122A24090 +:400CC00079689B00CB18196811420DD00024914319600021FFF778FF002E07D1280000F05CFD03E0044C01E0044CF2E72000FEBDEC0600080301880004018A0002018800B6 +:400D00000A4B1B68DA68136883420DD9430999005B01C31A0120984052688B581840431E9841034BC01800E002487047EC0600080001880004018A00024B1A68002A00D14A +:400D400018607047F8060008F0B52C246043104C1E0024681F0A2018FF2426403C400D4F06607601F61906610B4E1B0C44606401A4191E04836033434461A3600023059D5D +:400D8000C261016283619D4201D02B888381F0BDF80600080000234000102340F0B5038985B002AD2B800368066A1933AB704368476A0095826AC16A040003930369C068A1 +:400DC000FFF7C2FF00213B000A0000913000FFF7BBFF216B2800FFF7A9FE0023EA5E002A05DB1F231A401E3B9340024A136005B0F0BDC04600E100E0F7B52C25124C6843E9 +:400E0000276801933C182669002E08D04D4379198869002805D13568002D02DA03E00B4811E00B480FE06768012425004B689D4013882D041D431560F2608C61BC40019B65 +:400E4000A4B24B62B460FEBDF806000804028A0007028A002C235843064B1B681818C369934204D9036A9200D150002000E002487047C046F80600080A028A0073B500269A +:400E800042690400D56801962B0CB3421CD01B040069136013680369B34215DA01A9FFF7ABFEB0420CD10198E26903681E0C0378934205D2226A9B009B58002B00D0984725 +:400EC00031002069FFF780FEADB2002D0ED063691D6000251B68636AAB4202D09847656203E0A36A002B00D09847A56163691B6873BD0000042819D804290FD94B1EFF3B13 +:400F0000132B13D81F231940094B8000C018C02304229B00C1504033C25005E00723D0301940034B8000C150002000E0014870470000264001004A00F0B5012819D1C02275 +:400F4000224BD2009A58002A0CDB8A78901E0E280FD84C78601E11280BD8C8780D7800282FD101E01A4830E07026152D01D9AE4201D2184829E00E79022E14D0F82124020C +:400F80004901F8270C4021007F2412047F033A4011432C4021438024C022C006240520400143D2009950C020C0248005360706403200E4001D590849002029400A431A51C4 +:400FC00003E03826122DD4D9D1E7F0BD0000264003004A0001004A00FFFFFFCFF8B50D00012819D1C02180240D4BC9005A582406C826224307001C005A50F600A3593B42B7 +:4010000006D1002D0AD0012000F036FB013DF5E70020002D03D101E0024800E00248F8BD0000264001004A0002004A001E4A0300904238D010D840282ED005D8002831D0B5 +:4010400010282DD119482EE0802827D08021100049008B4227D023E0154A904214D008D8A022120690421DD0124AA020934211D016E0114A904209D0104A904208D0104AB1 +:4010800090420DD10F480EE0A42003E00E480AE00E4808E0C00306E00D4804E00D4802E00D4800E0002070470600520001005000010000F0090000A0040000F0050000F0C5 +:4010C000030000F00100520002005200030052000200500005005200FF0052000B4B10B51B69002B10DB0A4B0A4C1868FFF79EFF0121094B094A995099580029FCD10649AC +:4011000009590029F8D100E0054810BD00002340FC0600088C040000000025400C0400000200500010B5022202490020FFF792FE10BDC046450200080F4B30B5C0180F4B30 +:40114000C009C01800011F23032909D81D00C9008D4013408B400468AC432343036009E01D000439C9008D4013408B404468AC432343436030BDC0460000CEBF0010030457 +:40118000F7B504000E00150000286ED0002A6CD0012312688B40002A01D1436000E08360B30001930F231900B0008140A26A8A4369680B4083401343A3622A7A31002000BA +:4011C000FFF7BAFF0320710088400322636A83431800EB6813408B400343636201231F00B7400097FF43BC462F6962461F40B740A0691031104038436F69A0611F40B740A9 +:40120000E06A10403843E062A86903221840B0400600E869276B10408A408840009930430A4397436A6A384356000222206304201640AA6A616B92000240286A3243034017 +:401240001A43EB6AD80018230340FF2013432A6B019D520102401343FE2292002A40934081430B436363002000E00148FEBDC04601005A0000281BD0002919D00D4B0E4AD2 +:40128000C318DB099B180A681B010260CA6882620A69C2624A6902638A6842624A6882618A694263CA6900201A600A6A5A6000E0024870470000CEBF0010030401005A0069 +:4012C00010B50F2402200649064BCA58A2430243CA50F02212028B58A34303438B5010BD0000214004F0000010B50F2403200649064BCA58A2430243CA50F02212028B5872 +:40130000A34303438B5010BD0000214004F000000449054A054B88580340C020C00103438B5070470000214004F00000FF8FFFFF0449054A054B885803408020C001034365 +:401340008B5070470000214004F00000FF8FFFFF031E03D1084B5869C00F0CE00020012B09D1054918008A69920F1A4201D18869C00F01231840704700002640072370B540 +:40138000084CA2691A4090420BD0A5699D4303402B43A361002904D0904202D9C82000F06BF970BD00002640F7B5060000F0F1F9B022E8211F27244D244C01902B595205B1 +:4013C000C900525C3B409B1A5A1E9341B34236D0002E13D180211E4A490493690B439361FFF76EFF0B222B59BB4313432B51FFF78FFFB023E8225B05D2000CE00B222B5945 +:401400000920BB4313432B5100F036F9FFF790FFB022104B5205D35C2959DAB21F23994313400B432B51012E09D1092000F024F9FFF75AFF064A084B91690B409361019810 +:4014400000F0ABF9F7BDC046000026401CFF000000F0254041070000FFFFFFFEF0B5060085B00D00204F042901D001291AD100207C68002C35D01D4B984232D02379B3428C +:401480000ED1A368002B01D02B4209D1E36801A85A689B6842608360057023689847BC606469E6E7BC68022902D1002C00D024690020002C15D00D4B984212D02379B342AB +:4014C0000DD1A368002B01D02B4208D1E36801A85A689B68426083600570236898472469E7E705B0F0BDC0460C070008FF004200F7B5484C06002368002B0AD100F049F97C +:4015000023680700002B10D004210120FFF7A6FF0BE001210800FFF7A1FF0028EED002210120FFF79BFF3C4C72E03C4D2B680195DB061AD5F2223A4BD2019A58E260F022BA +:40154000D2019A582261374A9A586261364A9A58A261364A9A58E261354A9A582262354A9A586262344A9B58A362B02252055378002B02D05378212B03D1300000F07CFCAF +:401580001DE02E4B2E492F4859588C46E821C900515CC9B20091196809020AD41F2165460D402900009DA94203D0274952581A5002E00023214A1350300000F055FC019B2F +:4015C0001B68DB0619D5F0222169154BD20199506169144A9950A169134A9950E169134A9950216A124A9950616A124A9950A16A114A9950E168E8329950380000F0CDF888 +:4016000023680024A34203D008210120FFF726FF2000FEBD0C070008FF004200E00001400000344004780000087800000C7800001078000014780000187800000000264088 +:401640001CFF0000307F00001018000010B5E82400F09FF8064B07495A68A4010A4022435A605A68114059605B6800F096F810BD00002640FF00FC0F10B5034B1B78584324 +:4016800000F07EF810BDC046D400000880220020034B12069A649B6C834200DA0148704700002740030046008022054B120198585B68DBB2002B02D08023DB0218437047C5 +:4016C00000002640FEE7000002680A4B10B51A6042685A6082689A60C268DA6002691A6142695A6182699A61C269DA61FFF7EAFF10BDC04628040008F0B51922002800D19E +:401700004B32E82403258A429241194E640033595242AB43134333513359164F3B403351154B5C68AC4322435A605A6817405F60002808D00023102913D921338B429B4167 +:401740005B4201330DE003001D290AD901233A2907D9DB18572904D976338B4240410422131A0F21054A1068884303431360F0BD00002140FFFCFFFFFC002140000025403A +:401780000230800803D001300238FCD1C046C0467047EFF3108072B6704780F310887047094B042803D11A68104318600BE0C02200069204104090220449920088500421A6 +:4017C0001A688A431A60704710E000E000002140F8B58023FA250C0001271B0218430D4E0004F061AD00326C0A4B01203A4205D1002D0CD0013DFFF73FFFF4E7002D06D001 +:401800001A6C10431864DB6A0020238000E00248F8BDC04600003C400400160070B5FA2401260D4B000418400C4D0143E961A4002B6C0A4A0120334205D1002C0AD0013C8D +:40184000FFF71AFFF4E7002C04D0136C18431064002000E0024870BD0000FF7F00003C400400160030B524259DB02A00002101A800F0E5FA154B164C0493164B2A00002162 +:401880000AA808930993069400F0D9FA124B2A000D93124B00211193114B13A812930F9400F0CDFA0F4B01A916930F4B0F481A931894FFF7DFFC0AA90D48FFF7DBFC13A96A +:4018C0000C48FFF7D7FC1DB030BDC046666666660000FFFF1C1C1C1C66E6EE661C1A1A1A1A1A000066E666661A1A001C000132408001324000023240F0B585B000900028F3 +:4019000000D147E1BE4F7B689B0301D5FFF79EFE0122BC4BBC4C1D001959114204D0BB495B58134200D037E1FFF79CFFB84AB94BEA508022009BD2021B781343B64AAB5016 +:40194000B64AB74BEA50B74B5A6801231A4200D024E1B54A116F08220A4008D1B34BB44918681300884202D900F0D4F9431E2A68002B03D0AF485B03034300E0AE4B13439B +:401980002B607B699F499E4E01275B000DD539000320FFF7F3FC73699B0F3B420AD08022B369D2051343B36104E00320A34A8B5803438B502B5940200193019AA04BA14E7D +:4019C00013432B51FFF758FE0123AA598D4F1A4208D1BB514020FFF74FFE03234020BB51FFF74AFEFA27019A974B984E1A4016430192FF002E51964A964BD3581022134257 +:401A000007D1002F00D1CBE00120013FFFF734FEF1E7002F00D1C3E008218F4A0120AB580B43AB50FFF794FC002802D18B4E019B1E438B4B1E4001231E432E511E00894C2E +:401A4000724BEB58334207D1002C00D1A8E00120013CFFF711FEF3E7002C00D1A0E00B27C02181484901FFF7D9FE041E05D102AB991D7D48FFF7ACFE0400013F002F00D1E3 +:401A800096E0002C25D1C02202AB9E1D338852019342E5D131007548FFF79AFE041E18D180233288DB001A4200D083E00B27019380216E48C900FFF7B1FE041E04D13100AA +:401AC0006A48FFF785FE0400013F002F70D0002C68D0B0256D056B78002B44D06B78212B41D0634FEB5B002B3DD0002C00D0FEE002AB9E1D31005F48FFF76AFE041E00D061 +:401B0000F5E0C021E85B3488084060398C434008594920430140F020EA5BC000EB5BD201024011439B05554A9B0F1140DB02194350483180FFF772FE041E00D0D7E03100F2 +:401B40004F48FFF745FE041E00D0D0E0C022EB5B31889B069B0F9B019143194348483180FFF75CFE0400002C00D0C0E0009B454859781D78444B49001943FFF74FFE041EA3 +:401B800004D142494248FFF749FE04006801FFF773FDACE03F4CAAE03F4CA8E03F4CA6E03F4CA4E03388019A934200D080E701E03B4C8EE731003B48FFF70AFE041E00D074 +:401BC00087E732883F2310009843009B36499F78DB78012F0ED10222012B04D89FB2D21B92B2019201E0170001947022104330802E4A66E0002B5BD0019401275BE0C04668 +:401C00000000264000003C40A0F00100B4F0010006000001A4F00100A8F0010001000100ACF00100FC003C4000F03D40C800000800093D00041A0080040A0080C4F00100DC +:401C400030000300B0F00100EFFFFEFF20000200000032401040000068F0010028000200FFFFFBFFF07E0E00021E0000031E000016180000071E00007FF8FFFFFFE7FFFFDD +:401C8000061E0000081E000001100000376800000F1E000001001600030016000200160004001600091E0000C00000080048E80101201F0001907F2082436F3802433280A8 +:401CC0000C4ADA400A6031880B4839433180FFF7A5FD009B0400DB78DF1B03231F40019B9B001F43054BBFB23780EF50F1E6200005B0F0BD0024F400091E000064F001008B +:401D000002B4714649084900095C49008E4402BC7047C046002243088B4274D303098B425FD3030A8B4244D3030B8B4228D3030C8B420DD3FF22090212BA030C8B4202D3E9 +:401D40001212090265D0030B8B4219D300E0090AC30B8B4201D3CB03C01A5241830B8B4201D38B03C01A5241430B8B4201D34B03C01A5241030B8B4201D30B03C01A52419D +:401D8000C30A8B4201D3CB02C01A5241830A8B4201D38B02C01A5241430A8B4201D34B02C01A5241030A8B4201D30B02C01A5241CDD2C3098B4201D3CB01C01A52418309B2 +:401DC0008B4201D38B01C01A524143098B4201D34B01C01A524103098B4201D30B01C01A5241C3088B4201D3CB00C01A524183088B4201D38B00C01A524143088B4201D3C9 +:401E00004B00C01A5241411A00D20146524110467047FFE701B5002000F006F802BDC0460029F7D076E770477047C046002310B59A4203D0CC5CC4540133F9E710BD0300EB +:401E40008218934202D019700133FAE770470000F8B5C046F8BC08BC9E467047F8B5C046F8BC08BC9E46704701B40248844601BC604700BF3503000801B40248844601BC8E +:401E8000604700BF7102000803000000010000000100000000000000050360000400000001000000000000000100000006046000080000006C060008F107001008000000D2 +:401EC000010000000200000002000000080800030900000001000000000000000300000009090003080000008C060008D10700100A0000000100000004000000040000000B +:401F00000A0A000C0B0000000100000000000000050000000B0B000C10000000AC060008E1070010192001021901020000000000000000000000000000000000000000BA7A +:401F40000000000000000000000000000000000000001D1D000000000000001000000008C0000000781F0010C00000086803000048040008F002000000127A0000127A0017 +:401F800000093D0000093D0000093D0004000000A00F00000000D0070700000002000000030000000F000000000000000000000003000000000000000000000000000000A7 +:401FC0000000000000000000030000000000000000000000000000000000000000000000000000000000000019000050A000000002FF0000E9000010C1000010000000000A +:40200000F7B50D00019000F04BF9060003281FD12D4B1B69002B19DB002000F021F92B4FB84213D000232A4A1900012000F048F9041E0BD1002000F013F9264BB84203D00B +:402040009C4203D00134F5E79C4201D1224D39E000F01EF9214A04000121214800F028F900282DD1019B002B16D1ADB2ED0001D11C4D18E03E221C4B06211A601B4A1C4BCD +:402080001A60A3221B4BD20099501B4A9D50995899580029FCDAEBE7114A1369002BFCDB00F0E6F80500032E03D0200000F010F908E00121002000F0E3F80028F9D1F4E730 +:4020C000054DF0E72800FEBDC00023400101880038010008F049020005005200FC0600080000234001005000040126401E1F000008012640000026401C05000010B5437878 +:40210000FF2B0DD100F0C4F8064BDB685A68012311681943116011681942FCD100F0D8F810BDC0468000234070B52B490A682A4B002AFBDA0221DA680A43DA60DA68D2078E +:402140001BD5264D264CD9682A69266889B2360A36060E43FF21120209040A4032439026DA6029691F4A360111403143296121680A40324322602A692268002204241A491B +:402180005A605A680A6922430A61012801D030BF00E020BF1A68104D002AFBDAEA68D20712D5FF240D4E0F4A3069E9682402090A1040214001430A4831610668E9683240C4 +:4021C000090C0C40224302600221DA688A43DA6000225A6070BDC046E00023400000214090002140FF00FFFF00ED00E00421134A13690B431361012801D030BF00E020BF75 +:402200000F4A1368002BFCDA0E4B19691A00002910D10D490D4B196006210D4B19600D4B383119600C4B0631196019680029FCDA0A4B13610022024B5A60704700ED00E074 +:40224000E0002340FC0025401E1F00000801264018052640040126401C052640AAAAAAAA01B40248844601BC604700BF010D001001B40248844601BC604700BFDD100010FE +:4022800001B40248844601BC604700BF890C001001B40248844601BC604700BF9317001001B40248844601BC604700BFE503001001B40248844601BC604700BFE10B00101B +:4022C00001B40248844601BC604700BFF90D001001B40248844601BC604700BF9B17001000000000000000000000000000000000000000000000000000000000000000002E +:40230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009D +:40234000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005D +:40238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001D +:4023C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000DD +:0200000490303A +:02000000121CD0 +:0200000490501A +:0C0000000005E20721002101E212331C80 +:00000001FF \ No newline at end of file diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/ipc_rpc.cpp b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/ipc_rpc.cpp new file mode 100644 index 0000000000..c331b23adc --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/ipc_rpc.cpp @@ -0,0 +1,108 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#include "ipc_rpc.h" +#include "Mutex.h" +#include "Semaphore.h" +#include "mbed_assert.h" +#include "cy_ipc_config.h" +#include "ipc/cy_ipc_pipe.h" +#include +#include "platform/SingletonPtr.h" + +using namespace rtos; + + +static SingletonPtr msg_mutex; +static SingletonPtr msg_semaphore; + + +#define RPC_GEN RPC_GEN_INTERFACE_IDS +#include "rpc_api.h" +#undef RPC_GEN + +// This function uses a "C" linkage as it is a callback called from Cypress library +// which is C-only. +extern "C" void ipcrpc_release(void); +void ipcrpc_release(void) +{ + // Just signal on semaphore that we are done with a call. + msg_semaphore->release(); +} + +// Encapsulate call arguments and send a message over IPC pipe to the +// other core for execution. +uint32_t ipcrpc_call(uint32_t call_id, uint32_t args_num, ...) +{ + va_list ap; + static IpcRpcMessage message; + cy_en_ipc_pipe_status_t status; + ScopedMutexLock lock(*msg_mutex.get()); + + // Make sure semaphore is initialized. + (void)msg_semaphore.get(); + + // Copy data to the buffer. + message.client_id = call_id; + message.args_num = args_num; + message.result = 0; // default result + + va_start(ap, args_num); + for (uint32_t i = 0; i < args_num; ++i) { + message.args[i] = va_arg (ap, uint32_t); + } + va_end (ap); + + // send message + status = Cy_IPC_Pipe_SendMessage(CY_IPC_EP_RPCPIPE_DEST, + CY_IPC_EP_RPCPIPE_ADDR, + &message, + ipcrpc_release); + // We are using dedicated IPC channel here and have locked global mutex + // so this had to succeed. + MBED_ASSERT(status == CY_IPC_PIPE_SUCCESS); + + // Now wait for the response; + msg_semaphore->wait(); + + return message.result; +} + +extern "C" { + + void ipcrpc_init(void) + { + uint32_t rpc_counter = 0; +#define RPC_GEN RPC_GEN_INTERFACE_IDS_INIT +#include "rpc_api.h" +#undef RPC_GEN + } + + +#define RPC_GEN RPC_GEN_INTERFACE +#include "rpc_api.h" +#undef RPC_GEN + + +#define RPC_GEN RPC_GEN_IMPLEMENTATION +#include "rpc_api.h" +#undef RPC_GEN + + +} /* extern "C" */ + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/system_psoc63_cm4.c b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/system_psoc63_cm4.c new file mode 100644 index 0000000000..384c287f5a --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/TARGET_MCU_PSOC6_M4/system_psoc63_cm4.c @@ -0,0 +1,461 @@ +/***************************************************************************//** +* \file system_psoc63_cm4.c +* \version 2.10 +* +* The device system-source file. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* Copyright 2017-2018, Future Electronics +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include +#include +#include "device.h" +#include "system_psoc63.h" +#include "cy_device_headers.h" +#include "ipc_rpc.h" +#include "psoc6_utils.h" + +#if defined(CY_DEVICE_PSOC6ABLE2) && !defined(CY_IPC_DEFAULT_CFG_DISABLE) + #include "ipc/cy_ipc_drv.h" + #include "flash/cy_flash.h" +#endif /* defined(CY_DEVICE_PSOC6ABLE2) && !defined(CY_IPC_DEFAULT_CFG_DISABLE) */ + + +/******************************************************************************* +* SystemCoreClockUpdate() +*******************************************************************************/ + +/** Default HFClk frequency in Hz */ +#define CY_CLK_HFCLK0_FREQ_HZ_DEFAULT CY_CLK_HFCLK0_FREQ_HZ + +/** Default PeriClk frequency in Hz */ +#define CY_CLK_PERICLK_FREQ_HZ_DEFAULT CY_CLK_PERICLK_FREQ_HZ + +/** Default SlowClk system core frequency in Hz */ +#define CY_CLK_SYSTEM_FREQ_HZ_DEFAULT CY_CLK_HFCLK0_FREQ_HZ + + +/* +* Holds the FastClk system core clock, which is the system clock frequency +* supplied to the SysTick timer and the processor core clock. +* This variable implements CMSIS Core global variable. +* Refer to the [CMSIS documentation] +* (http://www.keil.com/pack/doc/CMSIS/Core/html/group__system__init__gr.html "System and Clock Configuration") +* for more details. +* This variable can be used by debuggers to query the frequency +* of the debug timer or to configure the trace clock speed. +* +* \attention Compilers must be configured to avoid removing this variable in case +* the application program is not using it. Debugging systems require the variable +* to be physically present in memory so that it can be examined to configure the debugger. */ +uint32_t SystemCoreClock = CY_CLK_SYSTEM_FREQ_HZ_DEFAULT; + +/** Holds the HFClk0 clock frequency. Updated by \ref SystemCoreClockUpdate(). */ +uint32_t cy_Hfclk0FreqHz = CY_CLK_HFCLK0_FREQ_HZ_DEFAULT; + +/** Holds the PeriClk clock frequency. Updated by \ref SystemCoreClockUpdate(). */ +uint32_t cy_PeriClkFreqHz = CY_CLK_PERICLK_FREQ_HZ_DEFAULT; + +#if (defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL)) || defined (CY_DOXYGEN) + /** Holds the Alternate high frequency clock in Hz. Updated by \ref SystemCoreClockUpdate(). */ + uint32_t cy_BleEcoClockFreqHz = CY_CLK_ALTHF_FREQ_HZ; +#endif /* (defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL)) || defined (CY_DOXYGEN) */ + + +/* SCB->CPACR */ +#define SCB_CPACR_CP10_CP11_ENABLE (0xFUL << 20u) + + +/******************************************************************************* +* SystemInit() +*******************************************************************************/ +/* WDT lock bits */ +#define CY_WDT_LOCK_BIT0 ((uint32_t)0x01u << 30u) +#define CY_WDT_LOCK_BIT1 ((uint32_t)0x01u << 31u) + +#if (__CM0P_PRESENT == 0) + /* CLK_FLL_CONFIG default values */ + #define CY_FB_CLK_FLL_CONFIG_VALUE (0x01000000u) + #define CY_FB_CLK_FLL_CONFIG2_VALUE (0x00020001u) + #define CY_FB_CLK_FLL_CONFIG3_VALUE (0x00002800u) + #define CY_FB_CLK_FLL_CONFIG4_VALUE (0x000000FFu) +#endif /* (__CM0P_PRESENT == 0) */ + + +/******************************************************************************* +* SystemCoreClockUpdate (void) +*******************************************************************************/ +/* Do not use these definitions directly in your application */ +#define CY_DELAY_MS_OVERFLOW_THRESHOLD (0x8000u) +#define CY_DELAY_1K_THRESHOLD (1000u) +#define CY_DELAY_1K_MINUS_1_THRESHOLD (CY_DELAY_1K_THRESHOLD - 1u) +#define CY_DELAY_1M_THRESHOLD (1000000u) +#define CY_DELAY_1M_MINUS_1_THRESHOLD (CY_DELAY_1M_THRESHOLD - 1u) +uint32_t cy_delayFreqHz = CY_CLK_SYSTEM_FREQ_HZ_DEFAULT; + +uint32_t cy_delayFreqKhz = (CY_CLK_SYSTEM_FREQ_HZ_DEFAULT + CY_DELAY_1K_MINUS_1_THRESHOLD) / + CY_DELAY_1K_THRESHOLD; + +uint8_t cy_delayFreqMhz = (uint8_t)((CY_CLK_SYSTEM_FREQ_HZ_DEFAULT + CY_DELAY_1M_MINUS_1_THRESHOLD) / + CY_DELAY_1M_THRESHOLD); + +uint32_t cy_delay32kMs = CY_DELAY_MS_OVERFLOW_THRESHOLD * + ((CY_CLK_SYSTEM_FREQ_HZ_DEFAULT + CY_DELAY_1K_MINUS_1_THRESHOLD) / CY_DELAY_1K_THRESHOLD); + +#define CY_ROOT_PATH_SRC_IMO (0UL) +#define CY_ROOT_PATH_SRC_EXT (1UL) +#if (SRSS_ECO_PRESENT == 1U) + #define CY_ROOT_PATH_SRC_ECO (2UL) +#endif /* (SRSS_ECO_PRESENT == 1U) */ +#if (SRSS_ALTHF_PRESENT == 1U) + #define CY_ROOT_PATH_SRC_ALTHF (3UL) +#endif /* (SRSS_ALTHF_PRESENT == 1U) */ +#define CY_ROOT_PATH_SRC_DSI_MUX (4UL) +#define CY_ROOT_PATH_SRC_DSI_MUX_HVILO (16UL) +#define CY_ROOT_PATH_SRC_DSI_MUX_WCO (17UL) +#if (SRSS_ALTLF_PRESENT == 1U) + #define CY_ROOT_PATH_SRC_DSI_MUX_ALTLF (18UL) +#endif /* (SRSS_ALTLF_PRESENT == 1U) */ +#if (SRSS_PILO_PRESENT == 1U) + #define CY_ROOT_PATH_SRC_DSI_MUX_PILO (19UL) +#endif /* (SRSS_PILO_PRESENT == 1U) */ + + +/******************************************************************************* +* Function Name: SystemInit +****************************************************************************//** +* \cond +* Initializes the system: +* - Restores FLL registers to the default state for single core devices. +* - Unlocks and disables WDT. +* - Calls the Cy_SystemInit() function, if compiled from PSoC Creator. +* - Calls \ref SystemCoreClockUpdate(). +* \endcond +*******************************************************************************/ +void SystemInit(void) +{ +#if (__CM0P_PRESENT == 0) + /* Restore FLL registers to the default state as they are not restored by the ROM code */ + uint32_t copy = SRSS->CLK_FLL_CONFIG; + copy &= ~SRSS_CLK_FLL_CONFIG_FLL_ENABLE_Msk; + SRSS->CLK_FLL_CONFIG = copy; + + copy = SRSS->CLK_ROOT_SELECT[0u]; + copy &= ~SRSS_CLK_ROOT_SELECT_ROOT_DIV_Msk; /* Set ROOT_DIV = 0*/ + SRSS->CLK_ROOT_SELECT[0u] = copy; + + SRSS->CLK_FLL_CONFIG = CY_FB_CLK_FLL_CONFIG_VALUE; + SRSS->CLK_FLL_CONFIG2 = CY_FB_CLK_FLL_CONFIG2_VALUE; + SRSS->CLK_FLL_CONFIG3 = CY_FB_CLK_FLL_CONFIG3_VALUE; + SRSS->CLK_FLL_CONFIG4 = CY_FB_CLK_FLL_CONFIG4_VALUE; +#endif /* (__CM0P_PRESENT == 0) */ + + /* Unlock and disable WDT */ + SRSS->WDT_CTL = ((SRSS->WDT_CTL & (uint32_t)(~SRSS_WDT_CTL_WDT_LOCK_Msk)) | CY_WDT_LOCK_BIT0); + SRSS->WDT_CTL = (SRSS->WDT_CTL | CY_WDT_LOCK_BIT1); + SRSS->WDT_CTL &= (~ (uint32_t) SRSS_WDT_CTL_WDT_EN_Msk); + + Cy_SystemInit(); + SystemCoreClockUpdate(); +} + + +/******************************************************************************* +* Function Name: mbed_sdk_init +****************************************************************************//** +* +* Mbed's post-memory-initialization function. +* Used here to initialize common parts of the Cypress libraries. +* +*******************************************************************************/ +void mbed_sdk_init(void) +{ + /* Initialize shared resource manager */ + cy_srm_initialize(); + /* Initialize system and clocks. */ + /* Placed here as it must be done after proper LIBC initialization. */ + SystemInit(); + /* Allocate and initialize semaphores for the system operations. */ + Cy_IPC_SystemSemaInit(); + Cy_IPC_SystemPipeInit(); + Cy_Flash_Init(); + ipcrpc_init(); +} + + +/******************************************************************************* +* Function Name: Cy_SystemInit +****************************************************************************//** +* +* The function is called during device startup. Once project compiled as part of +* the PSoC Creator project, the Cy_SystemInit() function is generated by the +* PSoC Creator. +* +* The function generated by PSoC Creator performs all of the necessary device +* configuration based on the design settings. This includes settings from the +* Design Wide Resources (DWR) such as Clocks and Pins as well as any component +* configuration that is necessary. +* +*******************************************************************************/ +__WEAK void Cy_SystemInit(void) +{ + /* Empty weak function. The actual implementation to be in the PSoC Creator + * generated strong function. + */ +} + + +/******************************************************************************* +* Function Name: SystemCoreClockUpdate +****************************************************************************//** +* +* Gets core clock frequency and updates \ref SystemCoreClock, \ref +* cy_Hfclk0FreqHz, and \ref cy_PeriClkFreqHz. +* +* Updates global variables used by the \ref Cy_SysLib_Delay(), \ref +* Cy_SysLib_DelayUs(), and \ref Cy_SysLib_DelayCycles(). +* +*******************************************************************************/ +void SystemCoreClockUpdate (void) +{ + uint32_t srcFreqHz; + uint32_t pathFreqHz; + uint32_t fastClkDiv; + uint32_t periClkDiv; + uint32_t rootPath; + uint32_t srcClk; + + /* Get root path clock for the high-frequency clock # 0 */ + rootPath = _FLD2VAL(SRSS_CLK_ROOT_SELECT_ROOT_MUX, SRSS->CLK_ROOT_SELECT[0u]); + + /* Get source of the root path clock */ + srcClk = _FLD2VAL(SRSS_CLK_PATH_SELECT_PATH_MUX, SRSS->CLK_PATH_SELECT[rootPath]); + + /* Get frequency of the source */ + switch (srcClk) + { + case CY_ROOT_PATH_SRC_IMO: + srcFreqHz = CY_CLK_IMO_FREQ_HZ; + break; + + case CY_ROOT_PATH_SRC_EXT: + srcFreqHz = CY_CLK_EXT_FREQ_HZ; + break; + + #if (SRSS_ECO_PRESENT == 1U) + case CY_ROOT_PATH_SRC_ECO: + srcFreqHz = CY_CLK_ECO_FREQ_HZ; + break; + #endif /* (SRSS_ECO_PRESENT == 1U) */ + +#if defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) && (SRSS_ALTHF_PRESENT == 1U) + case CY_ROOT_PATH_SRC_ALTHF: + srcFreqHz = cy_BleEcoClockFreqHz; + break; +#endif /* defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) && (SRSS_ALTHF_PRESENT == 1U) */ + + case CY_ROOT_PATH_SRC_DSI_MUX: + { + uint32_t dsi_src; + dsi_src = _FLD2VAL(SRSS_CLK_DSI_SELECT_DSI_MUX, SRSS->CLK_DSI_SELECT[rootPath]); + switch (dsi_src) + { + case CY_ROOT_PATH_SRC_DSI_MUX_HVILO: + srcFreqHz = CY_CLK_HVILO_FREQ_HZ; + break; + + case CY_ROOT_PATH_SRC_DSI_MUX_WCO: + srcFreqHz = CY_CLK_WCO_FREQ_HZ; + break; + + #if (SRSS_ALTLF_PRESENT == 1U) + case CY_ROOT_PATH_SRC_DSI_MUX_ALTLF: + srcFreqHz = CY_CLK_ALTLF_FREQ_HZ; + break; + #endif /* (SRSS_ALTLF_PRESENT == 1U) */ + + #if (SRSS_PILO_PRESENT == 1U) + case CY_ROOT_PATH_SRC_DSI_MUX_PILO: + srcFreqHz = CY_CLK_PILO_FREQ_HZ; + break; + #endif /* (SRSS_PILO_PRESENT == 1U) */ + + default: + srcFreqHz = CY_CLK_HVILO_FREQ_HZ; + break; + } + } + break; + + default: + srcFreqHz = CY_CLK_EXT_FREQ_HZ; + break; + } + + if (rootPath == 0UL) + { + /* FLL */ + bool fllLocked = ( 0UL != _FLD2VAL(SRSS_CLK_FLL_STATUS_LOCKED, SRSS->CLK_FLL_STATUS)); + bool fllOutputOutput = ( 3UL == _FLD2VAL(SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, SRSS->CLK_FLL_CONFIG3)); + bool fllOutputAuto = ((0UL == _FLD2VAL(SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, SRSS->CLK_FLL_CONFIG3)) || + (1UL == _FLD2VAL(SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, SRSS->CLK_FLL_CONFIG3))); + if ((fllOutputAuto && fllLocked) || fllOutputOutput) + { + uint32_t fllMult; + uint32_t refDiv; + uint32_t outputDiv; + + fllMult = _FLD2VAL(SRSS_CLK_FLL_CONFIG_FLL_MULT, SRSS->CLK_FLL_CONFIG); + refDiv = _FLD2VAL(SRSS_CLK_FLL_CONFIG2_FLL_REF_DIV, SRSS->CLK_FLL_CONFIG2); + outputDiv = _FLD2VAL(SRSS_CLK_FLL_CONFIG_FLL_OUTPUT_DIV, SRSS->CLK_FLL_CONFIG) + 1UL; + + pathFreqHz = ((srcFreqHz / refDiv) * fllMult) / outputDiv; + } + else + { + pathFreqHz = srcFreqHz; + } + } + else if (rootPath == 1UL) + { + /* PLL */ + bool pllLocked = ( 0UL != _FLD2VAL(SRSS_CLK_PLL_STATUS_LOCKED, SRSS->CLK_PLL_STATUS[0UL])); + bool pllOutputOutput = ( 3UL == _FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, SRSS->CLK_PLL_CONFIG[0UL])); + bool pllOutputAuto = ((0UL == _FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, SRSS->CLK_PLL_CONFIG[0UL])) || + (1UL == _FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, SRSS->CLK_PLL_CONFIG[0UL]))); + if ((pllOutputAuto && pllLocked) || pllOutputOutput) + { + uint32_t feedbackDiv; + uint32_t referenceDiv; + uint32_t outputDiv; + + feedbackDiv = _FLD2VAL(SRSS_CLK_PLL_CONFIG_FEEDBACK_DIV, SRSS->CLK_PLL_CONFIG[0UL]); + referenceDiv = _FLD2VAL(SRSS_CLK_PLL_CONFIG_REFERENCE_DIV, SRSS->CLK_PLL_CONFIG[0UL]); + outputDiv = _FLD2VAL(SRSS_CLK_PLL_CONFIG_OUTPUT_DIV, SRSS->CLK_PLL_CONFIG[0UL]); + + pathFreqHz = ((srcFreqHz * feedbackDiv) / referenceDiv) / outputDiv; + + } + else + { + pathFreqHz = srcFreqHz; + } + } + else + { + /* Direct */ + pathFreqHz = srcFreqHz; + } + + /* Get frequency after hf_clk pre-divider */ + pathFreqHz = pathFreqHz >> _FLD2VAL(SRSS_CLK_ROOT_SELECT_ROOT_DIV, SRSS->CLK_ROOT_SELECT[0u]); + cy_Hfclk0FreqHz = pathFreqHz; + + /* Fast Clock Divider */ + fastClkDiv = 1u + _FLD2VAL(CPUSS_CM4_CLOCK_CTL_FAST_INT_DIV, CPUSS->CM4_CLOCK_CTL); + + /* Peripheral Clock Divider */ + periClkDiv = 1u + _FLD2VAL(CPUSS_CM0_CLOCK_CTL_PERI_INT_DIV, CPUSS->CM0_CLOCK_CTL); + cy_PeriClkFreqHz = pathFreqHz / periClkDiv; + + pathFreqHz = pathFreqHz / fastClkDiv; + SystemCoreClock = pathFreqHz; + + /* Sets clock frequency for Delay API */ + cy_delayFreqHz = SystemCoreClock; + cy_delayFreqMhz = (uint8_t)((cy_delayFreqHz + CY_DELAY_1M_MINUS_1_THRESHOLD) / CY_DELAY_1M_THRESHOLD); + cy_delayFreqKhz = (cy_delayFreqHz + CY_DELAY_1K_MINUS_1_THRESHOLD) / CY_DELAY_1K_THRESHOLD; + cy_delay32kMs = CY_DELAY_MS_OVERFLOW_THRESHOLD * cy_delayFreqKhz; +} + + +/******************************************************************************* +* Function Name: Cy_SystemInitFpuEnable +****************************************************************************//** +* +* Enables the FPU if it is used. The function is called from the startup file. +* +*******************************************************************************/ +void Cy_SystemInitFpuEnable(void) +{ + #if defined (__FPU_USED) && (__FPU_USED == 1U) + uint32_t interruptState; + interruptState = Cy_SaveIRQ(); + SCB->CPACR |= SCB_CPACR_CP10_CP11_ENABLE; + __DSB(); + __ISB(); + Cy_RestoreIRQ(interruptState); + #endif /* (__FPU_USED) && (__FPU_USED == 1U) */ +} + + +/******************************************************************************* +* Function Name: Cy_MemorySymbols +****************************************************************************//** +* +* The intention of the function is to declare boundaries of the memories for the +* MDK compilers. For the rest of the supported compilers, this is done using +* linker configuration files. The following symbols used by the cymcuelftool. +* +*******************************************************************************/ +#if defined (__ARMCC_VERSION) +__asm void Cy_MemorySymbols(void) +{ + /* Flash */ + EXPORT __cy_memory_0_start + EXPORT __cy_memory_0_length + EXPORT __cy_memory_0_row_size + + /* Working Flash */ + EXPORT __cy_memory_1_start + EXPORT __cy_memory_1_length + EXPORT __cy_memory_1_row_size + + /* Supervisory Flash */ + EXPORT __cy_memory_2_start + EXPORT __cy_memory_2_length + EXPORT __cy_memory_2_row_size + + /* XIP */ + EXPORT __cy_memory_3_start + EXPORT __cy_memory_3_length + EXPORT __cy_memory_3_row_size + + /* eFuse */ + EXPORT __cy_memory_4_start + EXPORT __cy_memory_4_length + EXPORT __cy_memory_4_row_size + + /* Flash */ +__cy_memory_0_start EQU __cpp(CY_FLASH_BASE) +__cy_memory_0_length EQU __cpp(CY_FLASH_SIZE) +__cy_memory_0_row_size EQU 0x200 + + /* Flash region for EEPROM emulation */ +__cy_memory_1_start EQU __cpp(CY_EM_EEPROM_BASE) +__cy_memory_1_length EQU __cpp(CY_EM_EEPROM_SIZE) +__cy_memory_1_row_size EQU 0x200 + + /* Supervisory Flash */ +__cy_memory_2_start EQU __cpp(CY_SFLASH_BASE) +__cy_memory_2_length EQU __cpp(CY_SFLASH_SIZE) +__cy_memory_2_row_size EQU 0x200 + + /* XIP */ +__cy_memory_3_start EQU __cpp(CY_XIP_BASE) +__cy_memory_3_length EQU __cpp(CY_XIP_SIZE) +__cy_memory_3_row_size EQU 0x200 + + /* eFuse */ +__cy_memory_4_start EQU __cpp(0x90700000) +__cy_memory_4_length EQU __cpp(0x100000) +__cy_memory_4_row_size EQU __cpp(1) +} +#endif /* defined (__ARMCC_VERSION) */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device.h b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device.h new file mode 100644 index 0000000000..0ef546175a --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device.h @@ -0,0 +1,81 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#ifndef MBED_DEVICE_H +#define MBED_DEVICE_H + +/*----------------------------------------------------------------------------*/ +/** Config options. */ +/*----------------------------------------------------------------------------*/ +/** ALTHF (BLE ECO) frequency in Hz */ +#define CYDEV_CLK_ALTHF__HZ ( 8000000UL) + +/*----------------------------------------------------------------------------*/ + +#include "cmsis.h" +#include "objects.h" + +/* + * Board clocks. + */ +/** IMO frequency in Hz */ +#define CY_CLK_IMO_FREQ_HZ ( 8000000UL) +/** PILO frequency in Hz */ +#define CY_CLK_PILO_FREQ_HZ ( 32768UL) + +/** WCO frequency in Hz */ +#define CY_CLK_WCO_FREQ_HZ ( 32768UL) + +/** HVILO frequency in Hz */ +#define CY_CLK_HVILO_FREQ_HZ ( 32000UL) + +/** ALTLF frequency in Hz */ +#define CY_CLK_ALTLF_FREQ_HZ ( 32768UL) + +/** Default HFClk frequency in Hz */ +#ifndef CY_CLK_HFCLK0_FREQ_HZ +#define CY_CLK_HFCLK0_FREQ_HZ (100000000UL) +#endif + +/** Default PeriClk frequency in Hz */ +#ifndef CY_CLK_PERICLK_FREQ_HZ +#define CY_CLK_PERICLK_FREQ_HZ (CY_CLK_HFCLK0_FREQ_HZ / 2) +#endif + +/** Default SlowClk system core frequency in Hz */ +#ifndef CY_CLK_SYSTEM_FREQ_HZ +#define CY_CLK_SYSTEM_FREQ_HZ (CY_CLK_PERICLK_FREQ_HZ) +#endif + + +/** Interrupt assignment for CM0+ core. + * On PSoC6 CM0+ core physical interrupt are routed into NVIC through a programmable + * multiplexer. This requires that we define which of the 32 NVIC channels is used + * by which interrupt. This is done here. + */ +#define CY_M0_CORE_IRQ_CHANNEL_US_TICKER ((IRQn_Type)0) +#define CY_M0_CORE_IRQ_CHANNEL_SERIAL ((IRQn_Type)4) +#define CY_M0_CORE_IRQ_CHANNEL_BLE ((IRQn_Type)3) + +/** Identifiers used in allocation of NVIC channels. + */ +#define CY_US_TICKER_IRQN_ID (0x100) +#define CY_SERIAL_IRQN_ID (0x200) +#define CY_BLE_IRQN_ID (0x300) +#define CY_GPIO_IRQN_ID (0x400) +#define CY_LP_TICKER_IRQN_ID (0x500) +#endif diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cmsis.h b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cmsis.h new file mode 100644 index 0000000000..6a55fa317e --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cmsis.h @@ -0,0 +1,24 @@ +/* mbed Microcontroller Library + * A generic CMSIS include header + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#ifndef MBED_CMSIS_H +#define MBED_CMSIS_H + +#include "cy_device_headers.h" +#undef BLE + +#endif diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cy8c6347bzi_bld53.h b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cy8c6347bzi_bld53.h new file mode 100644 index 0000000000..13745170e8 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cy8c6347bzi_bld53.h @@ -0,0 +1,1280 @@ +/***************************************************************************//** +* \file cy8c6347bzi_bld53.h +* +* \brief +* CY8C6347BZI-BLD53 device header +* +* \note +* Generator version: 1.2.0.117 +* Database revision: rev#1034984 +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#ifndef _CY8C6347BZI_BLD53_H_ +#define _CY8C6347BZI_BLD53_H_ + +/** +* \addtogroup group_device CY8C6347BZI-BLD53 +* \{ +*/ + +/** +* \addtogroup Configuration_of_CMSIS +* \{ +*/ + +/******************************************************************************* +* Interrupt Number Definition +*******************************************************************************/ + +typedef enum { +#if ((defined(__GNUC__) && (__ARM_ARCH == 6) && (__ARM_ARCH_6M__ == 1)) || \ + (defined(__ICCARM__) && (__CORE__ == __ARM6M__)) || \ + (defined(__ARMCC_VERSION) && (__TARGET_ARCH_THUMB == 3)) || \ + (defined(__ghs__) && defined(__CORE_CORTEXM0PLUS__))) + /* ARM Cortex-M0+ Core Interrupt Numbers */ + Reset_IRQn = -15, /*!< -15 Reset Vector, invoked on Power up and warm reset */ + NonMaskableInt_IRQn = -14, /*!< -14 Non maskable Interrupt, cannot be stopped or preempted */ + HardFault_IRQn = -13, /*!< -13 Hard Fault, all classes of Fault */ + SVCall_IRQn = -5, /*!< -5 System Service Call via SVC instruction */ + PendSV_IRQn = -2, /*!< -2 Pendable request for system service */ + SysTick_IRQn = -1, /*!< -1 System Tick Timer */ + /* ARM Cortex-M0+ NVIC Mux inputs. Allow routing of device interrupts to the CM0+ NVIC */ + NvicMux0_IRQn = 0, /*!< 0 [DeepSleep] CM0+ NVIC Mux input 0 */ + NvicMux1_IRQn = 1, /*!< 1 [DeepSleep] CM0+ NVIC Mux input 1 */ + NvicMux2_IRQn = 2, /*!< 2 [DeepSleep] CM0+ NVIC Mux input 2 */ + NvicMux3_IRQn = 3, /*!< 3 [DeepSleep] CM0+ NVIC Mux input 3 */ + NvicMux4_IRQn = 4, /*!< 4 [DeepSleep] CM0+ NVIC Mux input 4 */ + NvicMux5_IRQn = 5, /*!< 5 [DeepSleep] CM0+ NVIC Mux input 5 */ + NvicMux6_IRQn = 6, /*!< 6 [DeepSleep] CM0+ NVIC Mux input 6 */ + NvicMux7_IRQn = 7, /*!< 7 [DeepSleep] CM0+ NVIC Mux input 7 */ + NvicMux8_IRQn = 8, /*!< 8 [Active] CM0+ NVIC Mux input 8 */ + NvicMux9_IRQn = 9, /*!< 9 [Active] CM0+ NVIC Mux input 9 */ + NvicMux10_IRQn = 10, /*!< 10 [Active] CM0+ NVIC Mux input 10 */ + NvicMux11_IRQn = 11, /*!< 11 [Active] CM0+ NVIC Mux input 11 */ + NvicMux12_IRQn = 12, /*!< 12 [Active] CM0+ NVIC Mux input 12 */ + NvicMux13_IRQn = 13, /*!< 13 [Active] CM0+ NVIC Mux input 13 */ + NvicMux14_IRQn = 14, /*!< 14 [Active] CM0+ NVIC Mux input 14 */ + NvicMux15_IRQn = 15, /*!< 15 [Active] CM0+ NVIC Mux input 15 */ + NvicMux16_IRQn = 16, /*!< 16 [Active] CM0+ NVIC Mux input 16 */ + NvicMux17_IRQn = 17, /*!< 17 [Active] CM0+ NVIC Mux input 17 */ + NvicMux18_IRQn = 18, /*!< 18 [Active] CM0+ NVIC Mux input 18 */ + NvicMux19_IRQn = 19, /*!< 19 [Active] CM0+ NVIC Mux input 19 */ + NvicMux20_IRQn = 20, /*!< 20 [Active] CM0+ NVIC Mux input 20 */ + NvicMux21_IRQn = 21, /*!< 21 [Active] CM0+ NVIC Mux input 21 */ + NvicMux22_IRQn = 22, /*!< 22 [Active] CM0+ NVIC Mux input 22 */ + NvicMux23_IRQn = 23, /*!< 23 [Active] CM0+ NVIC Mux input 23 */ + NvicMux24_IRQn = 24, /*!< 24 [Active] CM0+ NVIC Mux input 24 */ + NvicMux25_IRQn = 25, /*!< 25 [Active] CM0+ NVIC Mux input 25 */ + NvicMux26_IRQn = 26, /*!< 26 [Active] CM0+ NVIC Mux input 26 */ + NvicMux27_IRQn = 27, /*!< 27 [Active] CM0+ NVIC Mux input 27 */ + NvicMux28_IRQn = 28, /*!< 28 [Active] CM0+ NVIC Mux input 28 */ + NvicMux29_IRQn = 29, /*!< 29 [Active] CM0+ NVIC Mux input 29 */ + NvicMux30_IRQn = 30, /*!< 30 [Active] CM0+ NVIC Mux input 30 */ + NvicMux31_IRQn = 31, /*!< 31 [Active] CM0+ NVIC Mux input 31 */ + unconnected_IRQn = 240 /*!< 240 Unconnected */ +#else + /* ARM Cortex-M4 Core Interrupt Numbers */ + Reset_IRQn = -15, /*!< -15 Reset Vector, invoked on Power up and warm reset */ + NonMaskableInt_IRQn = -14, /*!< -14 Non maskable Interrupt, cannot be stopped or preempted */ + HardFault_IRQn = -13, /*!< -13 Hard Fault, all classes of Fault */ + MemoryManagement_IRQn = -12, /*!< -12 Memory Management, MPU mismatch, including Access Violation and No Match */ + BusFault_IRQn = -11, /*!< -11 Bus Fault, Pre-Fetch-, Memory Access Fault, other address/memory related Fault */ + UsageFault_IRQn = -10, /*!< -10 Usage Fault, i.e. Undef Instruction, Illegal State Transition */ + SVCall_IRQn = -5, /*!< -5 System Service Call via SVC instruction */ + DebugMonitor_IRQn = -4, /*!< -4 Debug Monitor */ + PendSV_IRQn = -2, /*!< -2 Pendable request for system service */ + SysTick_IRQn = -1, /*!< -1 System Tick Timer */ + /* CY8C6347BZI-BLD53 Peripheral Interrupt Numbers */ + ioss_interrupts_gpio_0_IRQn = 0, /*!< 0 [DeepSleep] GPIO Port Interrupt #0 */ + ioss_interrupts_gpio_1_IRQn = 1, /*!< 1 [DeepSleep] GPIO Port Interrupt #1 */ + ioss_interrupts_gpio_2_IRQn = 2, /*!< 2 [DeepSleep] GPIO Port Interrupt #2 */ + ioss_interrupts_gpio_3_IRQn = 3, /*!< 3 [DeepSleep] GPIO Port Interrupt #3 */ + ioss_interrupts_gpio_4_IRQn = 4, /*!< 4 [DeepSleep] GPIO Port Interrupt #4 */ + ioss_interrupts_gpio_5_IRQn = 5, /*!< 5 [DeepSleep] GPIO Port Interrupt #5 */ + ioss_interrupts_gpio_6_IRQn = 6, /*!< 6 [DeepSleep] GPIO Port Interrupt #6 */ + ioss_interrupts_gpio_7_IRQn = 7, /*!< 7 [DeepSleep] GPIO Port Interrupt #7 */ + ioss_interrupts_gpio_8_IRQn = 8, /*!< 8 [DeepSleep] GPIO Port Interrupt #8 */ + ioss_interrupts_gpio_9_IRQn = 9, /*!< 9 [DeepSleep] GPIO Port Interrupt #9 */ + ioss_interrupts_gpio_10_IRQn = 10, /*!< 10 [DeepSleep] GPIO Port Interrupt #10 */ + ioss_interrupts_gpio_11_IRQn = 11, /*!< 11 [DeepSleep] GPIO Port Interrupt #11 */ + ioss_interrupts_gpio_12_IRQn = 12, /*!< 12 [DeepSleep] GPIO Port Interrupt #12 */ + ioss_interrupts_gpio_13_IRQn = 13, /*!< 13 [DeepSleep] GPIO Port Interrupt #13 */ + ioss_interrupts_gpio_14_IRQn = 14, /*!< 14 [DeepSleep] GPIO Port Interrupt #14 */ + ioss_interrupt_gpio_IRQn = 15, /*!< 15 [DeepSleep] GPIO All Ports */ + ioss_interrupt_vdd_IRQn = 16, /*!< 16 [DeepSleep] GPIO Supply Detect Interrupt */ + lpcomp_interrupt_IRQn = 17, /*!< 17 [DeepSleep] Low Power Comparator Interrupt */ + scb_8_interrupt_IRQn = 18, /*!< 18 [DeepSleep] Serial Communication Block #8 (DeepSleep capable) */ + srss_interrupt_mcwdt_0_IRQn = 19, /*!< 19 [DeepSleep] Multi Counter Watchdog Timer interrupt */ + srss_interrupt_mcwdt_1_IRQn = 20, /*!< 20 [DeepSleep] Multi Counter Watchdog Timer interrupt */ + srss_interrupt_backup_IRQn = 21, /*!< 21 [DeepSleep] Backup domain interrupt */ + srss_interrupt_IRQn = 22, /*!< 22 [DeepSleep] Other combined Interrupts for SRSS (LVD, WDT, CLKCAL) */ + pass_interrupt_ctbs_IRQn = 23, /*!< 23 [DeepSleep] CTBm Interrupt (all CTBms) */ + bless_interrupt_IRQn = 24, /*!< 24 [DeepSleep] Bluetooth Radio interrupt */ + cpuss_interrupts_ipc_0_IRQn = 25, /*!< 25 [DeepSleep] CPUSS Inter Process Communication Interrupt #0 */ + cpuss_interrupts_ipc_1_IRQn = 26, /*!< 26 [DeepSleep] CPUSS Inter Process Communication Interrupt #1 */ + cpuss_interrupts_ipc_2_IRQn = 27, /*!< 27 [DeepSleep] CPUSS Inter Process Communication Interrupt #2 */ + cpuss_interrupts_ipc_3_IRQn = 28, /*!< 28 [DeepSleep] CPUSS Inter Process Communication Interrupt #3 */ + cpuss_interrupts_ipc_4_IRQn = 29, /*!< 29 [DeepSleep] CPUSS Inter Process Communication Interrupt #4 */ + cpuss_interrupts_ipc_5_IRQn = 30, /*!< 30 [DeepSleep] CPUSS Inter Process Communication Interrupt #5 */ + cpuss_interrupts_ipc_6_IRQn = 31, /*!< 31 [DeepSleep] CPUSS Inter Process Communication Interrupt #6 */ + cpuss_interrupts_ipc_7_IRQn = 32, /*!< 32 [DeepSleep] CPUSS Inter Process Communication Interrupt #7 */ + cpuss_interrupts_ipc_8_IRQn = 33, /*!< 33 [DeepSleep] CPUSS Inter Process Communication Interrupt #8 */ + cpuss_interrupts_ipc_9_IRQn = 34, /*!< 34 [DeepSleep] CPUSS Inter Process Communication Interrupt #9 */ + cpuss_interrupts_ipc_10_IRQn = 35, /*!< 35 [DeepSleep] CPUSS Inter Process Communication Interrupt #10 */ + cpuss_interrupts_ipc_11_IRQn = 36, /*!< 36 [DeepSleep] CPUSS Inter Process Communication Interrupt #11 */ + cpuss_interrupts_ipc_12_IRQn = 37, /*!< 37 [DeepSleep] CPUSS Inter Process Communication Interrupt #12 */ + cpuss_interrupts_ipc_13_IRQn = 38, /*!< 38 [DeepSleep] CPUSS Inter Process Communication Interrupt #13 */ + cpuss_interrupts_ipc_14_IRQn = 39, /*!< 39 [DeepSleep] CPUSS Inter Process Communication Interrupt #14 */ + cpuss_interrupts_ipc_15_IRQn = 40, /*!< 40 [DeepSleep] CPUSS Inter Process Communication Interrupt #15 */ + scb_0_interrupt_IRQn = 41, /*!< 41 [Active] Serial Communication Block #0 */ + scb_1_interrupt_IRQn = 42, /*!< 42 [Active] Serial Communication Block #1 */ + scb_2_interrupt_IRQn = 43, /*!< 43 [Active] Serial Communication Block #2 */ + scb_3_interrupt_IRQn = 44, /*!< 44 [Active] Serial Communication Block #3 */ + scb_4_interrupt_IRQn = 45, /*!< 45 [Active] Serial Communication Block #4 */ + scb_5_interrupt_IRQn = 46, /*!< 46 [Active] Serial Communication Block #5 */ + scb_6_interrupt_IRQn = 47, /*!< 47 [Active] Serial Communication Block #6 */ + scb_7_interrupt_IRQn = 48, /*!< 48 [Active] Serial Communication Block #7 */ + csd_interrupt_IRQn = 49, /*!< 49 [Active] CSD (Capsense) interrupt */ + cpuss_interrupts_dw0_0_IRQn = 50, /*!< 50 [Active] CPUSS DataWire #0, Channel #0 */ + cpuss_interrupts_dw0_1_IRQn = 51, /*!< 51 [Active] CPUSS DataWire #0, Channel #1 */ + cpuss_interrupts_dw0_2_IRQn = 52, /*!< 52 [Active] CPUSS DataWire #0, Channel #2 */ + cpuss_interrupts_dw0_3_IRQn = 53, /*!< 53 [Active] CPUSS DataWire #0, Channel #3 */ + cpuss_interrupts_dw0_4_IRQn = 54, /*!< 54 [Active] CPUSS DataWire #0, Channel #4 */ + cpuss_interrupts_dw0_5_IRQn = 55, /*!< 55 [Active] CPUSS DataWire #0, Channel #5 */ + cpuss_interrupts_dw0_6_IRQn = 56, /*!< 56 [Active] CPUSS DataWire #0, Channel #6 */ + cpuss_interrupts_dw0_7_IRQn = 57, /*!< 57 [Active] CPUSS DataWire #0, Channel #7 */ + cpuss_interrupts_dw0_8_IRQn = 58, /*!< 58 [Active] CPUSS DataWire #0, Channel #8 */ + cpuss_interrupts_dw0_9_IRQn = 59, /*!< 59 [Active] CPUSS DataWire #0, Channel #9 */ + cpuss_interrupts_dw0_10_IRQn = 60, /*!< 60 [Active] CPUSS DataWire #0, Channel #10 */ + cpuss_interrupts_dw0_11_IRQn = 61, /*!< 61 [Active] CPUSS DataWire #0, Channel #11 */ + cpuss_interrupts_dw0_12_IRQn = 62, /*!< 62 [Active] CPUSS DataWire #0, Channel #12 */ + cpuss_interrupts_dw0_13_IRQn = 63, /*!< 63 [Active] CPUSS DataWire #0, Channel #13 */ + cpuss_interrupts_dw0_14_IRQn = 64, /*!< 64 [Active] CPUSS DataWire #0, Channel #14 */ + cpuss_interrupts_dw0_15_IRQn = 65, /*!< 65 [Active] CPUSS DataWire #0, Channel #15 */ + cpuss_interrupts_dw1_0_IRQn = 66, /*!< 66 [Active] CPUSS DataWire #1, Channel #0 */ + cpuss_interrupts_dw1_1_IRQn = 67, /*!< 67 [Active] CPUSS DataWire #1, Channel #1 */ + cpuss_interrupts_dw1_2_IRQn = 68, /*!< 68 [Active] CPUSS DataWire #1, Channel #2 */ + cpuss_interrupts_dw1_3_IRQn = 69, /*!< 69 [Active] CPUSS DataWire #1, Channel #3 */ + cpuss_interrupts_dw1_4_IRQn = 70, /*!< 70 [Active] CPUSS DataWire #1, Channel #4 */ + cpuss_interrupts_dw1_5_IRQn = 71, /*!< 71 [Active] CPUSS DataWire #1, Channel #5 */ + cpuss_interrupts_dw1_6_IRQn = 72, /*!< 72 [Active] CPUSS DataWire #1, Channel #6 */ + cpuss_interrupts_dw1_7_IRQn = 73, /*!< 73 [Active] CPUSS DataWire #1, Channel #7 */ + cpuss_interrupts_dw1_8_IRQn = 74, /*!< 74 [Active] CPUSS DataWire #1, Channel #8 */ + cpuss_interrupts_dw1_9_IRQn = 75, /*!< 75 [Active] CPUSS DataWire #1, Channel #9 */ + cpuss_interrupts_dw1_10_IRQn = 76, /*!< 76 [Active] CPUSS DataWire #1, Channel #10 */ + cpuss_interrupts_dw1_11_IRQn = 77, /*!< 77 [Active] CPUSS DataWire #1, Channel #11 */ + cpuss_interrupts_dw1_12_IRQn = 78, /*!< 78 [Active] CPUSS DataWire #1, Channel #12 */ + cpuss_interrupts_dw1_13_IRQn = 79, /*!< 79 [Active] CPUSS DataWire #1, Channel #13 */ + cpuss_interrupts_dw1_14_IRQn = 80, /*!< 80 [Active] CPUSS DataWire #1, Channel #14 */ + cpuss_interrupts_dw1_15_IRQn = 81, /*!< 81 [Active] CPUSS DataWire #1, Channel #15 */ + cpuss_interrupts_fault_0_IRQn = 82, /*!< 82 [Active] CPUSS Fault Structure Interrupt #0 */ + cpuss_interrupts_fault_1_IRQn = 83, /*!< 83 [Active] CPUSS Fault Structure Interrupt #1 */ + cpuss_interrupt_crypto_IRQn = 84, /*!< 84 [Active] CRYPTO Accelerator Interrupt */ + cpuss_interrupt_fm_IRQn = 85, /*!< 85 [Active] FLASH Macro Interrupt */ + cpuss_interrupts_cm0_cti_0_IRQn = 86, /*!< 86 [Active] CM0+ CTI #0 */ + cpuss_interrupts_cm0_cti_1_IRQn = 87, /*!< 87 [Active] CM0+ CTI #1 */ + cpuss_interrupts_cm4_cti_0_IRQn = 88, /*!< 88 [Active] CM4 CTI #0 */ + cpuss_interrupts_cm4_cti_1_IRQn = 89, /*!< 89 [Active] CM4 CTI #1 */ + tcpwm_0_interrupts_0_IRQn = 90, /*!< 90 [Active] TCPWM #0, Counter #0 */ + tcpwm_0_interrupts_1_IRQn = 91, /*!< 91 [Active] TCPWM #0, Counter #1 */ + tcpwm_0_interrupts_2_IRQn = 92, /*!< 92 [Active] TCPWM #0, Counter #2 */ + tcpwm_0_interrupts_3_IRQn = 93, /*!< 93 [Active] TCPWM #0, Counter #3 */ + tcpwm_0_interrupts_4_IRQn = 94, /*!< 94 [Active] TCPWM #0, Counter #4 */ + tcpwm_0_interrupts_5_IRQn = 95, /*!< 95 [Active] TCPWM #0, Counter #5 */ + tcpwm_0_interrupts_6_IRQn = 96, /*!< 96 [Active] TCPWM #0, Counter #6 */ + tcpwm_0_interrupts_7_IRQn = 97, /*!< 97 [Active] TCPWM #0, Counter #7 */ + tcpwm_1_interrupts_0_IRQn = 98, /*!< 98 [Active] TCPWM #1, Counter #0 */ + tcpwm_1_interrupts_1_IRQn = 99, /*!< 99 [Active] TCPWM #1, Counter #1 */ + tcpwm_1_interrupts_2_IRQn = 100, /*!< 100 [Active] TCPWM #1, Counter #2 */ + tcpwm_1_interrupts_3_IRQn = 101, /*!< 101 [Active] TCPWM #1, Counter #3 */ + tcpwm_1_interrupts_4_IRQn = 102, /*!< 102 [Active] TCPWM #1, Counter #4 */ + tcpwm_1_interrupts_5_IRQn = 103, /*!< 103 [Active] TCPWM #1, Counter #5 */ + tcpwm_1_interrupts_6_IRQn = 104, /*!< 104 [Active] TCPWM #1, Counter #6 */ + tcpwm_1_interrupts_7_IRQn = 105, /*!< 105 [Active] TCPWM #1, Counter #7 */ + tcpwm_1_interrupts_8_IRQn = 106, /*!< 106 [Active] TCPWM #1, Counter #8 */ + tcpwm_1_interrupts_9_IRQn = 107, /*!< 107 [Active] TCPWM #1, Counter #9 */ + tcpwm_1_interrupts_10_IRQn = 108, /*!< 108 [Active] TCPWM #1, Counter #10 */ + tcpwm_1_interrupts_11_IRQn = 109, /*!< 109 [Active] TCPWM #1, Counter #11 */ + tcpwm_1_interrupts_12_IRQn = 110, /*!< 110 [Active] TCPWM #1, Counter #12 */ + tcpwm_1_interrupts_13_IRQn = 111, /*!< 111 [Active] TCPWM #1, Counter #13 */ + tcpwm_1_interrupts_14_IRQn = 112, /*!< 112 [Active] TCPWM #1, Counter #14 */ + tcpwm_1_interrupts_15_IRQn = 113, /*!< 113 [Active] TCPWM #1, Counter #15 */ + tcpwm_1_interrupts_16_IRQn = 114, /*!< 114 [Active] TCPWM #1, Counter #16 */ + tcpwm_1_interrupts_17_IRQn = 115, /*!< 115 [Active] TCPWM #1, Counter #17 */ + tcpwm_1_interrupts_18_IRQn = 116, /*!< 116 [Active] TCPWM #1, Counter #18 */ + tcpwm_1_interrupts_19_IRQn = 117, /*!< 117 [Active] TCPWM #1, Counter #19 */ + tcpwm_1_interrupts_20_IRQn = 118, /*!< 118 [Active] TCPWM #1, Counter #20 */ + tcpwm_1_interrupts_21_IRQn = 119, /*!< 119 [Active] TCPWM #1, Counter #21 */ + tcpwm_1_interrupts_22_IRQn = 120, /*!< 120 [Active] TCPWM #1, Counter #22 */ + tcpwm_1_interrupts_23_IRQn = 121, /*!< 121 [Active] TCPWM #1, Counter #23 */ + udb_interrupts_0_IRQn = 122, /*!< 122 [Active] UDB Interrupt #0 */ + udb_interrupts_1_IRQn = 123, /*!< 123 [Active] UDB Interrupt #1 */ + udb_interrupts_2_IRQn = 124, /*!< 124 [Active] UDB Interrupt #2 */ + udb_interrupts_3_IRQn = 125, /*!< 125 [Active] UDB Interrupt #3 */ + udb_interrupts_4_IRQn = 126, /*!< 126 [Active] UDB Interrupt #4 */ + udb_interrupts_5_IRQn = 127, /*!< 127 [Active] UDB Interrupt #5 */ + udb_interrupts_6_IRQn = 128, /*!< 128 [Active] UDB Interrupt #6 */ + udb_interrupts_7_IRQn = 129, /*!< 129 [Active] UDB Interrupt #7 */ + udb_interrupts_8_IRQn = 130, /*!< 130 [Active] UDB Interrupt #8 */ + udb_interrupts_9_IRQn = 131, /*!< 131 [Active] UDB Interrupt #9 */ + udb_interrupts_10_IRQn = 132, /*!< 132 [Active] UDB Interrupt #10 */ + udb_interrupts_11_IRQn = 133, /*!< 133 [Active] UDB Interrupt #11 */ + udb_interrupts_12_IRQn = 134, /*!< 134 [Active] UDB Interrupt #12 */ + udb_interrupts_13_IRQn = 135, /*!< 135 [Active] UDB Interrupt #13 */ + udb_interrupts_14_IRQn = 136, /*!< 136 [Active] UDB Interrupt #14 */ + udb_interrupts_15_IRQn = 137, /*!< 137 [Active] UDB Interrupt #15 */ + pass_interrupt_sar_IRQn = 138, /*!< 138 [Active] SAR ADC interrupt */ + audioss_interrupt_i2s_IRQn = 139, /*!< 139 [Active] I2S Audio interrupt */ + audioss_interrupt_pdm_IRQn = 140, /*!< 140 [Active] PDM/PCM Audio interrupt */ + profile_interrupt_IRQn = 141, /*!< 141 [Active] Energy Profiler interrupt */ + smif_interrupt_IRQn = 142, /*!< 142 [Active] Serial Memory Interface interrupt */ + usb_interrupt_hi_IRQn = 143, /*!< 143 [Active] USB Interrupt */ + usb_interrupt_med_IRQn = 144, /*!< 144 [Active] USB Interrupt */ + usb_interrupt_lo_IRQn = 145, /*!< 145 [Active] USB Interrupt */ + pass_interrupt_dacs_IRQn = 146, /*!< 146 [Active] Consolidated interrrupt for all DACs */ + unconnected_IRQn = 240 /*!< 240 Unconnected */ +#endif +} IRQn_Type; + + +#if ((defined(__GNUC__) && (__ARM_ARCH == 6) && (__ARM_ARCH_6M__ == 1)) || \ + (defined(__ICCARM__) && (__CORE__ == __ARM6M__)) || \ + (defined(__ARMCC_VERSION) && (__TARGET_ARCH_THUMB == 3)) || \ + (defined(__ghs__) && defined(__CORE_CORTEXM0PLUS__))) + +/* CY8C6347BZI-BLD53 interrupts that can be routed to the CM0+ NVIC */ +typedef enum { + ioss_interrupts_gpio_0_IRQn = 0, /*!< 0 [DeepSleep] GPIO Port Interrupt #0 */ + ioss_interrupts_gpio_1_IRQn = 1, /*!< 1 [DeepSleep] GPIO Port Interrupt #1 */ + ioss_interrupts_gpio_2_IRQn = 2, /*!< 2 [DeepSleep] GPIO Port Interrupt #2 */ + ioss_interrupts_gpio_3_IRQn = 3, /*!< 3 [DeepSleep] GPIO Port Interrupt #3 */ + ioss_interrupts_gpio_4_IRQn = 4, /*!< 4 [DeepSleep] GPIO Port Interrupt #4 */ + ioss_interrupts_gpio_5_IRQn = 5, /*!< 5 [DeepSleep] GPIO Port Interrupt #5 */ + ioss_interrupts_gpio_6_IRQn = 6, /*!< 6 [DeepSleep] GPIO Port Interrupt #6 */ + ioss_interrupts_gpio_7_IRQn = 7, /*!< 7 [DeepSleep] GPIO Port Interrupt #7 */ + ioss_interrupts_gpio_8_IRQn = 8, /*!< 8 [DeepSleep] GPIO Port Interrupt #8 */ + ioss_interrupts_gpio_9_IRQn = 9, /*!< 9 [DeepSleep] GPIO Port Interrupt #9 */ + ioss_interrupts_gpio_10_IRQn = 10, /*!< 10 [DeepSleep] GPIO Port Interrupt #10 */ + ioss_interrupts_gpio_11_IRQn = 11, /*!< 11 [DeepSleep] GPIO Port Interrupt #11 */ + ioss_interrupts_gpio_12_IRQn = 12, /*!< 12 [DeepSleep] GPIO Port Interrupt #12 */ + ioss_interrupts_gpio_13_IRQn = 13, /*!< 13 [DeepSleep] GPIO Port Interrupt #13 */ + ioss_interrupts_gpio_14_IRQn = 14, /*!< 14 [DeepSleep] GPIO Port Interrupt #14 */ + ioss_interrupt_gpio_IRQn = 15, /*!< 15 [DeepSleep] GPIO All Ports */ + ioss_interrupt_vdd_IRQn = 16, /*!< 16 [DeepSleep] GPIO Supply Detect Interrupt */ + lpcomp_interrupt_IRQn = 17, /*!< 17 [DeepSleep] Low Power Comparator Interrupt */ + scb_8_interrupt_IRQn = 18, /*!< 18 [DeepSleep] Serial Communication Block #8 (DeepSleep capable) */ + srss_interrupt_mcwdt_0_IRQn = 19, /*!< 19 [DeepSleep] Multi Counter Watchdog Timer interrupt */ + srss_interrupt_mcwdt_1_IRQn = 20, /*!< 20 [DeepSleep] Multi Counter Watchdog Timer interrupt */ + srss_interrupt_backup_IRQn = 21, /*!< 21 [DeepSleep] Backup domain interrupt */ + srss_interrupt_IRQn = 22, /*!< 22 [DeepSleep] Other combined Interrupts for SRSS (LVD, WDT, CLKCAL) */ + pass_interrupt_ctbs_IRQn = 23, /*!< 23 [DeepSleep] CTBm Interrupt (all CTBms) */ + bless_interrupt_IRQn = 24, /*!< 24 [DeepSleep] Bluetooth Radio interrupt */ + cpuss_interrupts_ipc_0_IRQn = 25, /*!< 25 [DeepSleep] CPUSS Inter Process Communication Interrupt #0 */ + cpuss_interrupts_ipc_1_IRQn = 26, /*!< 26 [DeepSleep] CPUSS Inter Process Communication Interrupt #1 */ + cpuss_interrupts_ipc_2_IRQn = 27, /*!< 27 [DeepSleep] CPUSS Inter Process Communication Interrupt #2 */ + cpuss_interrupts_ipc_3_IRQn = 28, /*!< 28 [DeepSleep] CPUSS Inter Process Communication Interrupt #3 */ + cpuss_interrupts_ipc_4_IRQn = 29, /*!< 29 [DeepSleep] CPUSS Inter Process Communication Interrupt #4 */ + cpuss_interrupts_ipc_5_IRQn = 30, /*!< 30 [DeepSleep] CPUSS Inter Process Communication Interrupt #5 */ + cpuss_interrupts_ipc_6_IRQn = 31, /*!< 31 [DeepSleep] CPUSS Inter Process Communication Interrupt #6 */ + cpuss_interrupts_ipc_7_IRQn = 32, /*!< 32 [DeepSleep] CPUSS Inter Process Communication Interrupt #7 */ + cpuss_interrupts_ipc_8_IRQn = 33, /*!< 33 [DeepSleep] CPUSS Inter Process Communication Interrupt #8 */ + cpuss_interrupts_ipc_9_IRQn = 34, /*!< 34 [DeepSleep] CPUSS Inter Process Communication Interrupt #9 */ + cpuss_interrupts_ipc_10_IRQn = 35, /*!< 35 [DeepSleep] CPUSS Inter Process Communication Interrupt #10 */ + cpuss_interrupts_ipc_11_IRQn = 36, /*!< 36 [DeepSleep] CPUSS Inter Process Communication Interrupt #11 */ + cpuss_interrupts_ipc_12_IRQn = 37, /*!< 37 [DeepSleep] CPUSS Inter Process Communication Interrupt #12 */ + cpuss_interrupts_ipc_13_IRQn = 38, /*!< 38 [DeepSleep] CPUSS Inter Process Communication Interrupt #13 */ + cpuss_interrupts_ipc_14_IRQn = 39, /*!< 39 [DeepSleep] CPUSS Inter Process Communication Interrupt #14 */ + cpuss_interrupts_ipc_15_IRQn = 40, /*!< 40 [DeepSleep] CPUSS Inter Process Communication Interrupt #15 */ + scb_0_interrupt_IRQn = 41, /*!< 41 [Active] Serial Communication Block #0 */ + scb_1_interrupt_IRQn = 42, /*!< 42 [Active] Serial Communication Block #1 */ + scb_2_interrupt_IRQn = 43, /*!< 43 [Active] Serial Communication Block #2 */ + scb_3_interrupt_IRQn = 44, /*!< 44 [Active] Serial Communication Block #3 */ + scb_4_interrupt_IRQn = 45, /*!< 45 [Active] Serial Communication Block #4 */ + scb_5_interrupt_IRQn = 46, /*!< 46 [Active] Serial Communication Block #5 */ + scb_6_interrupt_IRQn = 47, /*!< 47 [Active] Serial Communication Block #6 */ + scb_7_interrupt_IRQn = 48, /*!< 48 [Active] Serial Communication Block #7 */ + csd_interrupt_IRQn = 49, /*!< 49 [Active] CSD (Capsense) interrupt */ + cpuss_interrupts_dw0_0_IRQn = 50, /*!< 50 [Active] CPUSS DataWire #0, Channel #0 */ + cpuss_interrupts_dw0_1_IRQn = 51, /*!< 51 [Active] CPUSS DataWire #0, Channel #1 */ + cpuss_interrupts_dw0_2_IRQn = 52, /*!< 52 [Active] CPUSS DataWire #0, Channel #2 */ + cpuss_interrupts_dw0_3_IRQn = 53, /*!< 53 [Active] CPUSS DataWire #0, Channel #3 */ + cpuss_interrupts_dw0_4_IRQn = 54, /*!< 54 [Active] CPUSS DataWire #0, Channel #4 */ + cpuss_interrupts_dw0_5_IRQn = 55, /*!< 55 [Active] CPUSS DataWire #0, Channel #5 */ + cpuss_interrupts_dw0_6_IRQn = 56, /*!< 56 [Active] CPUSS DataWire #0, Channel #6 */ + cpuss_interrupts_dw0_7_IRQn = 57, /*!< 57 [Active] CPUSS DataWire #0, Channel #7 */ + cpuss_interrupts_dw0_8_IRQn = 58, /*!< 58 [Active] CPUSS DataWire #0, Channel #8 */ + cpuss_interrupts_dw0_9_IRQn = 59, /*!< 59 [Active] CPUSS DataWire #0, Channel #9 */ + cpuss_interrupts_dw0_10_IRQn = 60, /*!< 60 [Active] CPUSS DataWire #0, Channel #10 */ + cpuss_interrupts_dw0_11_IRQn = 61, /*!< 61 [Active] CPUSS DataWire #0, Channel #11 */ + cpuss_interrupts_dw0_12_IRQn = 62, /*!< 62 [Active] CPUSS DataWire #0, Channel #12 */ + cpuss_interrupts_dw0_13_IRQn = 63, /*!< 63 [Active] CPUSS DataWire #0, Channel #13 */ + cpuss_interrupts_dw0_14_IRQn = 64, /*!< 64 [Active] CPUSS DataWire #0, Channel #14 */ + cpuss_interrupts_dw0_15_IRQn = 65, /*!< 65 [Active] CPUSS DataWire #0, Channel #15 */ + cpuss_interrupts_dw1_0_IRQn = 66, /*!< 66 [Active] CPUSS DataWire #1, Channel #0 */ + cpuss_interrupts_dw1_1_IRQn = 67, /*!< 67 [Active] CPUSS DataWire #1, Channel #1 */ + cpuss_interrupts_dw1_2_IRQn = 68, /*!< 68 [Active] CPUSS DataWire #1, Channel #2 */ + cpuss_interrupts_dw1_3_IRQn = 69, /*!< 69 [Active] CPUSS DataWire #1, Channel #3 */ + cpuss_interrupts_dw1_4_IRQn = 70, /*!< 70 [Active] CPUSS DataWire #1, Channel #4 */ + cpuss_interrupts_dw1_5_IRQn = 71, /*!< 71 [Active] CPUSS DataWire #1, Channel #5 */ + cpuss_interrupts_dw1_6_IRQn = 72, /*!< 72 [Active] CPUSS DataWire #1, Channel #6 */ + cpuss_interrupts_dw1_7_IRQn = 73, /*!< 73 [Active] CPUSS DataWire #1, Channel #7 */ + cpuss_interrupts_dw1_8_IRQn = 74, /*!< 74 [Active] CPUSS DataWire #1, Channel #8 */ + cpuss_interrupts_dw1_9_IRQn = 75, /*!< 75 [Active] CPUSS DataWire #1, Channel #9 */ + cpuss_interrupts_dw1_10_IRQn = 76, /*!< 76 [Active] CPUSS DataWire #1, Channel #10 */ + cpuss_interrupts_dw1_11_IRQn = 77, /*!< 77 [Active] CPUSS DataWire #1, Channel #11 */ + cpuss_interrupts_dw1_12_IRQn = 78, /*!< 78 [Active] CPUSS DataWire #1, Channel #12 */ + cpuss_interrupts_dw1_13_IRQn = 79, /*!< 79 [Active] CPUSS DataWire #1, Channel #13 */ + cpuss_interrupts_dw1_14_IRQn = 80, /*!< 80 [Active] CPUSS DataWire #1, Channel #14 */ + cpuss_interrupts_dw1_15_IRQn = 81, /*!< 81 [Active] CPUSS DataWire #1, Channel #15 */ + cpuss_interrupts_fault_0_IRQn = 82, /*!< 82 [Active] CPUSS Fault Structure Interrupt #0 */ + cpuss_interrupts_fault_1_IRQn = 83, /*!< 83 [Active] CPUSS Fault Structure Interrupt #1 */ + cpuss_interrupt_crypto_IRQn = 84, /*!< 84 [Active] CRYPTO Accelerator Interrupt */ + cpuss_interrupt_fm_IRQn = 85, /*!< 85 [Active] FLASH Macro Interrupt */ + cpuss_interrupts_cm0_cti_0_IRQn = 86, /*!< 86 [Active] CM0+ CTI #0 */ + cpuss_interrupts_cm0_cti_1_IRQn = 87, /*!< 87 [Active] CM0+ CTI #1 */ + cpuss_interrupts_cm4_cti_0_IRQn = 88, /*!< 88 [Active] CM4 CTI #0 */ + cpuss_interrupts_cm4_cti_1_IRQn = 89, /*!< 89 [Active] CM4 CTI #1 */ + tcpwm_0_interrupts_0_IRQn = 90, /*!< 90 [Active] TCPWM #0, Counter #0 */ + tcpwm_0_interrupts_1_IRQn = 91, /*!< 91 [Active] TCPWM #0, Counter #1 */ + tcpwm_0_interrupts_2_IRQn = 92, /*!< 92 [Active] TCPWM #0, Counter #2 */ + tcpwm_0_interrupts_3_IRQn = 93, /*!< 93 [Active] TCPWM #0, Counter #3 */ + tcpwm_0_interrupts_4_IRQn = 94, /*!< 94 [Active] TCPWM #0, Counter #4 */ + tcpwm_0_interrupts_5_IRQn = 95, /*!< 95 [Active] TCPWM #0, Counter #5 */ + tcpwm_0_interrupts_6_IRQn = 96, /*!< 96 [Active] TCPWM #0, Counter #6 */ + tcpwm_0_interrupts_7_IRQn = 97, /*!< 97 [Active] TCPWM #0, Counter #7 */ + tcpwm_1_interrupts_0_IRQn = 98, /*!< 98 [Active] TCPWM #1, Counter #0 */ + tcpwm_1_interrupts_1_IRQn = 99, /*!< 99 [Active] TCPWM #1, Counter #1 */ + tcpwm_1_interrupts_2_IRQn = 100, /*!< 100 [Active] TCPWM #1, Counter #2 */ + tcpwm_1_interrupts_3_IRQn = 101, /*!< 101 [Active] TCPWM #1, Counter #3 */ + tcpwm_1_interrupts_4_IRQn = 102, /*!< 102 [Active] TCPWM #1, Counter #4 */ + tcpwm_1_interrupts_5_IRQn = 103, /*!< 103 [Active] TCPWM #1, Counter #5 */ + tcpwm_1_interrupts_6_IRQn = 104, /*!< 104 [Active] TCPWM #1, Counter #6 */ + tcpwm_1_interrupts_7_IRQn = 105, /*!< 105 [Active] TCPWM #1, Counter #7 */ + tcpwm_1_interrupts_8_IRQn = 106, /*!< 106 [Active] TCPWM #1, Counter #8 */ + tcpwm_1_interrupts_9_IRQn = 107, /*!< 107 [Active] TCPWM #1, Counter #9 */ + tcpwm_1_interrupts_10_IRQn = 108, /*!< 108 [Active] TCPWM #1, Counter #10 */ + tcpwm_1_interrupts_11_IRQn = 109, /*!< 109 [Active] TCPWM #1, Counter #11 */ + tcpwm_1_interrupts_12_IRQn = 110, /*!< 110 [Active] TCPWM #1, Counter #12 */ + tcpwm_1_interrupts_13_IRQn = 111, /*!< 111 [Active] TCPWM #1, Counter #13 */ + tcpwm_1_interrupts_14_IRQn = 112, /*!< 112 [Active] TCPWM #1, Counter #14 */ + tcpwm_1_interrupts_15_IRQn = 113, /*!< 113 [Active] TCPWM #1, Counter #15 */ + tcpwm_1_interrupts_16_IRQn = 114, /*!< 114 [Active] TCPWM #1, Counter #16 */ + tcpwm_1_interrupts_17_IRQn = 115, /*!< 115 [Active] TCPWM #1, Counter #17 */ + tcpwm_1_interrupts_18_IRQn = 116, /*!< 116 [Active] TCPWM #1, Counter #18 */ + tcpwm_1_interrupts_19_IRQn = 117, /*!< 117 [Active] TCPWM #1, Counter #19 */ + tcpwm_1_interrupts_20_IRQn = 118, /*!< 118 [Active] TCPWM #1, Counter #20 */ + tcpwm_1_interrupts_21_IRQn = 119, /*!< 119 [Active] TCPWM #1, Counter #21 */ + tcpwm_1_interrupts_22_IRQn = 120, /*!< 120 [Active] TCPWM #1, Counter #22 */ + tcpwm_1_interrupts_23_IRQn = 121, /*!< 121 [Active] TCPWM #1, Counter #23 */ + udb_interrupts_0_IRQn = 122, /*!< 122 [Active] UDB Interrupt #0 */ + udb_interrupts_1_IRQn = 123, /*!< 123 [Active] UDB Interrupt #1 */ + udb_interrupts_2_IRQn = 124, /*!< 124 [Active] UDB Interrupt #2 */ + udb_interrupts_3_IRQn = 125, /*!< 125 [Active] UDB Interrupt #3 */ + udb_interrupts_4_IRQn = 126, /*!< 126 [Active] UDB Interrupt #4 */ + udb_interrupts_5_IRQn = 127, /*!< 127 [Active] UDB Interrupt #5 */ + udb_interrupts_6_IRQn = 128, /*!< 128 [Active] UDB Interrupt #6 */ + udb_interrupts_7_IRQn = 129, /*!< 129 [Active] UDB Interrupt #7 */ + udb_interrupts_8_IRQn = 130, /*!< 130 [Active] UDB Interrupt #8 */ + udb_interrupts_9_IRQn = 131, /*!< 131 [Active] UDB Interrupt #9 */ + udb_interrupts_10_IRQn = 132, /*!< 132 [Active] UDB Interrupt #10 */ + udb_interrupts_11_IRQn = 133, /*!< 133 [Active] UDB Interrupt #11 */ + udb_interrupts_12_IRQn = 134, /*!< 134 [Active] UDB Interrupt #12 */ + udb_interrupts_13_IRQn = 135, /*!< 135 [Active] UDB Interrupt #13 */ + udb_interrupts_14_IRQn = 136, /*!< 136 [Active] UDB Interrupt #14 */ + udb_interrupts_15_IRQn = 137, /*!< 137 [Active] UDB Interrupt #15 */ + pass_interrupt_sar_IRQn = 138, /*!< 138 [Active] SAR ADC interrupt */ + audioss_interrupt_i2s_IRQn = 139, /*!< 139 [Active] I2S Audio interrupt */ + audioss_interrupt_pdm_IRQn = 140, /*!< 140 [Active] PDM/PCM Audio interrupt */ + profile_interrupt_IRQn = 141, /*!< 141 [Active] Energy Profiler interrupt */ + smif_interrupt_IRQn = 142, /*!< 142 [Active] Serial Memory Interface interrupt */ + usb_interrupt_hi_IRQn = 143, /*!< 143 [Active] USB Interrupt */ + usb_interrupt_med_IRQn = 144, /*!< 144 [Active] USB Interrupt */ + usb_interrupt_lo_IRQn = 145, /*!< 145 [Active] USB Interrupt */ + pass_interrupt_dacs_IRQn = 146, /*!< 146 [Active] Consolidated interrrupt for all DACs */ + disconnected_IRQn = 240 /*!< 240 Disconnected */ +} cy_en_intr_t; + +#endif + +/******************************************************************************* +* Processor and Core Peripheral Section +*******************************************************************************/ + +#if ((defined(__GNUC__) && (__ARM_ARCH == 6) && (__ARM_ARCH_6M__ == 1)) || \ + (defined(__ICCARM__) && (__CORE__ == __ARM6M__)) || \ + (defined(__ARMCC_VERSION) && (__TARGET_ARCH_THUMB == 3)) || \ + (defined(__ghs__) && defined(__CORE_CORTEXM0PLUS__))) + +/* Configuration of the ARM Cortex-M0+ Processor and Core Peripherals */ +#define __CM0PLUS_REV 0x0001U /*!< CM0PLUS Core Revision */ +#define __NVIC_PRIO_BITS 2 /*!< Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +#define __VTOR_PRESENT 1 /*!< Set to 1 if CPU supports Vector Table Offset Register */ +#define __MPU_PRESENT 1 /*!< MPU present or not */ + +/** \} Configuration_of_CMSIS */ + +#include "core_cm0plus.h" /*!< ARM Cortex-M0+ processor and core peripherals */ +#include "system_psoc63.h" /*!< PSoC 63 System */ + +#else + +/* Configuration of the ARM Cortex-M4 Processor and Core Peripherals */ +#define __CM4_REV 0x0001U /*!< CM4 Core Revision */ +#define __NVIC_PRIO_BITS 3 /*!< Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +#define __VTOR_PRESENT 1 /*!< Set to 1 if CPU supports Vector Table Offset Register */ +#define __MPU_PRESENT 1 /*!< MPU present or not */ +#define __FPU_PRESENT 1 /*!< FPU present or not */ +#define __CM0P_PRESENT 1 /*!< CM0P present or not */ + +/** \} Configuration_of_CMSIS */ + +#include "core_cm4.h" /*!< ARM Cortex-M4 processor and core peripherals */ +#include "system_psoc63.h" /*!< PSoC 63 System */ + +#endif + +#include "psoc63_config.h" +#include "gpio_psoc63_116_bga_ble.h" + +/* Memory Blocks */ +#define CY_ROM_BASE 0x00000000UL +#define CY_ROM_SIZE 0x00020000UL +#define CY_SRAM0_BASE 0x08000000UL +#define CY_SRAM0_SIZE 0x00048000UL +#define CY_FLASH_BASE 0x10000000UL +#define CY_FLASH_SIZE 0x00100000UL +#define CY_EM_EEPROM_BASE 0x14000000UL +#define CY_EM_EEPROM_SIZE 0x00008000UL +#define CY_XIP_BASE 0x18000000UL +#define CY_XIP_SIZE 0x08000000UL +#define CY_SFLASH_BASE 0x16000000UL +#define CY_SFLASH_SIZE 0x00008000UL +#define CY_EFUSE_BASE 0x402C0800UL +#define CY_EFUSE_SIZE 0x000000C8UL + +#define CY_DEVICE_PSOC6ABLE2 +#define CY_SILICON_ID 0xE2072100UL +#define CY_HF_CLK_MAX_FREQ 150000000UL + +#define CPUSS_FLASHC_PA_SIZE_LOG2 0x7UL +#define SCB_GET_EZ_DATA_NR(base) 256u +#define SCB_IS_I2C_SLAVE_CAPABLE(base) true +#define SCB_IS_I2C_MASTER_CAPABLE(base) ((base) != SCB8) +#define SCB_IS_I2C_DS_CAPABLE(base) ((base) == SCB8) +#define SCB_IS_SPI_SLAVE_CAPABLE(base) true +#define SCB_IS_SPI_MASTER_CAPABLE(base) ((base) != SCB8) +#define SCB_IS_SPI_DS_CAPABLE(base) ((base) == SCB8) +#define SCB_IS_UART_CAPABLE(base) ((base) != SCB8) + +/* IP List */ +#define CY_IP_MXTCPWM 1u +#define CY_IP_MXTCPWM_INSTANCES 2u +#define CY_IP_MXTCPWM_VERSION 1u +#define CY_IP_MXCSDV2 1u +#define CY_IP_MXCSDV2_INSTANCES 1u +#define CY_IP_MXCSDV2_VERSION 1u +#define CY_IP_MXLCD 1u +#define CY_IP_MXLCD_INSTANCES 1u +#define CY_IP_MXLCD_VERSION 1u +#define CY_IP_MXS40SRSS 1u +#define CY_IP_MXS40SRSS_INSTANCES 1u +#define CY_IP_MXS40SRSS_VERSION 1u +#define CY_IP_MXS40SRSS_RTC 1u +#define CY_IP_MXS40SRSS_RTC_INSTANCES 1u +#define CY_IP_MXS40SRSS_RTC_VERSION 1u +#define CY_IP_MXS40SRSS_MCWDT 1u +#define CY_IP_MXS40SRSS_MCWDT_INSTANCES 2u +#define CY_IP_MXS40SRSS_MCWDT_VERSION 1u +#define CY_IP_MXSCB 1u +#define CY_IP_MXSCB_INSTANCES 9u +#define CY_IP_MXSCB_VERSION 1u +#define CY_IP_MXPERI 1u +#define CY_IP_MXPERI_INSTANCES 1u +#define CY_IP_MXPERI_VERSION 1u +#define CY_IP_MXPERI_TR 1u +#define CY_IP_MXPERI_TR_INSTANCES 1u +#define CY_IP_MXPERI_TR_VERSION 1u +#define CY_IP_M4CPUSS 1u +#define CY_IP_M4CPUSS_INSTANCES 1u +#define CY_IP_M4CPUSS_VERSION 1u +#define CY_IP_M4CPUSS_DMA 1u +#define CY_IP_M4CPUSS_DMA_INSTANCES 2u +#define CY_IP_M4CPUSS_DMA_VERSION 1u +#define CY_IP_MXCRYPTO 1u +#define CY_IP_MXCRYPTO_INSTANCES 1u +#define CY_IP_MXCRYPTO_VERSION 1u +#define CY_IP_MXBLESS 1u +#define CY_IP_MXBLESS_INSTANCES 1u +#define CY_IP_MXBLESS_VERSION 1u +#define CY_IP_MXAUDIOSS 1u +#define CY_IP_MXAUDIOSS_INSTANCES 1u +#define CY_IP_MXAUDIOSS_VERSION 1u +#define CY_IP_MXLPCOMP 1u +#define CY_IP_MXLPCOMP_INSTANCES 1u +#define CY_IP_MXLPCOMP_VERSION 1u +#define CY_IP_MXS40PASS 1u +#define CY_IP_MXS40PASS_INSTANCES 1u +#define CY_IP_MXS40PASS_VERSION 1u +#define CY_IP_MXS40PASS_SAR 1u +#define CY_IP_MXS40PASS_SAR_INSTANCES 16u +#define CY_IP_MXS40PASS_SAR_VERSION 1u +#define CY_IP_MXS40PASS_CTDAC 1u +#define CY_IP_MXS40PASS_CTDAC_INSTANCES 1u +#define CY_IP_MXS40PASS_CTDAC_VERSION 1u +#define CY_IP_MXS40PASS_CTB 1u +#define CY_IP_MXS40PASS_CTB_INSTANCES 1u +#define CY_IP_MXS40PASS_CTB_VERSION 1u +#define CY_IP_MXSMIF 1u +#define CY_IP_MXSMIF_INSTANCES 1u +#define CY_IP_MXSMIF_VERSION 1u +#define CY_IP_MXS40IOSS 1u +#define CY_IP_MXS40IOSS_INSTANCES 1u +#define CY_IP_MXS40IOSS_VERSION 1u +#define CY_IP_MXEFUSE 1u +#define CY_IP_MXEFUSE_INSTANCES 1u +#define CY_IP_MXEFUSE_VERSION 1u +#define CY_IP_MXUDB 1u +#define CY_IP_MXUDB_INSTANCES 1u +#define CY_IP_MXUDB_VERSION 1u +#define CY_IP_MXPROFILE 1u +#define CY_IP_MXPROFILE_INSTANCES 1u +#define CY_IP_MXPROFILE_VERSION 1u + +/* Include IP definitions */ +#include "cyip_sflash.h" +#include "cyip_peri.h" +#include "cyip_crypto.h" +#include "cyip_cpuss.h" +#include "cyip_fault.h" +#include "cyip_ipc.h" +#include "cyip_prot.h" +#include "cyip_flashc.h" +#include "cyip_srss.h" +#include "cyip_backup.h" +#include "cyip_dw.h" +#include "cyip_efuse.h" +#include "cyip_efuse_data.h" +#include "cyip_profile.h" +#include "cyip_hsiom.h" +#include "cyip_gpio.h" +#include "cyip_smartio.h" +#include "cyip_udb.h" +#include "cyip_lpcomp.h" +#include "cyip_csd.h" +#include "cyip_tcpwm.h" +#include "cyip_lcd.h" +#include "cyip_ble.h" +#include "cyip_smif.h" +#include "cyip_scb.h" +#include "cyip_ctbm.h" +#include "cyip_ctdac.h" +#include "cyip_sar.h" +#include "cyip_pass.h" +#include "cyip_i2s.h" +#include "cyip_pdm.h" + +/******************************************************************************* +* SFLASH +*******************************************************************************/ + +#define SFLASH_BASE 0x16000000UL +#define SFLASH ((SFLASH_Type*) SFLASH_BASE) /* 0x16000000 */ + +/******************************************************************************* +* PERI +*******************************************************************************/ + +#define PERI_BASE 0x40010000UL +#define PERI_PPU_GR_MMIO0_BASE 0x40015000UL +#define PERI_PPU_GR_MMIO1_BASE 0x40015040UL +#define PERI_PPU_GR_MMIO2_BASE 0x40015080UL +#define PERI_PPU_GR_MMIO3_BASE 0x400150C0UL +#define PERI_PPU_GR_MMIO4_BASE 0x40015100UL +#define PERI_PPU_GR_MMIO6_BASE 0x40015180UL +#define PERI_PPU_GR_MMIO9_BASE 0x40015240UL +#define PERI_PPU_GR_MMIO10_BASE 0x40015280UL +#define PERI_GR_PPU_SL_PERI_GR1_BASE 0x40100000UL +#define PERI_GR_PPU_SL_CRYPTO_BASE 0x40100040UL +#define PERI_GR_PPU_SL_PERI_GR2_BASE 0x40200000UL +#define PERI_GR_PPU_SL_CPUSS_BASE 0x40200040UL +#define PERI_GR_PPU_SL_FAULT_BASE 0x40200080UL +#define PERI_GR_PPU_SL_IPC_BASE 0x402000C0UL +#define PERI_GR_PPU_SL_PROT_BASE 0x40200100UL +#define PERI_GR_PPU_SL_FLASHC_BASE 0x40200140UL +#define PERI_GR_PPU_SL_SRSS_BASE 0x40200180UL +#define PERI_GR_PPU_SL_BACKUP_BASE 0x402001C0UL +#define PERI_GR_PPU_SL_DW0_BASE 0x40200200UL +#define PERI_GR_PPU_SL_DW1_BASE 0x40200240UL +#define PERI_GR_PPU_SL_EFUSE_BASE 0x40200300UL +#define PERI_GR_PPU_SL_PROFILE_BASE 0x40200340UL +#define PERI_GR_PPU_RG_IPC_STRUCT0_BASE 0x40201000UL +#define PERI_GR_PPU_RG_IPC_STRUCT1_BASE 0x40201040UL +#define PERI_GR_PPU_RG_IPC_STRUCT2_BASE 0x40201080UL +#define PERI_GR_PPU_RG_IPC_STRUCT3_BASE 0x402010C0UL +#define PERI_GR_PPU_RG_IPC_STRUCT4_BASE 0x40201100UL +#define PERI_GR_PPU_RG_IPC_STRUCT5_BASE 0x40201140UL +#define PERI_GR_PPU_RG_IPC_STRUCT6_BASE 0x40201180UL +#define PERI_GR_PPU_RG_IPC_STRUCT7_BASE 0x402011C0UL +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT0_BASE 0x40201200UL +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT1_BASE 0x40201240UL +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT2_BASE 0x40201280UL +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT3_BASE 0x402012C0UL +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT4_BASE 0x40201300UL +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT5_BASE 0x40201340UL +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT6_BASE 0x40201380UL +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT7_BASE 0x402013C0UL +#define PERI_GR_PPU_RG_DW0_DW_CH_STRUCT0_BASE 0x40201400UL +#define PERI_GR_PPU_RG_DW0_DW_CH_STRUCT1_BASE 0x40201440UL +#define PERI_GR_PPU_RG_DW0_DW_CH_STRUCT2_BASE 0x40201480UL +#define PERI_GR_PPU_RG_DW0_DW_CH_STRUCT3_BASE 0x402014C0UL +#define PERI_GR_PPU_RG_DW1_DW_CH_STRUCT0_BASE 0x40201500UL +#define PERI_GR_PPU_RG_DW1_DW_CH_STRUCT1_BASE 0x40201540UL +#define PERI_GR_PPU_RG_DW1_DW_CH_STRUCT2_BASE 0x40201580UL +#define PERI_GR_PPU_RG_DW1_DW_CH_STRUCT3_BASE 0x402015C0UL +#define PERI_GR_PPU_RG_SMPU_BASE 0x40201600UL +#define PERI_GR_PPU_RG_MPU_CM0P_BASE 0x40201640UL +#define PERI_GR_PPU_RG_MPU_CRYPTO_BASE 0x40201680UL +#define PERI_GR_PPU_RG_MPU_CM4_BASE 0x402016C0UL +#define PERI_GR_PPU_RG_MPU_TC_BASE 0x40201700UL +#define PERI_GR_PPU_SL_PERI_GR3_BASE 0x40300000UL +#define PERI_GR_PPU_SL_HSIOM_BASE 0x40300040UL +#define PERI_GR_PPU_SL_GPIO_BASE 0x40300080UL +#define PERI_GR_PPU_SL_SMARTIO_BASE 0x403000C0UL +#define PERI_GR_PPU_SL_UDB_BASE 0x40300100UL +#define PERI_GR_PPU_SL_LPCOMP_BASE 0x40300140UL +#define PERI_GR_PPU_SL_CSD_BASE 0x40300180UL +#define PERI_GR_PPU_SL_TCPWM0_BASE 0x40300200UL +#define PERI_GR_PPU_SL_TCPWM1_BASE 0x40300240UL +#define PERI_GR_PPU_SL_LCD_BASE 0x40300280UL +#define PERI_GR_PPU_SL_BLE_BASE 0x403002C0UL +#define PERI_GR_PPU_SL_USBFS_BASE 0x40300300UL +#define PERI_GR_PPU_SL_PERI_GR4_BASE 0x40400000UL +#define PERI_GR_PPU_SL_SMIF_BASE 0x40400080UL +#define PERI_GR_PPU_SL_PERI_GR6_BASE 0x40600000UL +#define PERI_GR_PPU_SL_SCB0_BASE 0x40600040UL +#define PERI_GR_PPU_SL_SCB1_BASE 0x40600080UL +#define PERI_GR_PPU_SL_SCB2_BASE 0x406000C0UL +#define PERI_GR_PPU_SL_SCB3_BASE 0x40600100UL +#define PERI_GR_PPU_SL_SCB4_BASE 0x40600140UL +#define PERI_GR_PPU_SL_SCB5_BASE 0x40600180UL +#define PERI_GR_PPU_SL_SCB6_BASE 0x406001C0UL +#define PERI_GR_PPU_SL_SCB7_BASE 0x40600200UL +#define PERI_GR_PPU_SL_SCB8_BASE 0x40600240UL +#define PERI_GR_PPU_SL_PERI_GR9_BASE 0x41000000UL +#define PERI_GR_PPU_SL_PASS_BASE 0x41000040UL +#define PERI_GR_PPU_SL_PERI_GR10_BASE 0x42A00000UL +#define PERI_GR_PPU_SL_I2S_BASE 0x42A00040UL +#define PERI_GR_PPU_SL_PDM_BASE 0x42A00080UL +#define PERI ((PERI_Type*) PERI_BASE) /* 0x40010000 */ +#define PERI_GR0 ((PERI_GR_Type*) &PERI->GR[0]) /* 0x40010000 */ +#define PERI_GR1 ((PERI_GR_Type*) &PERI->GR[1]) /* 0x40010040 */ +#define PERI_GR2 ((PERI_GR_Type*) &PERI->GR[2]) /* 0x40010080 */ +#define PERI_GR3 ((PERI_GR_Type*) &PERI->GR[3]) /* 0x400100C0 */ +#define PERI_GR4 ((PERI_GR_Type*) &PERI->GR[4]) /* 0x40010100 */ +#define PERI_GR6 ((PERI_GR_Type*) &PERI->GR[6]) /* 0x40010180 */ +#define PERI_GR9 ((PERI_GR_Type*) &PERI->GR[9]) /* 0x40010240 */ +#define PERI_GR10 ((PERI_GR_Type*) &PERI->GR[10]) /* 0x40010280 */ +#define PERI_TR_GR0 ((PERI_TR_GR_Type*) &PERI->TR_GR[0]) /* 0x40012000 */ +#define PERI_TR_GR1 ((PERI_TR_GR_Type*) &PERI->TR_GR[1]) /* 0x40012200 */ +#define PERI_TR_GR2 ((PERI_TR_GR_Type*) &PERI->TR_GR[2]) /* 0x40012400 */ +#define PERI_TR_GR3 ((PERI_TR_GR_Type*) &PERI->TR_GR[3]) /* 0x40012600 */ +#define PERI_TR_GR4 ((PERI_TR_GR_Type*) &PERI->TR_GR[4]) /* 0x40012800 */ +#define PERI_TR_GR5 ((PERI_TR_GR_Type*) &PERI->TR_GR[5]) /* 0x40012A00 */ +#define PERI_TR_GR6 ((PERI_TR_GR_Type*) &PERI->TR_GR[6]) /* 0x40012C00 */ +#define PERI_TR_GR7 ((PERI_TR_GR_Type*) &PERI->TR_GR[7]) /* 0x40012E00 */ +#define PERI_TR_GR8 ((PERI_TR_GR_Type*) &PERI->TR_GR[8]) /* 0x40013000 */ +#define PERI_TR_GR9 ((PERI_TR_GR_Type*) &PERI->TR_GR[9]) /* 0x40013200 */ +#define PERI_TR_GR10 ((PERI_TR_GR_Type*) &PERI->TR_GR[10]) /* 0x40013400 */ +#define PERI_TR_GR11 ((PERI_TR_GR_Type*) &PERI->TR_GR[11]) /* 0x40013600 */ +#define PERI_TR_GR12 ((PERI_TR_GR_Type*) &PERI->TR_GR[12]) /* 0x40013800 */ +#define PERI_TR_GR13 ((PERI_TR_GR_Type*) &PERI->TR_GR[13]) /* 0x40013A00 */ +#define PERI_TR_GR14 ((PERI_TR_GR_Type*) &PERI->TR_GR[14]) /* 0x40013C00 */ +#define PERI_PPU_PR0 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[0]) /* 0x40014000 */ +#define PERI_PPU_PR1 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[1]) /* 0x40014040 */ +#define PERI_PPU_PR2 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[2]) /* 0x40014080 */ +#define PERI_PPU_PR3 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[3]) /* 0x400140C0 */ +#define PERI_PPU_PR4 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[4]) /* 0x40014100 */ +#define PERI_PPU_PR5 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[5]) /* 0x40014140 */ +#define PERI_PPU_PR6 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[6]) /* 0x40014180 */ +#define PERI_PPU_PR7 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[7]) /* 0x400141C0 */ +#define PERI_PPU_PR8 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[8]) /* 0x40014200 */ +#define PERI_PPU_PR9 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[9]) /* 0x40014240 */ +#define PERI_PPU_PR10 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[10]) /* 0x40014280 */ +#define PERI_PPU_PR11 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[11]) /* 0x400142C0 */ +#define PERI_PPU_PR12 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[12]) /* 0x40014300 */ +#define PERI_PPU_PR13 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[13]) /* 0x40014340 */ +#define PERI_PPU_PR14 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[14]) /* 0x40014380 */ +#define PERI_PPU_PR15 ((PERI_PPU_PR_Type*) &PERI->PPU_PR[15]) /* 0x400143C0 */ +#define PERI_PPU_GR0 ((PERI_PPU_GR_Type*) &PERI->PPU_GR[0]) /* 0x40015000 */ +#define PERI_PPU_GR1 ((PERI_PPU_GR_Type*) &PERI->PPU_GR[1]) /* 0x40015040 */ +#define PERI_PPU_GR2 ((PERI_PPU_GR_Type*) &PERI->PPU_GR[2]) /* 0x40015080 */ +#define PERI_PPU_GR3 ((PERI_PPU_GR_Type*) &PERI->PPU_GR[3]) /* 0x400150C0 */ +#define PERI_PPU_GR4 ((PERI_PPU_GR_Type*) &PERI->PPU_GR[4]) /* 0x40015100 */ +#define PERI_PPU_GR6 ((PERI_PPU_GR_Type*) &PERI->PPU_GR[6]) /* 0x40015180 */ +#define PERI_PPU_GR9 ((PERI_PPU_GR_Type*) &PERI->PPU_GR[9]) /* 0x40015240 */ +#define PERI_PPU_GR10 ((PERI_PPU_GR_Type*) &PERI->PPU_GR[10]) /* 0x40015280 */ +#define PERI_PPU_GR_MMIO0 ((PERI_PPU_GR_Type*) PERI_PPU_GR_MMIO0_BASE) /* 0x40015000 */ +#define PERI_PPU_GR_MMIO1 ((PERI_PPU_GR_Type*) PERI_PPU_GR_MMIO1_BASE) /* 0x40015040 */ +#define PERI_PPU_GR_MMIO2 ((PERI_PPU_GR_Type*) PERI_PPU_GR_MMIO2_BASE) /* 0x40015080 */ +#define PERI_PPU_GR_MMIO3 ((PERI_PPU_GR_Type*) PERI_PPU_GR_MMIO3_BASE) /* 0x400150C0 */ +#define PERI_PPU_GR_MMIO4 ((PERI_PPU_GR_Type*) PERI_PPU_GR_MMIO4_BASE) /* 0x40015100 */ +#define PERI_PPU_GR_MMIO6 ((PERI_PPU_GR_Type*) PERI_PPU_GR_MMIO6_BASE) /* 0x40015180 */ +#define PERI_PPU_GR_MMIO9 ((PERI_PPU_GR_Type*) PERI_PPU_GR_MMIO9_BASE) /* 0x40015240 */ +#define PERI_PPU_GR_MMIO10 ((PERI_PPU_GR_Type*) PERI_PPU_GR_MMIO10_BASE) /* 0x40015280 */ +#define PERI_GR_PPU_SL_PERI_GR1 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_PERI_GR1_BASE) /* 0x40100000 */ +#define PERI_GR_PPU_SL_CRYPTO ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_CRYPTO_BASE) /* 0x40100040 */ +#define PERI_GR_PPU_SL_PERI_GR2 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_PERI_GR2_BASE) /* 0x40200000 */ +#define PERI_GR_PPU_SL_CPUSS ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_CPUSS_BASE) /* 0x40200040 */ +#define PERI_GR_PPU_SL_FAULT ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_FAULT_BASE) /* 0x40200080 */ +#define PERI_GR_PPU_SL_IPC ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_IPC_BASE) /* 0x402000C0 */ +#define PERI_GR_PPU_SL_PROT ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_PROT_BASE) /* 0x40200100 */ +#define PERI_GR_PPU_SL_FLASHC ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_FLASHC_BASE) /* 0x40200140 */ +#define PERI_GR_PPU_SL_SRSS ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_SRSS_BASE) /* 0x40200180 */ +#define PERI_GR_PPU_SL_BACKUP ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_BACKUP_BASE) /* 0x402001C0 */ +#define PERI_GR_PPU_SL_DW0 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_DW0_BASE) /* 0x40200200 */ +#define PERI_GR_PPU_SL_DW1 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_DW1_BASE) /* 0x40200240 */ +#define PERI_GR_PPU_SL_EFUSE ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_EFUSE_BASE) /* 0x40200300 */ +#define PERI_GR_PPU_SL_PROFILE ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_PROFILE_BASE) /* 0x40200340 */ +#define PERI_GR_PPU_RG_IPC_STRUCT0 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_STRUCT0_BASE) /* 0x40201000 */ +#define PERI_GR_PPU_RG_IPC_STRUCT1 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_STRUCT1_BASE) /* 0x40201040 */ +#define PERI_GR_PPU_RG_IPC_STRUCT2 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_STRUCT2_BASE) /* 0x40201080 */ +#define PERI_GR_PPU_RG_IPC_STRUCT3 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_STRUCT3_BASE) /* 0x402010C0 */ +#define PERI_GR_PPU_RG_IPC_STRUCT4 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_STRUCT4_BASE) /* 0x40201100 */ +#define PERI_GR_PPU_RG_IPC_STRUCT5 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_STRUCT5_BASE) /* 0x40201140 */ +#define PERI_GR_PPU_RG_IPC_STRUCT6 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_STRUCT6_BASE) /* 0x40201180 */ +#define PERI_GR_PPU_RG_IPC_STRUCT7 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_STRUCT7_BASE) /* 0x402011C0 */ +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT0 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_INTR_STRUCT0_BASE) /* 0x40201200 */ +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT1 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_INTR_STRUCT1_BASE) /* 0x40201240 */ +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT2 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_INTR_STRUCT2_BASE) /* 0x40201280 */ +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT3 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_INTR_STRUCT3_BASE) /* 0x402012C0 */ +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT4 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_INTR_STRUCT4_BASE) /* 0x40201300 */ +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT5 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_INTR_STRUCT5_BASE) /* 0x40201340 */ +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT6 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_INTR_STRUCT6_BASE) /* 0x40201380 */ +#define PERI_GR_PPU_RG_IPC_INTR_STRUCT7 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_IPC_INTR_STRUCT7_BASE) /* 0x402013C0 */ +#define PERI_GR_PPU_RG_DW0_DW_CH_STRUCT0 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_DW0_DW_CH_STRUCT0_BASE) /* 0x40201400 */ +#define PERI_GR_PPU_RG_DW0_DW_CH_STRUCT1 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_DW0_DW_CH_STRUCT1_BASE) /* 0x40201440 */ +#define PERI_GR_PPU_RG_DW0_DW_CH_STRUCT2 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_DW0_DW_CH_STRUCT2_BASE) /* 0x40201480 */ +#define PERI_GR_PPU_RG_DW0_DW_CH_STRUCT3 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_DW0_DW_CH_STRUCT3_BASE) /* 0x402014C0 */ +#define PERI_GR_PPU_RG_DW1_DW_CH_STRUCT0 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_DW1_DW_CH_STRUCT0_BASE) /* 0x40201500 */ +#define PERI_GR_PPU_RG_DW1_DW_CH_STRUCT1 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_DW1_DW_CH_STRUCT1_BASE) /* 0x40201540 */ +#define PERI_GR_PPU_RG_DW1_DW_CH_STRUCT2 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_DW1_DW_CH_STRUCT2_BASE) /* 0x40201580 */ +#define PERI_GR_PPU_RG_DW1_DW_CH_STRUCT3 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_DW1_DW_CH_STRUCT3_BASE) /* 0x402015C0 */ +#define PERI_GR_PPU_RG_SMPU ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_SMPU_BASE) /* 0x40201600 */ +#define PERI_GR_PPU_RG_MPU_CM0P ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_MPU_CM0P_BASE) /* 0x40201640 */ +#define PERI_GR_PPU_RG_MPU_CRYPTO ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_MPU_CRYPTO_BASE) /* 0x40201680 */ +#define PERI_GR_PPU_RG_MPU_CM4 ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_MPU_CM4_BASE) /* 0x402016C0 */ +#define PERI_GR_PPU_RG_MPU_TC ((PERI_GR_PPU_RG_Type*) PERI_GR_PPU_RG_MPU_TC_BASE) /* 0x40201700 */ +#define PERI_GR_PPU_SL_PERI_GR3 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_PERI_GR3_BASE) /* 0x40300000 */ +#define PERI_GR_PPU_SL_HSIOM ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_HSIOM_BASE) /* 0x40300040 */ +#define PERI_GR_PPU_SL_GPIO ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_GPIO_BASE) /* 0x40300080 */ +#define PERI_GR_PPU_SL_SMARTIO ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_SMARTIO_BASE) /* 0x403000C0 */ +#define PERI_GR_PPU_SL_UDB ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_UDB_BASE) /* 0x40300100 */ +#define PERI_GR_PPU_SL_LPCOMP ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_LPCOMP_BASE) /* 0x40300140 */ +#define PERI_GR_PPU_SL_CSD ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_CSD_BASE) /* 0x40300180 */ +#define PERI_GR_PPU_SL_TCPWM0 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_TCPWM0_BASE) /* 0x40300200 */ +#define PERI_GR_PPU_SL_TCPWM1 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_TCPWM1_BASE) /* 0x40300240 */ +#define PERI_GR_PPU_SL_LCD ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_LCD_BASE) /* 0x40300280 */ +#define PERI_GR_PPU_SL_BLE ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_BLE_BASE) /* 0x403002C0 */ +#define PERI_GR_PPU_SL_USBFS ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_USBFS_BASE) /* 0x40300300 */ +#define PERI_GR_PPU_SL_PERI_GR4 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_PERI_GR4_BASE) /* 0x40400000 */ +#define PERI_GR_PPU_SL_SMIF ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_SMIF_BASE) /* 0x40400080 */ +#define PERI_GR_PPU_SL_PERI_GR6 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_PERI_GR6_BASE) /* 0x40600000 */ +#define PERI_GR_PPU_SL_SCB0 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_SCB0_BASE) /* 0x40600040 */ +#define PERI_GR_PPU_SL_SCB1 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_SCB1_BASE) /* 0x40600080 */ +#define PERI_GR_PPU_SL_SCB2 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_SCB2_BASE) /* 0x406000C0 */ +#define PERI_GR_PPU_SL_SCB3 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_SCB3_BASE) /* 0x40600100 */ +#define PERI_GR_PPU_SL_SCB4 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_SCB4_BASE) /* 0x40600140 */ +#define PERI_GR_PPU_SL_SCB5 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_SCB5_BASE) /* 0x40600180 */ +#define PERI_GR_PPU_SL_SCB6 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_SCB6_BASE) /* 0x406001C0 */ +#define PERI_GR_PPU_SL_SCB7 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_SCB7_BASE) /* 0x40600200 */ +#define PERI_GR_PPU_SL_SCB8 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_SCB8_BASE) /* 0x40600240 */ +#define PERI_GR_PPU_SL_PERI_GR9 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_PERI_GR9_BASE) /* 0x41000000 */ +#define PERI_GR_PPU_SL_PASS ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_PASS_BASE) /* 0x41000040 */ +#define PERI_GR_PPU_SL_PERI_GR10 ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_PERI_GR10_BASE) /* 0x42A00000 */ +#define PERI_GR_PPU_SL_I2S ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_I2S_BASE) /* 0x42A00040 */ +#define PERI_GR_PPU_SL_PDM ((PERI_GR_PPU_SL_Type*) PERI_GR_PPU_SL_PDM_BASE) /* 0x42A00080 */ + +/******************************************************************************* +* CRYPTO +*******************************************************************************/ + +#define CRYPTO_BASE 0x40110000UL +#define CRYPTO ((CRYPTO_Type*) CRYPTO_BASE) /* 0x40110000 */ + +/******************************************************************************* +* CPUSS +*******************************************************************************/ + +#define CPUSS_BASE 0x40210000UL +#define CPUSS ((CPUSS_Type*) CPUSS_BASE) /* 0x40210000 */ + +/******************************************************************************* +* FAULT +*******************************************************************************/ + +#define FAULT_BASE 0x40220000UL +#define FAULT ((FAULT_Type*) FAULT_BASE) /* 0x40220000 */ +#define FAULT_STRUCT0 ((FAULT_STRUCT_Type*) &FAULT->STRUCT[0]) /* 0x40220000 */ +#define FAULT_STRUCT1 ((FAULT_STRUCT_Type*) &FAULT->STRUCT[1]) /* 0x40220100 */ + +/******************************************************************************* +* IPC +*******************************************************************************/ + +#define IPC_BASE 0x40230000UL +#define IPC ((IPC_Type*) IPC_BASE) /* 0x40230000 */ +#define IPC_STRUCT0 ((IPC_STRUCT_Type*) &IPC->STRUCT[0]) /* 0x40230000 */ +#define IPC_STRUCT1 ((IPC_STRUCT_Type*) &IPC->STRUCT[1]) /* 0x40230020 */ +#define IPC_STRUCT2 ((IPC_STRUCT_Type*) &IPC->STRUCT[2]) /* 0x40230040 */ +#define IPC_STRUCT3 ((IPC_STRUCT_Type*) &IPC->STRUCT[3]) /* 0x40230060 */ +#define IPC_STRUCT4 ((IPC_STRUCT_Type*) &IPC->STRUCT[4]) /* 0x40230080 */ +#define IPC_STRUCT5 ((IPC_STRUCT_Type*) &IPC->STRUCT[5]) /* 0x402300A0 */ +#define IPC_STRUCT6 ((IPC_STRUCT_Type*) &IPC->STRUCT[6]) /* 0x402300C0 */ +#define IPC_STRUCT7 ((IPC_STRUCT_Type*) &IPC->STRUCT[7]) /* 0x402300E0 */ +#define IPC_STRUCT8 ((IPC_STRUCT_Type*) &IPC->STRUCT[8]) /* 0x40230100 */ +#define IPC_STRUCT9 ((IPC_STRUCT_Type*) &IPC->STRUCT[9]) /* 0x40230120 */ +#define IPC_STRUCT10 ((IPC_STRUCT_Type*) &IPC->STRUCT[10]) /* 0x40230140 */ +#define IPC_STRUCT11 ((IPC_STRUCT_Type*) &IPC->STRUCT[11]) /* 0x40230160 */ +#define IPC_STRUCT12 ((IPC_STRUCT_Type*) &IPC->STRUCT[12]) /* 0x40230180 */ +#define IPC_STRUCT13 ((IPC_STRUCT_Type*) &IPC->STRUCT[13]) /* 0x402301A0 */ +#define IPC_STRUCT14 ((IPC_STRUCT_Type*) &IPC->STRUCT[14]) /* 0x402301C0 */ +#define IPC_STRUCT15 ((IPC_STRUCT_Type*) &IPC->STRUCT[15]) /* 0x402301E0 */ +#define IPC_INTR_STRUCT0 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[0]) /* 0x40231000 */ +#define IPC_INTR_STRUCT1 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[1]) /* 0x40231020 */ +#define IPC_INTR_STRUCT2 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[2]) /* 0x40231040 */ +#define IPC_INTR_STRUCT3 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[3]) /* 0x40231060 */ +#define IPC_INTR_STRUCT4 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[4]) /* 0x40231080 */ +#define IPC_INTR_STRUCT5 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[5]) /* 0x402310A0 */ +#define IPC_INTR_STRUCT6 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[6]) /* 0x402310C0 */ +#define IPC_INTR_STRUCT7 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[7]) /* 0x402310E0 */ +#define IPC_INTR_STRUCT8 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[8]) /* 0x40231100 */ +#define IPC_INTR_STRUCT9 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[9]) /* 0x40231120 */ +#define IPC_INTR_STRUCT10 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[10]) /* 0x40231140 */ +#define IPC_INTR_STRUCT11 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[11]) /* 0x40231160 */ +#define IPC_INTR_STRUCT12 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[12]) /* 0x40231180 */ +#define IPC_INTR_STRUCT13 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[13]) /* 0x402311A0 */ +#define IPC_INTR_STRUCT14 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[14]) /* 0x402311C0 */ +#define IPC_INTR_STRUCT15 ((IPC_INTR_STRUCT_Type*) &IPC->INTR_STRUCT[15]) /* 0x402311E0 */ + +/******************************************************************************* +* PROT +*******************************************************************************/ + +#define PROT_BASE 0x40240000UL +#define PROT ((PROT_Type*) PROT_BASE) /* 0x40240000 */ +#define PROT_SMPU_SMPU_STRUCT0 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[0]) /* 0x40242000 */ +#define PROT_SMPU_SMPU_STRUCT1 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[1]) /* 0x40242040 */ +#define PROT_SMPU_SMPU_STRUCT2 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[2]) /* 0x40242080 */ +#define PROT_SMPU_SMPU_STRUCT3 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[3]) /* 0x402420C0 */ +#define PROT_SMPU_SMPU_STRUCT4 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[4]) /* 0x40242100 */ +#define PROT_SMPU_SMPU_STRUCT5 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[5]) /* 0x40242140 */ +#define PROT_SMPU_SMPU_STRUCT6 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[6]) /* 0x40242180 */ +#define PROT_SMPU_SMPU_STRUCT7 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[7]) /* 0x402421C0 */ +#define PROT_SMPU_SMPU_STRUCT8 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[8]) /* 0x40242200 */ +#define PROT_SMPU_SMPU_STRUCT9 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[9]) /* 0x40242240 */ +#define PROT_SMPU_SMPU_STRUCT10 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[10]) /* 0x40242280 */ +#define PROT_SMPU_SMPU_STRUCT11 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[11]) /* 0x402422C0 */ +#define PROT_SMPU_SMPU_STRUCT12 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[12]) /* 0x40242300 */ +#define PROT_SMPU_SMPU_STRUCT13 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[13]) /* 0x40242340 */ +#define PROT_SMPU_SMPU_STRUCT14 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[14]) /* 0x40242380 */ +#define PROT_SMPU_SMPU_STRUCT15 ((PROT_SMPU_SMPU_STRUCT_Type*) &PROT->SMPU.SMPU_STRUCT[15]) /* 0x402423C0 */ +#define PROT_SMPU ((PROT_SMPU_Type*) &PROT->SMPU) /* 0x40240000 */ +#define PROT_MPU1_MPU_STRUCT0 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[1].MPU_STRUCT[0]) /* 0x40244600 */ +#define PROT_MPU1_MPU_STRUCT1 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[1].MPU_STRUCT[1]) /* 0x40244620 */ +#define PROT_MPU1_MPU_STRUCT2 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[1].MPU_STRUCT[2]) /* 0x40244640 */ +#define PROT_MPU1_MPU_STRUCT3 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[1].MPU_STRUCT[3]) /* 0x40244660 */ +#define PROT_MPU1_MPU_STRUCT4 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[1].MPU_STRUCT[4]) /* 0x40244680 */ +#define PROT_MPU1_MPU_STRUCT5 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[1].MPU_STRUCT[5]) /* 0x402446A0 */ +#define PROT_MPU1_MPU_STRUCT6 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[1].MPU_STRUCT[6]) /* 0x402446C0 */ +#define PROT_MPU1_MPU_STRUCT7 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[1].MPU_STRUCT[7]) /* 0x402446E0 */ +#define PROT_MPU15_MPU_STRUCT0 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[15].MPU_STRUCT[0]) /* 0x40247E00 */ +#define PROT_MPU15_MPU_STRUCT1 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[15].MPU_STRUCT[1]) /* 0x40247E20 */ +#define PROT_MPU15_MPU_STRUCT2 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[15].MPU_STRUCT[2]) /* 0x40247E40 */ +#define PROT_MPU15_MPU_STRUCT3 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[15].MPU_STRUCT[3]) /* 0x40247E60 */ +#define PROT_MPU15_MPU_STRUCT4 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[15].MPU_STRUCT[4]) /* 0x40247E80 */ +#define PROT_MPU15_MPU_STRUCT5 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[15].MPU_STRUCT[5]) /* 0x40247EA0 */ +#define PROT_MPU15_MPU_STRUCT6 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[15].MPU_STRUCT[6]) /* 0x40247EC0 */ +#define PROT_MPU15_MPU_STRUCT7 ((PROT_MPU_MPU_STRUCT_Type*) &PROT->CYMPU[15].MPU_STRUCT[7]) /* 0x40247EE0 */ +#define PROT_MPU0 ((PROT_MPU_Type*) &PROT->CYMPU[0]) /* 0x40244000 */ +#define PROT_MPU1 ((PROT_MPU_Type*) &PROT->CYMPU[1]) /* 0x40244400 */ +#define PROT_MPU2 ((PROT_MPU_Type*) &PROT->CYMPU[2]) /* 0x40244800 */ +#define PROT_MPU3 ((PROT_MPU_Type*) &PROT->CYMPU[3]) /* 0x40244C00 */ +#define PROT_MPU4 ((PROT_MPU_Type*) &PROT->CYMPU[4]) /* 0x40245000 */ +#define PROT_MPU5 ((PROT_MPU_Type*) &PROT->CYMPU[5]) /* 0x40245400 */ +#define PROT_MPU6 ((PROT_MPU_Type*) &PROT->CYMPU[6]) /* 0x40245800 */ +#define PROT_MPU7 ((PROT_MPU_Type*) &PROT->CYMPU[7]) /* 0x40245C00 */ +#define PROT_MPU8 ((PROT_MPU_Type*) &PROT->CYMPU[8]) /* 0x40246000 */ +#define PROT_MPU9 ((PROT_MPU_Type*) &PROT->CYMPU[9]) /* 0x40246400 */ +#define PROT_MPU10 ((PROT_MPU_Type*) &PROT->CYMPU[10]) /* 0x40246800 */ +#define PROT_MPU11 ((PROT_MPU_Type*) &PROT->CYMPU[11]) /* 0x40246C00 */ +#define PROT_MPU12 ((PROT_MPU_Type*) &PROT->CYMPU[12]) /* 0x40247000 */ +#define PROT_MPU13 ((PROT_MPU_Type*) &PROT->CYMPU[13]) /* 0x40247400 */ +#define PROT_MPU14 ((PROT_MPU_Type*) &PROT->CYMPU[14]) /* 0x40247800 */ +#define PROT_MPU15 ((PROT_MPU_Type*) &PROT->CYMPU[15]) /* 0x40247C00 */ + +/******************************************************************************* +* FLASHC +*******************************************************************************/ + +#define FLASHC_BASE 0x40250000UL +#define FLASHC ((FLASHC_Type*) FLASHC_BASE) /* 0x40250000 */ +#define FLASHC_FM_CTL ((FLASHC_FM_CTL_Type*) &FLASHC->FM_CTL) /* 0x4025F000 */ + +/******************************************************************************* +* SRSS +*******************************************************************************/ + +#define SRSS_BASE 0x40260000UL +#define SRSS ((SRSS_Type*) SRSS_BASE) /* 0x40260000 */ +#define MCWDT_STRUCT0 ((MCWDT_STRUCT_Type*) &SRSS->MCWDT_STRUCT[0]) /* 0x40260200 */ +#define MCWDT_STRUCT1 ((MCWDT_STRUCT_Type*) &SRSS->MCWDT_STRUCT[1]) /* 0x40260240 */ + +/******************************************************************************* +* BACKUP +*******************************************************************************/ + +#define BACKUP_BASE 0x40270000UL +#define BACKUP ((BACKUP_Type*) BACKUP_BASE) /* 0x40270000 */ + +/******************************************************************************* +* DW +*******************************************************************************/ + +#define DW0_BASE 0x40280000UL +#define DW1_BASE 0x40281000UL +#define DW0 ((DW_Type*) DW0_BASE) /* 0x40280000 */ +#define DW1 ((DW_Type*) DW1_BASE) /* 0x40281000 */ +#define DW0_CH_STRUCT0 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[0]) /* 0x40280800 */ +#define DW0_CH_STRUCT1 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[1]) /* 0x40280820 */ +#define DW0_CH_STRUCT2 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[2]) /* 0x40280840 */ +#define DW0_CH_STRUCT3 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[3]) /* 0x40280860 */ +#define DW0_CH_STRUCT4 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[4]) /* 0x40280880 */ +#define DW0_CH_STRUCT5 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[5]) /* 0x402808A0 */ +#define DW0_CH_STRUCT6 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[6]) /* 0x402808C0 */ +#define DW0_CH_STRUCT7 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[7]) /* 0x402808E0 */ +#define DW0_CH_STRUCT8 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[8]) /* 0x40280900 */ +#define DW0_CH_STRUCT9 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[9]) /* 0x40280920 */ +#define DW0_CH_STRUCT10 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[10]) /* 0x40280940 */ +#define DW0_CH_STRUCT11 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[11]) /* 0x40280960 */ +#define DW0_CH_STRUCT12 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[12]) /* 0x40280980 */ +#define DW0_CH_STRUCT13 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[13]) /* 0x402809A0 */ +#define DW0_CH_STRUCT14 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[14]) /* 0x402809C0 */ +#define DW0_CH_STRUCT15 ((DW_CH_STRUCT_Type*) &DW0->CH_STRUCT[15]) /* 0x402809E0 */ +#define DW1_CH_STRUCT0 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[0]) /* 0x40281800 */ +#define DW1_CH_STRUCT1 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[1]) /* 0x40281820 */ +#define DW1_CH_STRUCT2 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[2]) /* 0x40281840 */ +#define DW1_CH_STRUCT3 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[3]) /* 0x40281860 */ +#define DW1_CH_STRUCT4 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[4]) /* 0x40281880 */ +#define DW1_CH_STRUCT5 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[5]) /* 0x402818A0 */ +#define DW1_CH_STRUCT6 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[6]) /* 0x402818C0 */ +#define DW1_CH_STRUCT7 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[7]) /* 0x402818E0 */ +#define DW1_CH_STRUCT8 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[8]) /* 0x40281900 */ +#define DW1_CH_STRUCT9 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[9]) /* 0x40281920 */ +#define DW1_CH_STRUCT10 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[10]) /* 0x40281940 */ +#define DW1_CH_STRUCT11 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[11]) /* 0x40281960 */ +#define DW1_CH_STRUCT12 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[12]) /* 0x40281980 */ +#define DW1_CH_STRUCT13 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[13]) /* 0x402819A0 */ +#define DW1_CH_STRUCT14 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[14]) /* 0x402819C0 */ +#define DW1_CH_STRUCT15 ((DW_CH_STRUCT_Type*) &DW1->CH_STRUCT[15]) /* 0x402819E0 */ + +/******************************************************************************* +* EFUSE +*******************************************************************************/ + +#define EFUSE_BASE 0x402C0000UL +#define EFUSE ((EFUSE_Type*) EFUSE_BASE) /* 0x402C0000 */ + +/******************************************************************************* +* PROFILE +*******************************************************************************/ + +#define PROFILE_BASE 0x402D0000UL +#define PROFILE ((PROFILE_Type*) PROFILE_BASE) /* 0x402D0000 */ +#define PROFILE_CNT_STRUCT0 ((PROFILE_CNT_STRUCT_Type*) &PROFILE->CNT_STRUCT[0]) /* 0x402D0800 */ +#define PROFILE_CNT_STRUCT1 ((PROFILE_CNT_STRUCT_Type*) &PROFILE->CNT_STRUCT[1]) /* 0x402D0810 */ +#define PROFILE_CNT_STRUCT2 ((PROFILE_CNT_STRUCT_Type*) &PROFILE->CNT_STRUCT[2]) /* 0x402D0820 */ +#define PROFILE_CNT_STRUCT3 ((PROFILE_CNT_STRUCT_Type*) &PROFILE->CNT_STRUCT[3]) /* 0x402D0830 */ +#define PROFILE_CNT_STRUCT4 ((PROFILE_CNT_STRUCT_Type*) &PROFILE->CNT_STRUCT[4]) /* 0x402D0840 */ +#define PROFILE_CNT_STRUCT5 ((PROFILE_CNT_STRUCT_Type*) &PROFILE->CNT_STRUCT[5]) /* 0x402D0850 */ +#define PROFILE_CNT_STRUCT6 ((PROFILE_CNT_STRUCT_Type*) &PROFILE->CNT_STRUCT[6]) /* 0x402D0860 */ +#define PROFILE_CNT_STRUCT7 ((PROFILE_CNT_STRUCT_Type*) &PROFILE->CNT_STRUCT[7]) /* 0x402D0870 */ + +/******************************************************************************* +* HSIOM +*******************************************************************************/ + +#define HSIOM_BASE 0x40310000UL +#define HSIOM ((HSIOM_Type*) HSIOM_BASE) /* 0x40310000 */ +#define HSIOM_PRT0 ((HSIOM_PRT_Type*) &HSIOM->PRT[0]) /* 0x40310000 */ +#define HSIOM_PRT1 ((HSIOM_PRT_Type*) &HSIOM->PRT[1]) /* 0x40310010 */ +#define HSIOM_PRT2 ((HSIOM_PRT_Type*) &HSIOM->PRT[2]) /* 0x40310020 */ +#define HSIOM_PRT3 ((HSIOM_PRT_Type*) &HSIOM->PRT[3]) /* 0x40310030 */ +#define HSIOM_PRT4 ((HSIOM_PRT_Type*) &HSIOM->PRT[4]) /* 0x40310040 */ +#define HSIOM_PRT5 ((HSIOM_PRT_Type*) &HSIOM->PRT[5]) /* 0x40310050 */ +#define HSIOM_PRT6 ((HSIOM_PRT_Type*) &HSIOM->PRT[6]) /* 0x40310060 */ +#define HSIOM_PRT7 ((HSIOM_PRT_Type*) &HSIOM->PRT[7]) /* 0x40310070 */ +#define HSIOM_PRT8 ((HSIOM_PRT_Type*) &HSIOM->PRT[8]) /* 0x40310080 */ +#define HSIOM_PRT9 ((HSIOM_PRT_Type*) &HSIOM->PRT[9]) /* 0x40310090 */ +#define HSIOM_PRT10 ((HSIOM_PRT_Type*) &HSIOM->PRT[10]) /* 0x403100A0 */ +#define HSIOM_PRT11 ((HSIOM_PRT_Type*) &HSIOM->PRT[11]) /* 0x403100B0 */ +#define HSIOM_PRT12 ((HSIOM_PRT_Type*) &HSIOM->PRT[12]) /* 0x403100C0 */ +#define HSIOM_PRT13 ((HSIOM_PRT_Type*) &HSIOM->PRT[13]) /* 0x403100D0 */ +#define HSIOM_PRT14 ((HSIOM_PRT_Type*) &HSIOM->PRT[14]) /* 0x403100E0 */ + +/******************************************************************************* +* GPIO +*******************************************************************************/ + +#define GPIO_BASE 0x40320000UL +#define GPIO ((GPIO_Type*) GPIO_BASE) /* 0x40320000 */ +#define GPIO_PRT0 ((GPIO_PRT_Type*) &GPIO->PRT[0]) /* 0x40320000 */ +#define GPIO_PRT1 ((GPIO_PRT_Type*) &GPIO->PRT[1]) /* 0x40320080 */ +#define GPIO_PRT2 ((GPIO_PRT_Type*) &GPIO->PRT[2]) /* 0x40320100 */ +#define GPIO_PRT3 ((GPIO_PRT_Type*) &GPIO->PRT[3]) /* 0x40320180 */ +#define GPIO_PRT4 ((GPIO_PRT_Type*) &GPIO->PRT[4]) /* 0x40320200 */ +#define GPIO_PRT5 ((GPIO_PRT_Type*) &GPIO->PRT[5]) /* 0x40320280 */ +#define GPIO_PRT6 ((GPIO_PRT_Type*) &GPIO->PRT[6]) /* 0x40320300 */ +#define GPIO_PRT7 ((GPIO_PRT_Type*) &GPIO->PRT[7]) /* 0x40320380 */ +#define GPIO_PRT8 ((GPIO_PRT_Type*) &GPIO->PRT[8]) /* 0x40320400 */ +#define GPIO_PRT9 ((GPIO_PRT_Type*) &GPIO->PRT[9]) /* 0x40320480 */ +#define GPIO_PRT10 ((GPIO_PRT_Type*) &GPIO->PRT[10]) /* 0x40320500 */ +#define GPIO_PRT11 ((GPIO_PRT_Type*) &GPIO->PRT[11]) /* 0x40320580 */ +#define GPIO_PRT12 ((GPIO_PRT_Type*) &GPIO->PRT[12]) /* 0x40320600 */ +#define GPIO_PRT13 ((GPIO_PRT_Type*) &GPIO->PRT[13]) /* 0x40320680 */ +#define GPIO_PRT14 ((GPIO_PRT_Type*) &GPIO->PRT[14]) /* 0x40320700 */ + +/******************************************************************************* +* SMARTIO +*******************************************************************************/ + +#define SMARTIO_BASE 0x40330000UL +#define SMARTIO ((SMARTIO_Type*) SMARTIO_BASE) /* 0x40330000 */ +#define SMARTIO_PRT8 ((SMARTIO_PRT_Type*) &SMARTIO->PRT[8]) /* 0x40330800 */ +#define SMARTIO_PRT9 ((SMARTIO_PRT_Type*) &SMARTIO->PRT[9]) /* 0x40330900 */ + +/******************************************************************************* +* UDB +*******************************************************************************/ + +#define UDB_BASE 0x40340000UL +#define UDB ((UDB_Type*) UDB_BASE) /* 0x40340000 */ +#define UDB_WRKONE ((UDB_WRKONE_Type*) &UDB->WRKONE) /* 0x40340000 */ +#define UDB_WRKMULT ((UDB_WRKMULT_Type*) &UDB->WRKMULT) /* 0x40341000 */ +#define UDB_UDBPAIR0_UDBSNG0 ((UDB_UDBPAIR_UDBSNG_Type*) &UDB->UDBPAIR[0].UDBSNG[0]) /* 0x40342000 */ +#define UDB_UDBPAIR0_UDBSNG1 ((UDB_UDBPAIR_UDBSNG_Type*) &UDB->UDBPAIR[0].UDBSNG[1]) /* 0x40342080 */ +#define UDB_UDBPAIR1_UDBSNG0 ((UDB_UDBPAIR_UDBSNG_Type*) &UDB->UDBPAIR[1].UDBSNG[0]) /* 0x40342200 */ +#define UDB_UDBPAIR1_UDBSNG1 ((UDB_UDBPAIR_UDBSNG_Type*) &UDB->UDBPAIR[1].UDBSNG[1]) /* 0x40342280 */ +#define UDB_UDBPAIR2_UDBSNG0 ((UDB_UDBPAIR_UDBSNG_Type*) &UDB->UDBPAIR[2].UDBSNG[0]) /* 0x40342400 */ +#define UDB_UDBPAIR2_UDBSNG1 ((UDB_UDBPAIR_UDBSNG_Type*) &UDB->UDBPAIR[2].UDBSNG[1]) /* 0x40342480 */ +#define UDB_UDBPAIR3_UDBSNG0 ((UDB_UDBPAIR_UDBSNG_Type*) &UDB->UDBPAIR[3].UDBSNG[0]) /* 0x40342600 */ +#define UDB_UDBPAIR3_UDBSNG1 ((UDB_UDBPAIR_UDBSNG_Type*) &UDB->UDBPAIR[3].UDBSNG[1]) /* 0x40342680 */ +#define UDB_UDBPAIR4_UDBSNG0 ((UDB_UDBPAIR_UDBSNG_Type*) &UDB->UDBPAIR[4].UDBSNG[0]) /* 0x40342800 */ +#define UDB_UDBPAIR4_UDBSNG1 ((UDB_UDBPAIR_UDBSNG_Type*) &UDB->UDBPAIR[4].UDBSNG[1]) /* 0x40342880 */ +#define UDB_UDBPAIR5_UDBSNG0 ((UDB_UDBPAIR_UDBSNG_Type*) &UDB->UDBPAIR[5].UDBSNG[0]) /* 0x40342A00 */ +#define UDB_UDBPAIR5_UDBSNG1 ((UDB_UDBPAIR_UDBSNG_Type*) &UDB->UDBPAIR[5].UDBSNG[1]) /* 0x40342A80 */ +#define UDB_UDBPAIR0_ROUTE ((UDB_UDBPAIR_ROUTE_Type*) &UDB->UDBPAIR[0].ROUTE) /* 0x40342100 */ +#define UDB_UDBPAIR1_ROUTE ((UDB_UDBPAIR_ROUTE_Type*) &UDB->UDBPAIR[1].ROUTE) /* 0x40342300 */ +#define UDB_UDBPAIR2_ROUTE ((UDB_UDBPAIR_ROUTE_Type*) &UDB->UDBPAIR[2].ROUTE) /* 0x40342500 */ +#define UDB_UDBPAIR3_ROUTE ((UDB_UDBPAIR_ROUTE_Type*) &UDB->UDBPAIR[3].ROUTE) /* 0x40342700 */ +#define UDB_UDBPAIR4_ROUTE ((UDB_UDBPAIR_ROUTE_Type*) &UDB->UDBPAIR[4].ROUTE) /* 0x40342900 */ +#define UDB_UDBPAIR5_ROUTE ((UDB_UDBPAIR_ROUTE_Type*) &UDB->UDBPAIR[5].ROUTE) /* 0x40342B00 */ +#define UDB_UDBPAIR0 ((UDB_UDBPAIR_Type*) &UDB->UDBPAIR[0]) /* 0x40342000 */ +#define UDB_UDBPAIR1 ((UDB_UDBPAIR_Type*) &UDB->UDBPAIR[1]) /* 0x40342200 */ +#define UDB_UDBPAIR2 ((UDB_UDBPAIR_Type*) &UDB->UDBPAIR[2]) /* 0x40342400 */ +#define UDB_UDBPAIR3 ((UDB_UDBPAIR_Type*) &UDB->UDBPAIR[3]) /* 0x40342600 */ +#define UDB_UDBPAIR4 ((UDB_UDBPAIR_Type*) &UDB->UDBPAIR[4]) /* 0x40342800 */ +#define UDB_UDBPAIR5 ((UDB_UDBPAIR_Type*) &UDB->UDBPAIR[5]) /* 0x40342A00 */ +#define UDB_DSI0 ((UDB_DSI_Type*) &UDB->DSI[0]) /* 0x40346000 */ +#define UDB_DSI1 ((UDB_DSI_Type*) &UDB->DSI[1]) /* 0x40346080 */ +#define UDB_DSI2 ((UDB_DSI_Type*) &UDB->DSI[2]) /* 0x40346100 */ +#define UDB_DSI3 ((UDB_DSI_Type*) &UDB->DSI[3]) /* 0x40346180 */ +#define UDB_DSI4 ((UDB_DSI_Type*) &UDB->DSI[4]) /* 0x40346200 */ +#define UDB_DSI5 ((UDB_DSI_Type*) &UDB->DSI[5]) /* 0x40346280 */ +#define UDB_DSI6 ((UDB_DSI_Type*) &UDB->DSI[6]) /* 0x40346300 */ +#define UDB_DSI7 ((UDB_DSI_Type*) &UDB->DSI[7]) /* 0x40346380 */ +#define UDB_DSI8 ((UDB_DSI_Type*) &UDB->DSI[8]) /* 0x40346400 */ +#define UDB_DSI9 ((UDB_DSI_Type*) &UDB->DSI[9]) /* 0x40346480 */ +#define UDB_DSI10 ((UDB_DSI_Type*) &UDB->DSI[10]) /* 0x40346500 */ +#define UDB_DSI11 ((UDB_DSI_Type*) &UDB->DSI[11]) /* 0x40346580 */ +#define UDB_PA0 ((UDB_PA_Type*) &UDB->PA[0]) /* 0x40347000 */ +#define UDB_PA1 ((UDB_PA_Type*) &UDB->PA[1]) /* 0x40347040 */ +#define UDB_PA2 ((UDB_PA_Type*) &UDB->PA[2]) /* 0x40347080 */ +#define UDB_PA3 ((UDB_PA_Type*) &UDB->PA[3]) /* 0x403470C0 */ +#define UDB_PA4 ((UDB_PA_Type*) &UDB->PA[4]) /* 0x40347100 */ +#define UDB_PA5 ((UDB_PA_Type*) &UDB->PA[5]) /* 0x40347140 */ +#define UDB_PA6 ((UDB_PA_Type*) &UDB->PA[6]) /* 0x40347180 */ +#define UDB_PA7 ((UDB_PA_Type*) &UDB->PA[7]) /* 0x403471C0 */ +#define UDB_PA8 ((UDB_PA_Type*) &UDB->PA[8]) /* 0x40347200 */ +#define UDB_PA9 ((UDB_PA_Type*) &UDB->PA[9]) /* 0x40347240 */ +#define UDB_PA10 ((UDB_PA_Type*) &UDB->PA[10]) /* 0x40347280 */ +#define UDB_PA11 ((UDB_PA_Type*) &UDB->PA[11]) /* 0x403472C0 */ +#define UDB_BCTL ((UDB_BCTL_Type*) &UDB->BCTL) /* 0x40347800 */ +#define UDB_UDBIF ((UDB_UDBIF_Type*) &UDB->UDBIF) /* 0x40347900 */ + +/******************************************************************************* +* LPCOMP +*******************************************************************************/ + +#define LPCOMP_BASE 0x40350000UL +#define LPCOMP ((LPCOMP_Type*) LPCOMP_BASE) /* 0x40350000 */ + +/******************************************************************************* +* CSD +*******************************************************************************/ + +#define CSD0_BASE 0x40360000UL +#define CSD0 ((CSD_Type*) CSD0_BASE) /* 0x40360000 */ + +/******************************************************************************* +* TCPWM +*******************************************************************************/ + +#define TCPWM0_BASE 0x40380000UL +#define TCPWM1_BASE 0x40390000UL +#define TCPWM0 ((TCPWM_Type*) TCPWM0_BASE) /* 0x40380000 */ +#define TCPWM1 ((TCPWM_Type*) TCPWM1_BASE) /* 0x40390000 */ +#define TCPWM0_CNT0 ((TCPWM_CNT_Type*) &TCPWM0->CNT[0]) /* 0x40380100 */ +#define TCPWM0_CNT1 ((TCPWM_CNT_Type*) &TCPWM0->CNT[1]) /* 0x40380140 */ +#define TCPWM0_CNT2 ((TCPWM_CNT_Type*) &TCPWM0->CNT[2]) /* 0x40380180 */ +#define TCPWM0_CNT3 ((TCPWM_CNT_Type*) &TCPWM0->CNT[3]) /* 0x403801C0 */ +#define TCPWM0_CNT4 ((TCPWM_CNT_Type*) &TCPWM0->CNT[4]) /* 0x40380200 */ +#define TCPWM0_CNT5 ((TCPWM_CNT_Type*) &TCPWM0->CNT[5]) /* 0x40380240 */ +#define TCPWM0_CNT6 ((TCPWM_CNT_Type*) &TCPWM0->CNT[6]) /* 0x40380280 */ +#define TCPWM0_CNT7 ((TCPWM_CNT_Type*) &TCPWM0->CNT[7]) /* 0x403802C0 */ +#define TCPWM1_CNT0 ((TCPWM_CNT_Type*) &TCPWM1->CNT[0]) /* 0x40390100 */ +#define TCPWM1_CNT1 ((TCPWM_CNT_Type*) &TCPWM1->CNT[1]) /* 0x40390140 */ +#define TCPWM1_CNT2 ((TCPWM_CNT_Type*) &TCPWM1->CNT[2]) /* 0x40390180 */ +#define TCPWM1_CNT3 ((TCPWM_CNT_Type*) &TCPWM1->CNT[3]) /* 0x403901C0 */ +#define TCPWM1_CNT4 ((TCPWM_CNT_Type*) &TCPWM1->CNT[4]) /* 0x40390200 */ +#define TCPWM1_CNT5 ((TCPWM_CNT_Type*) &TCPWM1->CNT[5]) /* 0x40390240 */ +#define TCPWM1_CNT6 ((TCPWM_CNT_Type*) &TCPWM1->CNT[6]) /* 0x40390280 */ +#define TCPWM1_CNT7 ((TCPWM_CNT_Type*) &TCPWM1->CNT[7]) /* 0x403902C0 */ +#define TCPWM1_CNT8 ((TCPWM_CNT_Type*) &TCPWM1->CNT[8]) /* 0x40390300 */ +#define TCPWM1_CNT9 ((TCPWM_CNT_Type*) &TCPWM1->CNT[9]) /* 0x40390340 */ +#define TCPWM1_CNT10 ((TCPWM_CNT_Type*) &TCPWM1->CNT[10]) /* 0x40390380 */ +#define TCPWM1_CNT11 ((TCPWM_CNT_Type*) &TCPWM1->CNT[11]) /* 0x403903C0 */ +#define TCPWM1_CNT12 ((TCPWM_CNT_Type*) &TCPWM1->CNT[12]) /* 0x40390400 */ +#define TCPWM1_CNT13 ((TCPWM_CNT_Type*) &TCPWM1->CNT[13]) /* 0x40390440 */ +#define TCPWM1_CNT14 ((TCPWM_CNT_Type*) &TCPWM1->CNT[14]) /* 0x40390480 */ +#define TCPWM1_CNT15 ((TCPWM_CNT_Type*) &TCPWM1->CNT[15]) /* 0x403904C0 */ +#define TCPWM1_CNT16 ((TCPWM_CNT_Type*) &TCPWM1->CNT[16]) /* 0x40390500 */ +#define TCPWM1_CNT17 ((TCPWM_CNT_Type*) &TCPWM1->CNT[17]) /* 0x40390540 */ +#define TCPWM1_CNT18 ((TCPWM_CNT_Type*) &TCPWM1->CNT[18]) /* 0x40390580 */ +#define TCPWM1_CNT19 ((TCPWM_CNT_Type*) &TCPWM1->CNT[19]) /* 0x403905C0 */ +#define TCPWM1_CNT20 ((TCPWM_CNT_Type*) &TCPWM1->CNT[20]) /* 0x40390600 */ +#define TCPWM1_CNT21 ((TCPWM_CNT_Type*) &TCPWM1->CNT[21]) /* 0x40390640 */ +#define TCPWM1_CNT22 ((TCPWM_CNT_Type*) &TCPWM1->CNT[22]) /* 0x40390680 */ +#define TCPWM1_CNT23 ((TCPWM_CNT_Type*) &TCPWM1->CNT[23]) /* 0x403906C0 */ + +/******************************************************************************* +* LCD +*******************************************************************************/ + +#define LCD0_BASE 0x403B0000UL +#define LCD0 ((LCD_Type*) LCD0_BASE) /* 0x403B0000 */ + +/******************************************************************************* +* BLE +*******************************************************************************/ + +#define BLE_BASE 0x403C0000UL +#define BLE ((BLE_Type*) BLE_BASE) /* 0x403C0000 */ +#define BLE_RCB_RCBLL ((BLE_RCB_RCBLL_Type*) &BLE->RCB.RCBLL) /* 0x403C0100 */ +#define BLE_RCB ((BLE_RCB_Type*) &BLE->RCB) /* 0x403C0000 */ +#define BLE_BLELL ((BLE_BLELL_Type*) &BLE->BLELL) /* 0x403C1000 */ +#define BLE_BLESS ((BLE_BLESS_Type*) &BLE->BLESS) /* 0x403DF000 */ + +/******************************************************************************* +* SMIF +*******************************************************************************/ + +#define SMIF0_BASE 0x40420000UL +#define SMIF0 ((SMIF_Type*) SMIF0_BASE) /* 0x40420000 */ +#define SMIF0_DEVICE0 ((SMIF_DEVICE_Type*) &SMIF0->DEVICE[0]) /* 0x40420800 */ +#define SMIF0_DEVICE1 ((SMIF_DEVICE_Type*) &SMIF0->DEVICE[1]) /* 0x40420880 */ +#define SMIF0_DEVICE2 ((SMIF_DEVICE_Type*) &SMIF0->DEVICE[2]) /* 0x40420900 */ +#define SMIF0_DEVICE3 ((SMIF_DEVICE_Type*) &SMIF0->DEVICE[3]) /* 0x40420980 */ + +/******************************************************************************* +* SCB +*******************************************************************************/ + +#define SCB0_BASE 0x40610000UL +#define SCB1_BASE 0x40620000UL +#define SCB2_BASE 0x40630000UL +#define SCB3_BASE 0x40640000UL +#define SCB4_BASE 0x40650000UL +#define SCB5_BASE 0x40660000UL +#define SCB6_BASE 0x40670000UL +#define SCB7_BASE 0x40680000UL +#define SCB8_BASE 0x40690000UL +#define SCB0 ((CySCB_Type*) SCB0_BASE) /* 0x40610000 */ +#define SCB1 ((CySCB_Type*) SCB1_BASE) /* 0x40620000 */ +#define SCB2 ((CySCB_Type*) SCB2_BASE) /* 0x40630000 */ +#define SCB3 ((CySCB_Type*) SCB3_BASE) /* 0x40640000 */ +#define SCB4 ((CySCB_Type*) SCB4_BASE) /* 0x40650000 */ +#define SCB5 ((CySCB_Type*) SCB5_BASE) /* 0x40660000 */ +#define SCB6 ((CySCB_Type*) SCB6_BASE) /* 0x40670000 */ +#define SCB7 ((CySCB_Type*) SCB7_BASE) /* 0x40680000 */ +#define SCB8 ((CySCB_Type*) SCB8_BASE) /* 0x40690000 */ + +/******************************************************************************* +* CTBM +*******************************************************************************/ + +#define CTBM0_BASE 0x41100000UL +#define CTBM0 ((CTBM_Type*) CTBM0_BASE) /* 0x41100000 */ + +/******************************************************************************* +* CTDAC +*******************************************************************************/ + +#define CTDAC0_BASE 0x41140000UL +#define CTDAC0 ((CTDAC_Type*) CTDAC0_BASE) /* 0x41140000 */ + +/******************************************************************************* +* SAR +*******************************************************************************/ + +#define SAR_BASE 0x411D0000UL +#define SAR ((SAR_Type*) SAR_BASE) /* 0x411D0000 */ + +/******************************************************************************* +* PASS +*******************************************************************************/ + +#define PASS_BASE 0x411F0000UL +#define PASS ((PASS_Type*) PASS_BASE) /* 0x411F0000 */ +#define PASS_AREF ((PASS_AREF_Type*) &PASS->AREF) /* 0x411F0E00 */ + +/******************************************************************************* +* I2S +*******************************************************************************/ + +#define I2S0_BASE 0x42A10000UL +#define I2S0 ((I2S_Type*) I2S0_BASE) /* 0x42A10000 */ + +/******************************************************************************* +* PDM +*******************************************************************************/ + +#define PDM0_BASE 0x42A20000UL +#define PDM0 ((PDM_Type*) PDM0_BASE) /* 0x42A20000 */ + +/* Backward compabitility definitions */ +#define I2S I2S0 +#define PDM PDM0 + +/** \} CY8C6347BZI-BLD53 */ + +#endif /* _CY8C6347BZI_BLD53_H_ */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cy_device_headers.h b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cy_device_headers.h new file mode 100644 index 0000000000..7225333329 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cy_device_headers.h @@ -0,0 +1,69 @@ +/***************************************************************************//** +* \file cy_device_headers.h +* +* \brief +* Common header file to be included by the drivers. +* +* \note +* Generator version: 1.2.0.117 +* Database revision: rev#1034984 +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#ifndef _CY_DEVICE_HEADERS_H_ +#define _CY_DEVICE_HEADERS_H_ + +#if defined (CY8C6336BZI_BLF03) + #include "cy8c6336bzi_blf03.h" +#elif defined (CY8C6316BZI_BLF03) + #include "cy8c6316bzi_blf03.h" +#elif defined (CY8C6316BZI_BLF53) + #include "cy8c6316bzi_blf53.h" +#elif defined (CY8C6336BZI_BLD13) + #include "cy8c6336bzi_bld13.h" +#elif defined (CY8C6347BZI_BLD43) + #include "cy8c6347bzi_bld43.h" +#elif defined (CY8C6347BZI_BLD33) + #include "cy8c6347bzi_bld33.h" +#elif defined (CY8C6347BZI_BLD53) + #include "cy8c6347bzi_bld53.h" +#elif defined (CY8C6347FMI_BLD13) + #include "cy8c6347fmi_bld13.h" +#elif defined (CY8C6347FMI_BLD43) + #include "cy8c6347fmi_bld43.h" +#elif defined (CY8C6347FMI_BLD33) + #include "cy8c6347fmi_bld33.h" +#elif defined (CY8C6347FMI_BLD53) + #include "cy8c6347fmi_bld53.h" +#elif defined (CY8C637BZI_MD76) + #include "cy8c637bzi_md76.h" +#elif defined (CY8C637BZI_BLD74) + #include "cy8c637bzi_bld74.h" +#elif defined (CY8C637FMI_BLD73) + #include "cy8c637fmi_bld73.h" +#elif defined (CY8C68237BZ_BLE) + #include "cy8c68237bz_ble.h" +#elif defined (CY8C68237FM_BLE) + #include "cy8c68237fm_ble.h" +#elif defined (CY8C6336BZI_BUD13) + #include "cy8c6336bzi_bud13.h" +#elif defined (CY8C6347BZI_BUD43) + #include "cy8c6347bzi_bud43.h" +#elif defined (CY8C6347BZI_BUD33) + #include "cy8c6347bzi_bud33.h" +#elif defined (CY8C6347BZI_BUD53) + #include "cy8c6347bzi_bud53.h" +#elif defined (CY8C6337BZI_BLF13) + #include "cy8c6337bzi_blf13.h" +#else + #error Undefined part number +#endif + +#endif /* _CY_DEVICE_HEADERS_H_ */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cy_ipc_config.c b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cy_ipc_config.c new file mode 100644 index 0000000000..1394c20dbe --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cy_ipc_config.c @@ -0,0 +1,190 @@ +/***************************************************************************//** +* \file cy_ipc_config.c +* \version 1.10.1 +* +* Description: +* This C file is not intended to be part of the IPC driver. It is the code +* required to configure the device specific IPC channels for semaphores +* and pipes. +* +******************************************************************************** +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include "ipc/cy_ipc_drv.h" +#include "ipc/cy_ipc_pipe.h" +#include "ipc/cy_ipc_sema.h" + +#include "cy_ipc_config.h" + +/* Create an array of endpoint structures */ +static cy_stc_ipc_pipe_ep_t cy_ipc_pipe_sysEpArray[CY_IPC_MAX_ENDPOINTS]; + +#define CY_CYPIPE_DEFAULT_CONFIG \ +{\ + /* .ep0ConfigData */ {\ + /* .ipcNotifierNumber */ CY_IPC_INTR_CYPIPE_EP0,\ + /* .ipcNotifierPriority */ CY_IPC_INTR_CYPIPE_PRIOR_EP0,\ + /* .ipcNotifierMuxNumber */ CY_IPC_INTR_CYPIPE_MUX_EP0,\ + /* .epAddress */ CY_IPC_EP_CYPIPE_CM0_ADDR,\ + /* .epConfig */ CY_IPC_CYPIPE_CONFIG_EP0\ + },\ + /* .ep1ConfigData */ {\ + /* .ipcNotifierNumber */ CY_IPC_INTR_CYPIPE_EP1,\ + /* .ipcNotifierPriority */ CY_IPC_INTR_CYPIPE_PRIOR_EP1,\ + /* .ipcNotifierMuxNumber */ 0u,\ + /* .epAddress */ CY_IPC_EP_CYPIPE_CM4_ADDR,\ + /* .epConfig */ CY_IPC_CYPIPE_CONFIG_EP1\ + },\ + /* .endpointClientsCount */ CY_IPC_CYPIPE_CLIENT_CNT,\ + /* .endpointsCallbacksArray */ cy_ipc_pipe_sysCbArray,\ + /* .userPipeIsrHandler */ &Cy_IPC_SystemPipeIsr\ +} + + + +/******************************************************************************* +* Function Name: Cy_IPC_SystemSemaInit +****************************************************************************//** +* +* Initializes the system semaphores. The system semaphores are used by Flash. +* +* This function is called in the SystemInit() function. If the default startup +* file is not used, or SystemInit() is not called in your project, +* call the following three functions prior to executing any flash or EmEEPROM +* write or erase operation: +* -# Cy_IPC_SystemSemaInit() +* -# Cy_IPC_SystemPipeInit() +* -# Cy_Flash_Init() +* +*******************************************************************************/ +void Cy_IPC_SystemSemaInit(void) +{ +/* Create array used for semaphores */ +#if !(CY_CPU_CORTEX_M0P) + (void) Cy_IPC_Sema_Init(CY_IPC_CHAN_SEMA, 0ul, NULL); +#else + static uint32_t ipcSemaArray[CY_IPC_SEMA_COUNT / CY_IPC_SEMA_PER_WORD]; + (void) Cy_IPC_Sema_Init(CY_IPC_CHAN_SEMA, CY_IPC_SEMA_COUNT, ipcSemaArray); +#endif +} + + +/******************************************************************************* +* Function Name: Cy_IPC_UserPipeIsr +****************************************************************************//** +* +* This is the interrupt service routine for the user pipe. +* +*******************************************************************************/ +void Cy_IPC_UserPipeIsr(void) +{ + Cy_IPC_Pipe_ExecCallback(&cy_ipc_pipe_sysEpArray[CY_IPC_EP_USRPIPE_ADDR]); +} + + +/******************************************************************************* +* Function Name: Cy_IPC_RpcPipeIsr +****************************************************************************//** +* +* This is the interrupt service routine for the RPC pipe. +* +*******************************************************************************/ +void Cy_IPC_RpcPipeIsr(void) +{ + Cy_IPC_Pipe_ExecCallback(&cy_ipc_pipe_sysEpArray[CY_IPC_EP_RPCPIPE_ADDR]); +} + +/******************************************************************************* +* Function Name: Cy_IPC_SystemPipeInit +****************************************************************************//** +* +* Initializes the system pipes. The system pipes are used by BLE and Flash. +* \note The function should be called on all CPUs. +* +* This function is called in the SystemInit() function. If the default startup +* file is not used, or SystemInit() is not called in your project, +* call the following three functions prior to executing any flash or EmEEPROM +* write or erase operation: +* -# Cy_IPC_SystemSemaInit() +* -# Cy_IPC_SystemPipeInit() +* -# Cy_Flash_Init() +* +* Also this function is called to support BLE host/controller communication. +* +*******************************************************************************/ +void Cy_IPC_SystemPipeInit(void) +{ + uint32_t intr; + + intr = Cy_SysLib_EnterCriticalSection(); + + static cy_ipc_pipe_callback_ptr_t cy_ipc_pipe_sysCbArray[CY_IPC_CYPIPE_CLIENT_CNT]; + static cy_ipc_pipe_callback_ptr_t cy_ipc_pipe_userCbArray[CY_IPC_USRPIPE_CLIENT_CNT]; + static cy_ipc_pipe_callback_ptr_t cy_ipc_pipe_rpcCbArray[CY_IPC_RPCPIPE_CLIENT_CNT]; + + static const cy_stc_ipc_pipe_config_t systemPipeConfig = CY_CYPIPE_DEFAULT_CONFIG; + static const cy_stc_ipc_pipe_config_t userPipeConfig = { + .ep0ConfigData = { + .ipcNotifierNumber = CY_IPC_INTR_USRPIPE_CM0, + .ipcNotifierPriority = CY_IPC_INTR_USRPIPE_PRIOR_EP0, + .ipcNotifierMuxNumber = CY_IPC_INTR_USRPIPE_MUX_EP0, + .epAddress = CY_IPC_EP_USRPIPE_CM0_ADDR, + .epConfig = CY_IPC_USRPIPE_CONFIG_EP0 + }, + .ep1ConfigData = { + .ipcNotifierNumber = CY_IPC_INTR_USRPIPE_CM4, + .ipcNotifierPriority = CY_IPC_INTR_USRPIPE_PRIOR_EP1, + .ipcNotifierMuxNumber = 0u, + .epAddress = CY_IPC_EP_USRPIPE_CM4_ADDR, + .epConfig = CY_IPC_USRPIPE_CONFIG_EP1 + }, + .endpointClientsCount = CY_IPC_USRPIPE_CLIENT_CNT, + .endpointsCallbacksArray = cy_ipc_pipe_userCbArray, + .userPipeIsrHandler = &Cy_IPC_UserPipeIsr + }; + static const cy_stc_ipc_pipe_config_t rpcPipeConfig = { + .ep0ConfigData = { + .ipcNotifierNumber = CY_IPC_INTR_RPCPIPE_CM0, + .ipcNotifierPriority = CY_IPC_INTR_RPCPIPE_PRIOR_EP0, + .ipcNotifierMuxNumber = CY_IPC_INTR_RPCPIPE_MUX_EP0, + .epAddress = CY_IPC_EP_RPCPIPE_CM0_ADDR, + .epConfig = CY_IPC_RPCPIPE_CONFIG_EP0 + }, + .ep1ConfigData = { + .ipcNotifierNumber = CY_IPC_INTR_RPCPIPE_CM4, + .ipcNotifierPriority = CY_IPC_INTR_RPCPIPE_PRIOR_EP1, + .ipcNotifierMuxNumber = 0u, + .epAddress = CY_IPC_EP_RPCPIPE_CM4_ADDR, + .epConfig = CY_IPC_RPCPIPE_CONFIG_EP1 + }, + .endpointClientsCount = CY_IPC_RPCPIPE_CLIENT_CNT, + .endpointsCallbacksArray = cy_ipc_pipe_rpcCbArray, + .userPipeIsrHandler = &Cy_IPC_RpcPipeIsr + }; + + Cy_IPC_Pipe_Config(cy_ipc_pipe_sysEpArray); + + Cy_IPC_Pipe_Init(&systemPipeConfig); + Cy_IPC_Pipe_Init(&userPipeConfig); + Cy_IPC_Pipe_Init(&rpcPipeConfig); + + Cy_SysLib_ExitCriticalSection(intr); +} + +/******************************************************************************* +* Function Name: Cy_IPC_SystemPipeIsr +****************************************************************************//** +* +* This is the interrupt service routine for the system pipe. +* +*******************************************************************************/ +void Cy_IPC_SystemPipeIsr(void) +{ + Cy_IPC_Pipe_ExecCallback(&cy_ipc_pipe_sysEpArray[CY_IPC_EP_CYPIPE_ADDR]); +} + + +/* [] END OF FILE */ + diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cy_ipc_config.h b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cy_ipc_config.h new file mode 100644 index 0000000000..0dc321858a --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cy_ipc_config.h @@ -0,0 +1,219 @@ +/***************************************************************************//** +* \file cy_ipc_config.h +* \version 1.10.1 +* +* \brief +* This header file is not intended to be part of the IPC driver since it defines +* a device specific configuration for the IPC channels and pipes. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#ifndef CY_IPC_CONFIG_H +#define CY_IPC_CONFIG_H + +/* IPC Resources */ +#define CY_IPC_CHANNELS (uint32_t)(CPUSS_IPC_IPC_NR) +#define CY_IPC_INTERRUPTS (uint32_t)(CPUSS_IPC_IPC_IRQ_NR) + +/* IPC channel definitions */ +#define CY_IPC_CHAN_SYSCALL_CM0 (0u) /* System calls for the CM0 processor */ +#define CY_IPC_CHAN_SYSCALL_CM4 (1u) /* System calls for the 1st non-CM0 processor */ +#if (CY_CPU_CORTEX_M0P) + #define CY_IPC_CHAN_SYSCALL CY_IPC_CHAN_SYSCALL_CM0 + #define Cy_IPC_SystemPipeIsr NvicMux1_IRQHandler +#else + #define CY_IPC_CHAN_SYSCALL CY_IPC_CHAN_SYSCALL_CM4 + #define Cy_IPC_SystemPipeIsr cpuss_interrupts_ipc_4_IRQHandler +#endif /* (CY_CPU_CORTEX_M0P) */ + +#define CY_IPC_CHAN_SYSCALL_DAP (uint32_t)(2u) /**< System calls for the DAP */ +#define CY_IPC_CHAN_CRYPTO (uint32_t)(3u) /**< IPC data channel for the Crypto */ +#define CY_IPC_CHAN_SEMA (uint32_t)(4u) /**< IPC data channel for the Semaphores */ + +#define CY_IPC_CHAN_CYPIPE_EP0 (uint32_t)(5u) /**< IPC data channel for CYPIPE EP0 */ +#define CY_IPC_CHAN_CYPIPE_EP1 (uint32_t)(6u) /**< IPC data channel for CYPIPE EP1 */ + +/* IPC Notify interrupts definitions */ +#define CY_IPC_INTR_SYSCALL1 (uint32_t)(0u) + +#define CY_IPC_INTR_CRYPTO_SRV (uint32_t)(1u) /**< IPC interrupt structure for the Crypto server */ +#define CY_IPC_INTR_CRYPTO_CLI (uint32_t)(2u) /**< IPC interrupt structure for the Crypto client */ + +#define CY_IPC_INTR_SPARE (uint32_t)(7u) + +/* IPC Semaphores allocation + This will allow 128 (4*32) semaphores */ +#define CY_IPC_SEMA_COUNT (uint32_t)(128u) + +/* IPC Pipe definitions */ +#define CY_IPC_MAX_ENDPOINTS (uint32_t)(8u) + +/******************************************************************************* +** CY_PIPE default configuration +*******************************************************************************/ +#define CY_IPC_CYPIPE_CLIENT_CNT (uint32_t)(8u) +#define CY_IPC_USRPIPE_CLIENT_CNT (uint32_t)(8u) +#define CY_IPC_RPCPIPE_CLIENT_CNT (uint32_t)(16u) + +#if (CY_CPU_CORTEX_M0P) + #define CY_IPC_EP_CYPIPE_ADDR CY_IPC_EP_CYPIPE_CM0_ADDR +#else + #define CY_IPC_EP_CYPIPE_ADDR CY_IPC_EP_CYPIPE_CM4_ADDR +#endif /* (CY_CPU_CORTEX_M0P) */ + +#define CY_IPC_INTR_CYPIPE_MUX_EP0 (uint32_t)(1u) /* IPC CYPRESS PIPE */ +#define CY_IPC_INTR_CYPIPE_EP0 (uint32_t)(3u) /* Notifier EP0 */ +#define CY_IPC_INTR_CYPIPE_PRIOR_EP0 (uint32_t)(1u) /* Notifier Priority */ + +#define CY_IPC_INTR_CYPIPE_EP1 (uint32_t)(4u) /* Notifier EP1 */ +#define CY_IPC_INTR_CYPIPE_PRIOR_EP1 (uint32_t)(1u) /* Notifier Priority */ + +#define CY_IPC_CYPIPE_CHAN_MASK_EP0 (uint32_t)(0x0001ul << CY_IPC_CHAN_CYPIPE_EP0) +#define CY_IPC_CYPIPE_CHAN_MASK_EP1 (uint32_t)(0x0001ul << CY_IPC_CHAN_CYPIPE_EP1) + +/* Endpoint indexes in the pipe array */ +#define CY_IPC_EP_CYPIPE_CM0_ADDR (uint32_t)(0u) +#define CY_IPC_EP_CYPIPE_CM4_ADDR (uint32_t)(1u) + +/******************************************************************************/ + +/* + * The System pipe configuration defines the IPC channel number, interrupt + * number, and the pipe interrupt mask for the endpoint. + * + * The format of the endPoint configuration + * Bits[31:16] Interrupt Mask + * Bits[15:8 ] IPC interrupt + * Bits[ 7:0 ] IPC channel + */ + +/* System Pipe addresses */ +/* CyPipe defines */ + +#define CY_IPC_CYPIPE_CONFIG_EP0 (uint32_t)( (CY_IPC_CYPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos) \ + | (CY_IPC_INTR_CYPIPE_EP0 << CY_IPC_PIPE_CFG_INTR_Pos) \ + | CY_IPC_CHAN_CYPIPE_EP0) +#define CY_IPC_CYPIPE_CONFIG_EP1 (uint32_t)( (CY_IPC_CYPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos) \ + | (CY_IPC_INTR_CYPIPE_EP1 << CY_IPC_PIPE_CFG_INTR_Pos) \ + | CY_IPC_CHAN_CYPIPE_EP1) +#define CY_IPC_CYPIPE_INTR_MASK (uint32_t)( CY_IPC_CYPIPE_CHAN_MASK_EP0 | CY_IPC_CYPIPE_CHAN_MASK_EP1 ) + +/******************************************************************************/ +#define CY_IPC_CHAN_USRPIPE_CM0 (uint32_t)(8u) +#define CY_IPC_CHAN_USRPIPE_CM4 (uint32_t)(9u) + +#define CY_IPC_INTR_USRPIPE_CM0 (uint32_t)(8u) +#define CY_IPC_INTR_USRPIPE_CM4 (uint32_t)(9u) + +#define CY_IPC_EP_USRPIPE_ADDR_EP0 (uint32_t)(2u) +#define CY_IPC_EP_USRPIPE_ADDR_EP1 (uint32_t)(3u) + +/* Endpoint indexes in the pipe array */ +#define CY_IPC_EP_USRPIPE_CM0_ADDR (uint32_t)(2u) +#define CY_IPC_EP_USRPIPE_CM4_ADDR (uint32_t)(3u) + + +#if (CY_CPU_CORTEX_M0P) + #define CY_IPC_EP_USRPIPE_ADDR CY_IPC_EP_USRPIPE_CM0_ADDR + #define CY_IPC_EP_USRPIPE_DEST CY_IPC_EP_USRPIPE_CM4_ADDR +#else + #define CY_IPC_EP_USRPIPE_ADDR CY_IPC_EP_USRPIPE_CM4_ADDR + #define CY_IPC_EP_USRPIPE_DEST CY_IPC_EP_USRPIPE_CM0_ADDR +#endif /* (CY_CPU_CORTEX_M0P) */ + +#define CY_IPC_INTR_USRPIPE_MUX_EP0 (uint32_t)(2u) +#define CY_IPC_INTR_USRPIPE_EP0 CY_IPC_INTR_USRPIPE_CM0 +#define CY_IPC_INTR_USRPIPE_PRIOR_EP0 (uint32_t)(1u) /* Notifier Priority */ + +#define CY_IPC_INTR_USRPIPE_EP1 CY_IPC_INTR_USRPIPE_CM4 +#define CY_IPC_INTR_USRPIPE_PRIOR_EP1 (uint32_t)(1u) /* Notifier Priority */ + +#define CY_IPC_USRPIPE_CHAN_MASK_EP0 (uint32_t)(0x0001ul << CY_IPC_CHAN_USRPIPE_CM0) +#define CY_IPC_USRPIPE_CHAN_MASK_EP1 (uint32_t)(0x0001ul << CY_IPC_CHAN_USRPIPE_CM4) + + +#define CY_IPC_USRPIPE_CONFIG_EP0 (uint32_t)( (CY_IPC_USRPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos) \ + | (CY_IPC_INTR_USRPIPE_EP0 << CY_IPC_PIPE_CFG_INTR_Pos) \ + | CY_IPC_CHAN_USRPIPE_CM0) +#define CY_IPC_USRPIPE_CONFIG_EP1 (uint32_t)( (CY_IPC_USRPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos) \ + | (CY_IPC_INTR_USRPIPE_EP1 << CY_IPC_PIPE_CFG_INTR_Pos) \ + | CY_IPC_CHAN_USRPIPE_CM4) +#define CY_IPC_USRPIPE_INTR_MASK (uint32_t)( CY_IPC_USRPIPE_CHAN_MASK_EP0 | CY_IPC_USRPIPE_CHAN_MASK_EP1 ) + + +/******************************************************************************/ +#define CY_IPC_CHAN_RPCPIPE_CM0 (uint32_t)(10u) +#define CY_IPC_CHAN_RPCPIPE_CM4 (uint32_t)(11u) + +#define CY_IPC_INTR_RPCPIPE_CM0 (uint32_t)(10u) +#define CY_IPC_INTR_RPCPIPE_CM4 (uint32_t)(11u) + +#define CY_IPC_EP_RPCPIPE_ADDR_EP0 (uint32_t)(4u) +#define CY_IPC_EP_RPCPIPE_ADDR_EP1 (uint32_t)(5u) + +/* Endpoint indexes in the pipe array */ +#define CY_IPC_EP_RPCPIPE_CM0_ADDR (uint32_t)(4u) +#define CY_IPC_EP_RPCPIPE_CM4_ADDR (uint32_t)(5u) + + +#if (CY_CPU_CORTEX_M0P) + #define CY_IPC_EP_RPCPIPE_ADDR CY_IPC_EP_RPCPIPE_CM0_ADDR + #define CY_IPC_EP_RPCPIPE_DEST CY_IPC_EP_RPCPIPE_CM4_ADDR +#else + #define CY_IPC_EP_RPCPIPE_ADDR CY_IPC_EP_RPCPIPE_CM4_ADDR + #define CY_IPC_EP_RPCPIPE_DEST CY_IPC_EP_RPCPIPE_CM0_ADDR +#endif /* (CY_CPU_CORTEX_M0P) */ + +#define CY_IPC_INTR_RPCPIPE_MUX_EP0 (uint32_t)(4u) +#define CY_IPC_INTR_RPCPIPE_EP0 CY_IPC_INTR_RPCPIPE_CM0 +#define CY_IPC_INTR_RPCPIPE_PRIOR_EP0 (uint32_t)(1u) /* Notifier Priority */ + +#define CY_IPC_INTR_RPCPIPE_EP1 CY_IPC_INTR_RPCPIPE_CM4 +#define CY_IPC_INTR_RPCPIPE_PRIOR_EP1 (uint32_t)(1u) /* Notifier Priority */ + +#define CY_IPC_RPCPIPE_CHAN_MASK_EP0 (uint32_t)(0x0001ul << CY_IPC_CHAN_RPCPIPE_CM0) +#define CY_IPC_RPCPIPE_CHAN_MASK_EP1 (uint32_t)(0x0001ul << CY_IPC_CHAN_RPCPIPE_CM4) + + +#define CY_IPC_RPCPIPE_CONFIG_EP0 (uint32_t)( (CY_IPC_RPCPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos) \ + | (CY_IPC_INTR_RPCPIPE_EP0 << CY_IPC_PIPE_CFG_INTR_Pos) \ + | CY_IPC_CHAN_RPCPIPE_CM0) +#define CY_IPC_RPCPIPE_CONFIG_EP1 (uint32_t)( (CY_IPC_RPCPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos) \ + | (CY_IPC_INTR_RPCPIPE_EP1 << CY_IPC_PIPE_CFG_INTR_Pos) \ + | CY_IPC_CHAN_RPCPIPE_CM4) +#define CY_IPC_RPCPIPE_INTR_MASK (uint32_t)( CY_IPC_RPCPIPE_CHAN_MASK_EP0 | CY_IPC_RPCPIPE_CHAN_MASK_EP1 ) + +#ifdef __cplusplus +extern "C" { +#endif + + + +/* +* \addtogroup group_ipc_configuration_sema +* \{ +*/ +void Cy_IPC_SystemSemaInit(void); +/* \} group_ipc_configuration_sema */ + +/* +* \addtogroup group_ipc_configuration_cypipe +* \{ +*/ +void Cy_IPC_SystemPipeInit(void); +/* \} group_ipc_configuration_cypipe */ + +void Cy_IPC_SystemPipeIsr(void); + +#ifdef __cplusplus +} +#endif + +#endif /* CY_IPC_CONFIG_H */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cymetadata.c b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cymetadata.c new file mode 100644 index 0000000000..ca605b521a --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/cymetadata.c @@ -0,0 +1,56 @@ +/******************************************************************************* +* File Name: cymetadata.c +* +* PSoC Creator 4.1 +* +* Description: +* This file defines all extra memory spaces that need to be included. +* This file is automatically generated by PSoC Creator. +* +******************************************************************************** +* Copyright 2007-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +********************************************************************************/ + + +#include "stdint.h" + + +#if defined(__GNUC__) || defined(__ARMCC_VERSION) +#ifndef CY_META_SECTION +#define CY_META_SECTION __attribute__ ((__section__(".cymeta"), used)) +#endif +CY_META_SECTION +#elif defined(__ICCARM__) + +#pragma location=".cymeta" +#else +#error "Unsupported toolchain" +#endif +const uint8_t cy_metadata[] = { +#if defined(CY8C637BZI_BLD74) + 0x00u, 0x05u, 0xE2u, 0x01u, 0x11u, 0x00u, 0x00u, 0x01u, + 0x00u, 0x00u, 0x00u, 0x00u +#elif defined(CY8C6347BZI_BLD53) + 0x00u, 0x05u, 0xE2u, 0x07u, 0x21u, 0x00u, 0x21u, 0x01u, + 0x00u, 0x00u, 0x00u, 0x00u +#else +#error "Unknown target device" +#endif +}; + +#if defined(CY8C637BZI_BLD74) +#if defined(__GNUC__) || defined(__ARMCC_VERSION) +#ifndef CY_CHIP_PROT_SECTION +#define CY_CHIP_PROT_SECTION __attribute__ ((__section__(".cychipprotect"), used)) +#endif +CY_CHIP_PROT_SECTION +#elif defined(__ICCARM__) +#pragma location=".cychipprotect" +#else +#error "Unsupported toolchain" +#endif +const uint8_t cy_meta_chipprotect[] = { + 0x01u +}; +#endif diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/gpio_psoc63_116_bga_ble.h b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/gpio_psoc63_116_bga_ble.h new file mode 100644 index 0000000000..296018caf2 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/gpio_psoc63_116_bga_ble.h @@ -0,0 +1,1884 @@ +/***************************************************************************//** +* \file gpio_psoc63_116_bga_ble.h +* +* \brief +* PSoC 63 device GPIO header for 116-BGA-BLE package +* +* \note +* Generator version: 1.2.0.117 +* Database revision: rev#1034984 +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#ifndef _GPIO_PSOC63_116_BGA_BLE_H_ +#define _GPIO_PSOC63_116_BGA_BLE_H_ + +/* Package type */ +enum +{ + CY_GPIO_PACKAGE_QFN, + CY_GPIO_PACKAGE_BGA, + CY_GPIO_PACKAGE_CSP, + CY_GPIO_PACKAGE_WLCSP, + CY_GPIO_PACKAGE_LQFP, +}; + +#define CY_GPIO_PACKAGE_TYPE CY_GPIO_PACKAGE_BGA + +/* Port List */ +/* PORT 0 (GPIO) */ +#define P0_0_PORT GPIO_PRT0 +#define P0_0_PIN 0u +#define P0_0_NUM 0u +#define P0_1_PORT GPIO_PRT0 +#define P0_1_PIN 1u +#define P0_1_NUM 1u +#define P0_2_PORT GPIO_PRT0 +#define P0_2_PIN 2u +#define P0_2_NUM 2u +#define P0_3_PORT GPIO_PRT0 +#define P0_3_PIN 3u +#define P0_3_NUM 3u +#define P0_4_PORT GPIO_PRT0 +#define P0_4_PIN 4u +#define P0_4_NUM 4u +#define P0_5_PORT GPIO_PRT0 +#define P0_5_PIN 5u +#define P0_5_NUM 5u + +/* PORT 1 (GPIO_OVT) */ +#define P1_0_PORT GPIO_PRT1 +#define P1_0_PIN 0u +#define P1_0_NUM 0u +#define P1_1_PORT GPIO_PRT1 +#define P1_1_PIN 1u +#define P1_1_NUM 1u +#define P1_2_PORT GPIO_PRT1 +#define P1_2_PIN 2u +#define P1_2_NUM 2u +#define P1_3_PORT GPIO_PRT1 +#define P1_3_PIN 3u +#define P1_3_NUM 3u +#define P1_4_PORT GPIO_PRT1 +#define P1_4_PIN 4u +#define P1_4_NUM 4u +#define P1_5_PORT GPIO_PRT1 +#define P1_5_PIN 5u +#define P1_5_NUM 5u + +/* PORT 5 (GPIO) */ +#define P5_0_PORT GPIO_PRT5 +#define P5_0_PIN 0u +#define P5_0_NUM 0u +#define P5_1_PORT GPIO_PRT5 +#define P5_1_PIN 1u +#define P5_1_NUM 1u +#define P5_2_PORT GPIO_PRT5 +#define P5_2_PIN 2u +#define P5_2_NUM 2u +#define P5_3_PORT GPIO_PRT5 +#define P5_3_PIN 3u +#define P5_3_NUM 3u +#define P5_4_PORT GPIO_PRT5 +#define P5_4_PIN 4u +#define P5_4_NUM 4u +#define P5_5_PORT GPIO_PRT5 +#define P5_5_PIN 5u +#define P5_5_NUM 5u +#define P5_6_PORT GPIO_PRT5 +#define P5_6_PIN 6u +#define P5_6_NUM 6u + +/* PORT 6 (GPIO) */ +#define P6_0_PORT GPIO_PRT6 +#define P6_0_PIN 0u +#define P6_0_NUM 0u +#define P6_1_PORT GPIO_PRT6 +#define P6_1_PIN 1u +#define P6_1_NUM 1u +#define P6_2_PORT GPIO_PRT6 +#define P6_2_PIN 2u +#define P6_2_NUM 2u +#define P6_3_PORT GPIO_PRT6 +#define P6_3_PIN 3u +#define P6_3_NUM 3u +#define P6_4_PORT GPIO_PRT6 +#define P6_4_PIN 4u +#define P6_4_NUM 4u +#define P6_5_PORT GPIO_PRT6 +#define P6_5_PIN 5u +#define P6_5_NUM 5u +#define P6_6_PORT GPIO_PRT6 +#define P6_6_PIN 6u +#define P6_6_NUM 6u +#define P6_7_PORT GPIO_PRT6 +#define P6_7_PIN 7u +#define P6_7_NUM 7u + +/* PORT 7 (GPIO) */ +#define P7_0_PORT GPIO_PRT7 +#define P7_0_PIN 0u +#define P7_0_NUM 0u +#define P7_1_PORT GPIO_PRT7 +#define P7_1_PIN 1u +#define P7_1_NUM 1u +#define P7_2_PORT GPIO_PRT7 +#define P7_2_PIN 2u +#define P7_2_NUM 2u +#define P7_3_PORT GPIO_PRT7 +#define P7_3_PIN 3u +#define P7_3_NUM 3u +#define P7_4_PORT GPIO_PRT7 +#define P7_4_PIN 4u +#define P7_4_NUM 4u +#define P7_5_PORT GPIO_PRT7 +#define P7_5_PIN 5u +#define P7_5_NUM 5u +#define P7_6_PORT GPIO_PRT7 +#define P7_6_PIN 6u +#define P7_6_NUM 6u +#define P7_7_PORT GPIO_PRT7 +#define P7_7_PIN 7u +#define P7_7_NUM 7u + +/* PORT 8 (GPIO) */ +#define P8_0_PORT GPIO_PRT8 +#define P8_0_PIN 0u +#define P8_0_NUM 0u +#define P8_1_PORT GPIO_PRT8 +#define P8_1_PIN 1u +#define P8_1_NUM 1u +#define P8_2_PORT GPIO_PRT8 +#define P8_2_PIN 2u +#define P8_2_NUM 2u +#define P8_3_PORT GPIO_PRT8 +#define P8_3_PIN 3u +#define P8_3_NUM 3u +#define P8_4_PORT GPIO_PRT8 +#define P8_4_PIN 4u +#define P8_4_NUM 4u +#define P8_5_PORT GPIO_PRT8 +#define P8_5_PIN 5u +#define P8_5_NUM 5u +#define P8_6_PORT GPIO_PRT8 +#define P8_6_PIN 6u +#define P8_6_NUM 6u +#define P8_7_PORT GPIO_PRT8 +#define P8_7_PIN 7u +#define P8_7_NUM 7u + +/* PORT 9 (GPIO) */ +#define P9_0_PORT GPIO_PRT9 +#define P9_0_PIN 0u +#define P9_0_NUM 0u +#define P9_1_PORT GPIO_PRT9 +#define P9_1_PIN 1u +#define P9_1_NUM 1u +#define P9_2_PORT GPIO_PRT9 +#define P9_2_PIN 2u +#define P9_2_NUM 2u +#define P9_3_PORT GPIO_PRT9 +#define P9_3_PIN 3u +#define P9_3_NUM 3u +#define P9_4_PORT GPIO_PRT9 +#define P9_4_PIN 4u +#define P9_4_NUM 4u +#define P9_5_PORT GPIO_PRT9 +#define P9_5_PIN 5u +#define P9_5_NUM 5u +#define P9_6_PORT GPIO_PRT9 +#define P9_6_PIN 6u +#define P9_6_NUM 6u +#define P9_7_PORT GPIO_PRT9 +#define P9_7_PIN 7u +#define P9_7_NUM 7u + +/* PORT 10 (GPIO) */ +#define P10_0_PORT GPIO_PRT10 +#define P10_0_PIN 0u +#define P10_0_NUM 0u +#define P10_1_PORT GPIO_PRT10 +#define P10_1_PIN 1u +#define P10_1_NUM 1u +#define P10_2_PORT GPIO_PRT10 +#define P10_2_PIN 2u +#define P10_2_NUM 2u +#define P10_3_PORT GPIO_PRT10 +#define P10_3_PIN 3u +#define P10_3_NUM 3u +#define P10_4_PORT GPIO_PRT10 +#define P10_4_PIN 4u +#define P10_4_NUM 4u +#define P10_5_PORT GPIO_PRT10 +#define P10_5_PIN 5u +#define P10_5_NUM 5u +#define P10_6_PORT GPIO_PRT10 +#define P10_6_PIN 6u +#define P10_6_NUM 6u + +/* PORT 11 (GPIO) */ +#define P11_0_PORT GPIO_PRT11 +#define P11_0_PIN 0u +#define P11_0_NUM 0u +#define P11_1_PORT GPIO_PRT11 +#define P11_1_PIN 1u +#define P11_1_NUM 1u +#define P11_2_PORT GPIO_PRT11 +#define P11_2_PIN 2u +#define P11_2_NUM 2u +#define P11_3_PORT GPIO_PRT11 +#define P11_3_PIN 3u +#define P11_3_NUM 3u +#define P11_4_PORT GPIO_PRT11 +#define P11_4_PIN 4u +#define P11_4_NUM 4u +#define P11_5_PORT GPIO_PRT11 +#define P11_5_PIN 5u +#define P11_5_NUM 5u +#define P11_6_PORT GPIO_PRT11 +#define P11_6_PIN 6u +#define P11_6_NUM 6u +#define P11_7_PORT GPIO_PRT11 +#define P11_7_PIN 7u +#define P11_7_NUM 7u + +/* PORT 12 (GPIO) */ +#define P12_0_PORT GPIO_PRT12 +#define P12_0_PIN 0u +#define P12_0_NUM 0u +#define P12_1_PORT GPIO_PRT12 +#define P12_1_PIN 1u +#define P12_1_NUM 1u +#define P12_2_PORT GPIO_PRT12 +#define P12_2_PIN 2u +#define P12_2_NUM 2u +#define P12_3_PORT GPIO_PRT12 +#define P12_3_PIN 3u +#define P12_3_NUM 3u +#define P12_4_PORT GPIO_PRT12 +#define P12_4_PIN 4u +#define P12_4_NUM 4u +#define P12_5_PORT GPIO_PRT12 +#define P12_5_PIN 5u +#define P12_5_NUM 5u +#define P12_6_PORT GPIO_PRT12 +#define P12_6_PIN 6u +#define P12_6_NUM 6u +#define P12_7_PORT GPIO_PRT12 +#define P12_7_PIN 7u +#define P12_7_NUM 7u + +/* PORT 13 (GPIO) */ +#define P13_0_PORT GPIO_PRT13 +#define P13_0_PIN 0u +#define P13_0_NUM 0u +#define P13_1_PORT GPIO_PRT13 +#define P13_1_PIN 1u +#define P13_1_NUM 1u +#define P13_6_PORT GPIO_PRT13 +#define P13_6_PIN 6u +#define P13_6_NUM 6u +#define P13_7_PORT GPIO_PRT13 +#define P13_7_PIN 7u +#define P13_7_NUM 7u + +/* Analog Connections */ +#define CSD_CMODPADD_PORT 7u +#define CSD_CMODPADD_PIN 1u +#define CSD_CMODPADS_PORT 7u +#define CSD_CMODPADS_PIN 1u +#define CSD_CSH_TANKPADD_PORT 7u +#define CSD_CSH_TANKPADD_PIN 2u +#define CSD_CSH_TANKPADS_PORT 7u +#define CSD_CSH_TANKPADS_PIN 2u +#define CSD_CSHIELDPADS_PORT 7u +#define CSD_CSHIELDPADS_PIN 7u +#define CSD_VREF_EXT_PORT 7u +#define CSD_VREF_EXT_PIN 3u +#define IOSS_ADFT0_NET_PORT 10u +#define IOSS_ADFT0_NET_PIN 0u +#define IOSS_ADFT1_NET_PORT 10u +#define IOSS_ADFT1_NET_PIN 1u +#define LPCOMP_INN_COMP1_PORT 6u +#define LPCOMP_INN_COMP1_PIN 3u +#define LPCOMP_INP_COMP0_PORT 5u +#define LPCOMP_INP_COMP0_PIN 6u +#define LPCOMP_INP_COMP1_PORT 6u +#define LPCOMP_INP_COMP1_PIN 2u +#define PASS_AREF_EXT_VREF_PORT 9u +#define PASS_AREF_EXT_VREF_PIN 7u +#define PASS_CTB_OA0_OUT_10X_PORT 9u +#define PASS_CTB_OA0_OUT_10X_PIN 2u +#define PASS_CTB_OA1_OUT_10X_PORT 9u +#define PASS_CTB_OA1_OUT_10X_PIN 3u +#define PASS_CTB_PADS0_PORT 9u +#define PASS_CTB_PADS0_PIN 0u +#define PASS_CTB_PADS1_PORT 9u +#define PASS_CTB_PADS1_PIN 1u +#define PASS_CTB_PADS2_PORT 9u +#define PASS_CTB_PADS2_PIN 2u +#define PASS_CTB_PADS3_PORT 9u +#define PASS_CTB_PADS3_PIN 3u +#define PASS_CTB_PADS4_PORT 9u +#define PASS_CTB_PADS4_PIN 4u +#define PASS_CTB_PADS5_PORT 9u +#define PASS_CTB_PADS5_PIN 5u +#define PASS_CTB_PADS6_PORT 9u +#define PASS_CTB_PADS6_PIN 6u +#define PASS_CTB_PADS7_PORT 9u +#define PASS_CTB_PADS7_PIN 7u +#define PASS_SARMUX_PADS0_PORT 10u +#define PASS_SARMUX_PADS0_PIN 0u +#define PASS_SARMUX_PADS1_PORT 10u +#define PASS_SARMUX_PADS1_PIN 1u +#define PASS_SARMUX_PADS2_PORT 10u +#define PASS_SARMUX_PADS2_PIN 2u +#define PASS_SARMUX_PADS3_PORT 10u +#define PASS_SARMUX_PADS3_PIN 3u +#define PASS_SARMUX_PADS4_PORT 10u +#define PASS_SARMUX_PADS4_PIN 4u +#define PASS_SARMUX_PADS5_PORT 10u +#define PASS_SARMUX_PADS5_PIN 5u +#define PASS_SARMUX_PADS6_PORT 10u +#define PASS_SARMUX_PADS6_PIN 6u +#define SRSS_ADFT_PIN0_PORT 10u +#define SRSS_ADFT_PIN0_PIN 0u +#define SRSS_ADFT_PIN1_PORT 10u +#define SRSS_ADFT_PIN1_PIN 1u +#define SRSS_ECO_IN_PORT 12u +#define SRSS_ECO_IN_PIN 6u +#define SRSS_ECO_OUT_PORT 12u +#define SRSS_ECO_OUT_PIN 7u +#define SRSS_WCO_IN_PORT 0u +#define SRSS_WCO_IN_PIN 0u +#define SRSS_WCO_OUT_PORT 0u +#define SRSS_WCO_OUT_PIN 1u + +/* HSIOM Connections */ +typedef enum +{ + /* Generic HSIOM connections */ + HSIOM_SEL_GPIO = 0, /* GPIO controls 'out' */ + HSIOM_SEL_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + HSIOM_SEL_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + HSIOM_SEL_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + HSIOM_SEL_AMUXA = 4, /* Analog mux bus A */ + HSIOM_SEL_AMUXB = 5, /* Analog mux bus B */ + HSIOM_SEL_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + HSIOM_SEL_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + HSIOM_SEL_ACT_0 = 8, /* Active functionality 0 */ + HSIOM_SEL_ACT_1 = 9, /* Active functionality 1 */ + HSIOM_SEL_ACT_2 = 10, /* Active functionality 2 */ + HSIOM_SEL_ACT_3 = 11, /* Active functionality 3 */ + HSIOM_SEL_DS_0 = 12, /* DeepSleep functionality 0 */ + HSIOM_SEL_DS_1 = 13, /* DeepSleep functionality 1 */ + HSIOM_SEL_DS_2 = 14, /* DeepSleep functionality 2 */ + HSIOM_SEL_DS_3 = 15, /* DeepSleep functionality 3 */ + HSIOM_SEL_ACT_4 = 16, /* Active functionality 4 */ + HSIOM_SEL_ACT_5 = 17, /* Active functionality 5 */ + HSIOM_SEL_ACT_6 = 18, /* Active functionality 6 */ + HSIOM_SEL_ACT_7 = 19, /* Active functionality 7 */ + HSIOM_SEL_ACT_8 = 20, /* Active functionality 8 */ + HSIOM_SEL_ACT_9 = 21, /* Active functionality 9 */ + HSIOM_SEL_ACT_10 = 22, /* Active functionality 10 */ + HSIOM_SEL_ACT_11 = 23, /* Active functionality 11 */ + HSIOM_SEL_ACT_12 = 24, /* Active functionality 12 */ + HSIOM_SEL_ACT_13 = 25, /* Active functionality 13 */ + HSIOM_SEL_ACT_14 = 26, /* Active functionality 14 */ + HSIOM_SEL_ACT_15 = 27, /* Active functionality 15 */ + HSIOM_SEL_DS_4 = 28, /* DeepSleep functionality 4 */ + HSIOM_SEL_DS_5 = 29, /* DeepSleep functionality 5 */ + HSIOM_SEL_DS_6 = 30, /* DeepSleep functionality 6 */ + HSIOM_SEL_DS_7 = 31, /* DeepSleep functionality 7 */ + + /* P0.0 */ + P0_0_GPIO = 0, /* GPIO controls 'out' */ + P0_0_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P0_0_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P0_0_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P0_0_AMUXA = 4, /* Analog mux bus A */ + P0_0_AMUXB = 5, /* Analog mux bus B */ + P0_0_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P0_0_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P0_0_TCPWM0_LINE0 = 8, /* Digital Active - tcpwm[0].line[0]:0 */ + P0_0_TCPWM1_LINE0 = 9, /* Digital Active - tcpwm[1].line[0]:0 */ + P0_0_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:0 */ + P0_0_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:0 */ + P0_0_LCD_COM0 = 12, /* Digital Deep Sleep - lcd.com[0]:0 */ + P0_0_LCD_SEG0 = 13, /* Digital Deep Sleep - lcd.seg[0]:0 */ + P0_0_SRSS_EXT_CLK = 16, /* Digital Active - srss.ext_clk:0 */ + P0_0_SCB0_SPI_SELECT1 = 20, /* Digital Active - scb[0].spi_select1:0 */ + P0_0_PERI_TR_IO_INPUT0 = 24, /* Digital Active - peri.tr_io_input[0]:0 */ + + /* P0.1 */ + P0_1_GPIO = 0, /* GPIO controls 'out' */ + P0_1_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P0_1_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P0_1_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P0_1_AMUXA = 4, /* Analog mux bus A */ + P0_1_AMUXB = 5, /* Analog mux bus B */ + P0_1_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P0_1_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P0_1_TCPWM0_LINE_COMPL0 = 8, /* Digital Active - tcpwm[0].line_compl[0]:0 */ + P0_1_TCPWM1_LINE_COMPL0 = 9, /* Digital Active - tcpwm[1].line_compl[0]:0 */ + P0_1_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:1 */ + P0_1_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:1 */ + P0_1_LCD_COM1 = 12, /* Digital Deep Sleep - lcd.com[1]:0 */ + P0_1_LCD_SEG1 = 13, /* Digital Deep Sleep - lcd.seg[1]:0 */ + P0_1_SCB0_SPI_SELECT2 = 20, /* Digital Active - scb[0].spi_select2:0 */ + P0_1_PERI_TR_IO_INPUT1 = 24, /* Digital Active - peri.tr_io_input[1]:0 */ + P0_1_CPUSS_SWJ_TRSTN = 29, /* Digital Deep Sleep - cpuss.swj_trstn */ + + /* P0.2 */ + P0_2_GPIO = 0, /* GPIO controls 'out' */ + P0_2_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P0_2_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P0_2_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P0_2_AMUXA = 4, /* Analog mux bus A */ + P0_2_AMUXB = 5, /* Analog mux bus B */ + P0_2_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P0_2_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P0_2_TCPWM0_LINE1 = 8, /* Digital Active - tcpwm[0].line[1]:0 */ + P0_2_TCPWM1_LINE1 = 9, /* Digital Active - tcpwm[1].line[1]:0 */ + P0_2_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:2 */ + P0_2_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:2 */ + P0_2_LCD_COM2 = 12, /* Digital Deep Sleep - lcd.com[2]:0 */ + P0_2_LCD_SEG2 = 13, /* Digital Deep Sleep - lcd.seg[2]:0 */ + P0_2_SCB0_UART_RX = 18, /* Digital Active - scb[0].uart_rx:0 */ + P0_2_SCB0_I2C_SCL = 19, /* Digital Active - scb[0].i2c_scl:0 */ + P0_2_SCB0_SPI_MOSI = 20, /* Digital Active - scb[0].spi_mosi:0 */ + + /* P0.3 */ + P0_3_GPIO = 0, /* GPIO controls 'out' */ + P0_3_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P0_3_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P0_3_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P0_3_AMUXA = 4, /* Analog mux bus A */ + P0_3_AMUXB = 5, /* Analog mux bus B */ + P0_3_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P0_3_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P0_3_TCPWM0_LINE_COMPL1 = 8, /* Digital Active - tcpwm[0].line_compl[1]:0 */ + P0_3_TCPWM1_LINE_COMPL1 = 9, /* Digital Active - tcpwm[1].line_compl[1]:0 */ + P0_3_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:3 */ + P0_3_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:3 */ + P0_3_LCD_COM3 = 12, /* Digital Deep Sleep - lcd.com[3]:0 */ + P0_3_LCD_SEG3 = 13, /* Digital Deep Sleep - lcd.seg[3]:0 */ + P0_3_SCB0_UART_TX = 18, /* Digital Active - scb[0].uart_tx:0 */ + P0_3_SCB0_I2C_SDA = 19, /* Digital Active - scb[0].i2c_sda:0 */ + P0_3_SCB0_SPI_MISO = 20, /* Digital Active - scb[0].spi_miso:0 */ + + /* P0.4 */ + P0_4_GPIO = 0, /* GPIO controls 'out' */ + P0_4_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P0_4_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P0_4_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P0_4_AMUXA = 4, /* Analog mux bus A */ + P0_4_AMUXB = 5, /* Analog mux bus B */ + P0_4_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P0_4_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P0_4_TCPWM0_LINE2 = 8, /* Digital Active - tcpwm[0].line[2]:0 */ + P0_4_TCPWM1_LINE2 = 9, /* Digital Active - tcpwm[1].line[2]:0 */ + P0_4_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:4 */ + P0_4_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:4 */ + P0_4_LCD_COM4 = 12, /* Digital Deep Sleep - lcd.com[4]:0 */ + P0_4_LCD_SEG4 = 13, /* Digital Deep Sleep - lcd.seg[4]:0 */ + P0_4_SCB0_UART_RTS = 18, /* Digital Active - scb[0].uart_rts:0 */ + P0_4_SCB0_SPI_CLK = 20, /* Digital Active - scb[0].spi_clk:0 */ + P0_4_PERI_TR_IO_OUTPUT0 = 25, /* Digital Active - peri.tr_io_output[0]:2 */ + + /* P0.5 */ + P0_5_GPIO = 0, /* GPIO controls 'out' */ + P0_5_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P0_5_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P0_5_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P0_5_AMUXA = 4, /* Analog mux bus A */ + P0_5_AMUXB = 5, /* Analog mux bus B */ + P0_5_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P0_5_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P0_5_TCPWM0_LINE_COMPL2 = 8, /* Digital Active - tcpwm[0].line_compl[2]:0 */ + P0_5_TCPWM1_LINE_COMPL2 = 9, /* Digital Active - tcpwm[1].line_compl[2]:0 */ + P0_5_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:5 */ + P0_5_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:5 */ + P0_5_LCD_COM5 = 12, /* Digital Deep Sleep - lcd.com[5]:0 */ + P0_5_LCD_SEG5 = 13, /* Digital Deep Sleep - lcd.seg[5]:0 */ + P0_5_SRSS_EXT_CLK = 16, /* Digital Active - srss.ext_clk:1 */ + P0_5_SCB0_UART_CTS = 18, /* Digital Active - scb[0].uart_cts:0 */ + P0_5_SCB0_SPI_SELECT0 = 20, /* Digital Active - scb[0].spi_select0:0 */ + P0_5_PERI_TR_IO_OUTPUT1 = 25, /* Digital Active - peri.tr_io_output[1]:2 */ + + /* P1.0 */ + P1_0_GPIO = 0, /* GPIO controls 'out' */ + P1_0_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P1_0_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P1_0_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P1_0_AMUXA = 4, /* Analog mux bus A */ + P1_0_AMUXB = 5, /* Analog mux bus B */ + P1_0_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P1_0_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P1_0_TCPWM0_LINE3 = 8, /* Digital Active - tcpwm[0].line[3]:0 */ + P1_0_TCPWM1_LINE3 = 9, /* Digital Active - tcpwm[1].line[3]:0 */ + P1_0_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:6 */ + P1_0_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:6 */ + P1_0_LCD_COM6 = 12, /* Digital Deep Sleep - lcd.com[6]:0 */ + P1_0_LCD_SEG6 = 13, /* Digital Deep Sleep - lcd.seg[6]:0 */ + P1_0_SCB7_UART_RX = 18, /* Digital Active - scb[7].uart_rx:0 */ + P1_0_SCB7_I2C_SCL = 19, /* Digital Active - scb[7].i2c_scl:0 */ + P1_0_SCB7_SPI_MOSI = 20, /* Digital Active - scb[7].spi_mosi:0 */ + P1_0_PERI_TR_IO_INPUT2 = 24, /* Digital Active - peri.tr_io_input[2]:0 */ + + /* P1.1 */ + P1_1_GPIO = 0, /* GPIO controls 'out' */ + P1_1_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P1_1_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P1_1_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P1_1_AMUXA = 4, /* Analog mux bus A */ + P1_1_AMUXB = 5, /* Analog mux bus B */ + P1_1_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P1_1_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P1_1_TCPWM0_LINE_COMPL3 = 8, /* Digital Active - tcpwm[0].line_compl[3]:0 */ + P1_1_TCPWM1_LINE_COMPL3 = 9, /* Digital Active - tcpwm[1].line_compl[3]:0 */ + P1_1_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:7 */ + P1_1_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:7 */ + P1_1_LCD_COM7 = 12, /* Digital Deep Sleep - lcd.com[7]:0 */ + P1_1_LCD_SEG7 = 13, /* Digital Deep Sleep - lcd.seg[7]:0 */ + P1_1_SCB7_UART_TX = 18, /* Digital Active - scb[7].uart_tx:0 */ + P1_1_SCB7_I2C_SDA = 19, /* Digital Active - scb[7].i2c_sda:0 */ + P1_1_SCB7_SPI_MISO = 20, /* Digital Active - scb[7].spi_miso:0 */ + P1_1_PERI_TR_IO_INPUT3 = 24, /* Digital Active - peri.tr_io_input[3]:0 */ + + /* P1.2 */ + P1_2_GPIO = 0, /* GPIO controls 'out' */ + P1_2_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P1_2_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P1_2_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P1_2_AMUXA = 4, /* Analog mux bus A */ + P1_2_AMUXB = 5, /* Analog mux bus B */ + P1_2_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P1_2_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P1_2_TCPWM0_LINE4 = 8, /* Digital Active - tcpwm[0].line[4]:4 */ + P1_2_TCPWM1_LINE12 = 9, /* Digital Active - tcpwm[1].line[12]:1 */ + P1_2_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:8 */ + P1_2_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:8 */ + P1_2_LCD_COM8 = 12, /* Digital Deep Sleep - lcd.com[8]:0 */ + P1_2_LCD_SEG8 = 13, /* Digital Deep Sleep - lcd.seg[8]:0 */ + P1_2_SCB7_UART_RTS = 18, /* Digital Active - scb[7].uart_rts:0 */ + P1_2_SCB7_SPI_CLK = 20, /* Digital Active - scb[7].spi_clk:0 */ + + /* P1.3 */ + P1_3_GPIO = 0, /* GPIO controls 'out' */ + P1_3_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P1_3_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P1_3_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P1_3_AMUXA = 4, /* Analog mux bus A */ + P1_3_AMUXB = 5, /* Analog mux bus B */ + P1_3_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P1_3_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P1_3_TCPWM0_LINE_COMPL4 = 8, /* Digital Active - tcpwm[0].line_compl[4]:4 */ + P1_3_TCPWM1_LINE_COMPL12 = 9, /* Digital Active - tcpwm[1].line_compl[12]:1 */ + P1_3_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:9 */ + P1_3_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:9 */ + P1_3_LCD_COM9 = 12, /* Digital Deep Sleep - lcd.com[9]:0 */ + P1_3_LCD_SEG9 = 13, /* Digital Deep Sleep - lcd.seg[9]:0 */ + P1_3_SCB7_UART_CTS = 18, /* Digital Active - scb[7].uart_cts:0 */ + P1_3_SCB7_SPI_SELECT0 = 20, /* Digital Active - scb[7].spi_select0:0 */ + + /* P1.4 */ + P1_4_GPIO = 0, /* GPIO controls 'out' */ + P1_4_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P1_4_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P1_4_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P1_4_AMUXA = 4, /* Analog mux bus A */ + P1_4_AMUXB = 5, /* Analog mux bus B */ + P1_4_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P1_4_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P1_4_TCPWM0_LINE5 = 8, /* Digital Active - tcpwm[0].line[5]:4 */ + P1_4_TCPWM1_LINE13 = 9, /* Digital Active - tcpwm[1].line[13]:1 */ + P1_4_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:10 */ + P1_4_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:10 */ + P1_4_LCD_COM10 = 12, /* Digital Deep Sleep - lcd.com[10]:0 */ + P1_4_LCD_SEG10 = 13, /* Digital Deep Sleep - lcd.seg[10]:0 */ + P1_4_SCB7_SPI_SELECT1 = 20, /* Digital Active - scb[7].spi_select1:0 */ + + /* P1.5 */ + P1_5_GPIO = 0, /* GPIO controls 'out' */ + P1_5_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P1_5_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P1_5_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P1_5_AMUXA = 4, /* Analog mux bus A */ + P1_5_AMUXB = 5, /* Analog mux bus B */ + P1_5_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P1_5_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P1_5_TCPWM0_LINE_COMPL5 = 8, /* Digital Active - tcpwm[0].line_compl[5]:4 */ + P1_5_TCPWM1_LINE_COMPL14 = 9, /* Digital Active - tcpwm[1].line_compl[14]:1 */ + P1_5_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:11 */ + P1_5_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:11 */ + P1_5_LCD_COM11 = 12, /* Digital Deep Sleep - lcd.com[11]:0 */ + P1_5_LCD_SEG11 = 13, /* Digital Deep Sleep - lcd.seg[11]:0 */ + P1_5_SCB7_SPI_SELECT2 = 20, /* Digital Active - scb[7].spi_select2:0 */ + + /* P5.0 */ + P5_0_GPIO = 0, /* GPIO controls 'out' */ + P5_0_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P5_0_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P5_0_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P5_0_AMUXA = 4, /* Analog mux bus A */ + P5_0_AMUXB = 5, /* Analog mux bus B */ + P5_0_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P5_0_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P5_0_TCPWM0_LINE4 = 8, /* Digital Active - tcpwm[0].line[4]:0 */ + P5_0_TCPWM1_LINE4 = 9, /* Digital Active - tcpwm[1].line[4]:0 */ + P5_0_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:30 */ + P5_0_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:30 */ + P5_0_LCD_COM30 = 12, /* Digital Deep Sleep - lcd.com[30]:0 */ + P5_0_LCD_SEG30 = 13, /* Digital Deep Sleep - lcd.seg[30]:0 */ + P5_0_SCB5_UART_RX = 18, /* Digital Active - scb[5].uart_rx:0 */ + P5_0_SCB5_I2C_SCL = 19, /* Digital Active - scb[5].i2c_scl:0 */ + P5_0_SCB5_SPI_MOSI = 20, /* Digital Active - scb[5].spi_mosi:0 */ + P5_0_AUDIOSS_CLK_I2S_IF = 22, /* Digital Active - audioss.clk_i2s_if */ + P5_0_PERI_TR_IO_INPUT10 = 24, /* Digital Active - peri.tr_io_input[10]:0 */ + + /* P5.1 */ + P5_1_GPIO = 0, /* GPIO controls 'out' */ + P5_1_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P5_1_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P5_1_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P5_1_AMUXA = 4, /* Analog mux bus A */ + P5_1_AMUXB = 5, /* Analog mux bus B */ + P5_1_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P5_1_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P5_1_TCPWM0_LINE_COMPL4 = 8, /* Digital Active - tcpwm[0].line_compl[4]:0 */ + P5_1_TCPWM1_LINE_COMPL4 = 9, /* Digital Active - tcpwm[1].line_compl[4]:0 */ + P5_1_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:31 */ + P5_1_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:31 */ + P5_1_LCD_COM31 = 12, /* Digital Deep Sleep - lcd.com[31]:0 */ + P5_1_LCD_SEG31 = 13, /* Digital Deep Sleep - lcd.seg[31]:0 */ + P5_1_SCB5_UART_TX = 18, /* Digital Active - scb[5].uart_tx:0 */ + P5_1_SCB5_I2C_SDA = 19, /* Digital Active - scb[5].i2c_sda:0 */ + P5_1_SCB5_SPI_MISO = 20, /* Digital Active - scb[5].spi_miso:0 */ + P5_1_AUDIOSS_TX_SCK = 22, /* Digital Active - audioss.tx_sck */ + P5_1_PERI_TR_IO_INPUT11 = 24, /* Digital Active - peri.tr_io_input[11]:0 */ + + /* P5.2 */ + P5_2_GPIO = 0, /* GPIO controls 'out' */ + P5_2_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P5_2_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P5_2_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P5_2_AMUXA = 4, /* Analog mux bus A */ + P5_2_AMUXB = 5, /* Analog mux bus B */ + P5_2_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P5_2_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P5_2_TCPWM0_LINE5 = 8, /* Digital Active - tcpwm[0].line[5]:0 */ + P5_2_TCPWM1_LINE5 = 9, /* Digital Active - tcpwm[1].line[5]:0 */ + P5_2_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:32 */ + P5_2_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:32 */ + P5_2_LCD_COM32 = 12, /* Digital Deep Sleep - lcd.com[32]:0 */ + P5_2_LCD_SEG32 = 13, /* Digital Deep Sleep - lcd.seg[32]:0 */ + P5_2_SCB5_UART_RTS = 18, /* Digital Active - scb[5].uart_rts:0 */ + P5_2_SCB5_SPI_CLK = 20, /* Digital Active - scb[5].spi_clk:0 */ + P5_2_AUDIOSS_TX_WS = 22, /* Digital Active - audioss.tx_ws */ + + /* P5.3 */ + P5_3_GPIO = 0, /* GPIO controls 'out' */ + P5_3_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P5_3_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P5_3_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P5_3_AMUXA = 4, /* Analog mux bus A */ + P5_3_AMUXB = 5, /* Analog mux bus B */ + P5_3_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P5_3_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P5_3_TCPWM0_LINE_COMPL5 = 8, /* Digital Active - tcpwm[0].line_compl[5]:0 */ + P5_3_TCPWM1_LINE_COMPL5 = 9, /* Digital Active - tcpwm[1].line_compl[5]:0 */ + P5_3_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:33 */ + P5_3_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:33 */ + P5_3_LCD_COM33 = 12, /* Digital Deep Sleep - lcd.com[33]:0 */ + P5_3_LCD_SEG33 = 13, /* Digital Deep Sleep - lcd.seg[33]:0 */ + P5_3_SCB5_UART_CTS = 18, /* Digital Active - scb[5].uart_cts:0 */ + P5_3_SCB5_SPI_SELECT0 = 20, /* Digital Active - scb[5].spi_select0:0 */ + P5_3_AUDIOSS_TX_SDO = 22, /* Digital Active - audioss.tx_sdo */ + + /* P5.4 */ + P5_4_GPIO = 0, /* GPIO controls 'out' */ + P5_4_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P5_4_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P5_4_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P5_4_AMUXA = 4, /* Analog mux bus A */ + P5_4_AMUXB = 5, /* Analog mux bus B */ + P5_4_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P5_4_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P5_4_TCPWM0_LINE6 = 8, /* Digital Active - tcpwm[0].line[6]:0 */ + P5_4_TCPWM1_LINE6 = 9, /* Digital Active - tcpwm[1].line[6]:0 */ + P5_4_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:34 */ + P5_4_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:34 */ + P5_4_LCD_COM34 = 12, /* Digital Deep Sleep - lcd.com[34]:0 */ + P5_4_LCD_SEG34 = 13, /* Digital Deep Sleep - lcd.seg[34]:0 */ + P5_4_SCB5_SPI_SELECT1 = 20, /* Digital Active - scb[5].spi_select1:0 */ + P5_4_AUDIOSS_RX_SCK = 22, /* Digital Active - audioss.rx_sck */ + + /* P5.5 */ + P5_5_GPIO = 0, /* GPIO controls 'out' */ + P5_5_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P5_5_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P5_5_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P5_5_AMUXA = 4, /* Analog mux bus A */ + P5_5_AMUXB = 5, /* Analog mux bus B */ + P5_5_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P5_5_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P5_5_TCPWM0_LINE_COMPL6 = 8, /* Digital Active - tcpwm[0].line_compl[6]:0 */ + P5_5_TCPWM1_LINE_COMPL6 = 9, /* Digital Active - tcpwm[1].line_compl[6]:0 */ + P5_5_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:35 */ + P5_5_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:35 */ + P5_5_LCD_COM35 = 12, /* Digital Deep Sleep - lcd.com[35]:0 */ + P5_5_LCD_SEG35 = 13, /* Digital Deep Sleep - lcd.seg[35]:0 */ + P5_5_SCB5_SPI_SELECT2 = 20, /* Digital Active - scb[5].spi_select2:0 */ + P5_5_AUDIOSS_RX_WS = 22, /* Digital Active - audioss.rx_ws */ + + /* P5.6 */ + P5_6_GPIO = 0, /* GPIO controls 'out' */ + P5_6_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P5_6_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P5_6_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P5_6_AMUXA = 4, /* Analog mux bus A */ + P5_6_AMUXB = 5, /* Analog mux bus B */ + P5_6_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P5_6_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P5_6_TCPWM0_LINE7 = 8, /* Digital Active - tcpwm[0].line[7]:0 */ + P5_6_TCPWM1_LINE7 = 9, /* Digital Active - tcpwm[1].line[7]:0 */ + P5_6_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:36 */ + P5_6_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:36 */ + P5_6_LCD_COM36 = 12, /* Digital Deep Sleep - lcd.com[36]:0 */ + P5_6_LCD_SEG36 = 13, /* Digital Deep Sleep - lcd.seg[36]:0 */ + P5_6_SCB5_SPI_SELECT3 = 20, /* Digital Active - scb[5].spi_select3:0 */ + P5_6_AUDIOSS_RX_SDI = 22, /* Digital Active - audioss.rx_sdi */ + + /* P6.0 */ + P6_0_GPIO = 0, /* GPIO controls 'out' */ + P6_0_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P6_0_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P6_0_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P6_0_AMUXA = 4, /* Analog mux bus A */ + P6_0_AMUXB = 5, /* Analog mux bus B */ + P6_0_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P6_0_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P6_0_TCPWM0_LINE0 = 8, /* Digital Active - tcpwm[0].line[0]:1 */ + P6_0_TCPWM1_LINE8 = 9, /* Digital Active - tcpwm[1].line[8]:0 */ + P6_0_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:38 */ + P6_0_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:38 */ + P6_0_LCD_COM38 = 12, /* Digital Deep Sleep - lcd.com[38]:0 */ + P6_0_LCD_SEG38 = 13, /* Digital Deep Sleep - lcd.seg[38]:0 */ + P6_0_SCB8_I2C_SCL = 14, /* Digital Deep Sleep - scb[8].i2c_scl:0 */ + P6_0_SCB3_UART_RX = 18, /* Digital Active - scb[3].uart_rx:0 */ + P6_0_SCB3_I2C_SCL = 19, /* Digital Active - scb[3].i2c_scl:0 */ + P6_0_SCB3_SPI_MOSI = 20, /* Digital Active - scb[3].spi_mosi:0 */ + P6_0_CPUSS_FAULT_OUT0 = 25, /* Digital Active - cpuss.fault_out[0] */ + P6_0_SCB8_SPI_MOSI = 30, /* Digital Deep Sleep - scb[8].spi_mosi:0 */ + + /* P6.1 */ + P6_1_GPIO = 0, /* GPIO controls 'out' */ + P6_1_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P6_1_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P6_1_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P6_1_AMUXA = 4, /* Analog mux bus A */ + P6_1_AMUXB = 5, /* Analog mux bus B */ + P6_1_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P6_1_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P6_1_TCPWM0_LINE_COMPL0 = 8, /* Digital Active - tcpwm[0].line_compl[0]:1 */ + P6_1_TCPWM1_LINE_COMPL8 = 9, /* Digital Active - tcpwm[1].line_compl[8]:0 */ + P6_1_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:39 */ + P6_1_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:39 */ + P6_1_LCD_COM39 = 12, /* Digital Deep Sleep - lcd.com[39]:0 */ + P6_1_LCD_SEG39 = 13, /* Digital Deep Sleep - lcd.seg[39]:0 */ + P6_1_SCB8_I2C_SDA = 14, /* Digital Deep Sleep - scb[8].i2c_sda:0 */ + P6_1_SCB3_UART_TX = 18, /* Digital Active - scb[3].uart_tx:0 */ + P6_1_SCB3_I2C_SDA = 19, /* Digital Active - scb[3].i2c_sda:0 */ + P6_1_SCB3_SPI_MISO = 20, /* Digital Active - scb[3].spi_miso:0 */ + P6_1_CPUSS_FAULT_OUT1 = 25, /* Digital Active - cpuss.fault_out[1] */ + P6_1_SCB8_SPI_MISO = 30, /* Digital Deep Sleep - scb[8].spi_miso:0 */ + + /* P6.2 */ + P6_2_GPIO = 0, /* GPIO controls 'out' */ + P6_2_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P6_2_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P6_2_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P6_2_AMUXA = 4, /* Analog mux bus A */ + P6_2_AMUXB = 5, /* Analog mux bus B */ + P6_2_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P6_2_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P6_2_TCPWM0_LINE1 = 8, /* Digital Active - tcpwm[0].line[1]:1 */ + P6_2_TCPWM1_LINE9 = 9, /* Digital Active - tcpwm[1].line[9]:0 */ + P6_2_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:40 */ + P6_2_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:40 */ + P6_2_LCD_COM40 = 12, /* Digital Deep Sleep - lcd.com[40]:0 */ + P6_2_LCD_SEG40 = 13, /* Digital Deep Sleep - lcd.seg[40]:0 */ + P6_2_SCB3_UART_RTS = 18, /* Digital Active - scb[3].uart_rts:0 */ + P6_2_SCB3_SPI_CLK = 20, /* Digital Active - scb[3].spi_clk:0 */ + P6_2_SCB8_SPI_CLK = 30, /* Digital Deep Sleep - scb[8].spi_clk:0 */ + + /* P6.3 */ + P6_3_GPIO = 0, /* GPIO controls 'out' */ + P6_3_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P6_3_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P6_3_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P6_3_AMUXA = 4, /* Analog mux bus A */ + P6_3_AMUXB = 5, /* Analog mux bus B */ + P6_3_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P6_3_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P6_3_TCPWM0_LINE_COMPL1 = 8, /* Digital Active - tcpwm[0].line_compl[1]:1 */ + P6_3_TCPWM1_LINE_COMPL9 = 9, /* Digital Active - tcpwm[1].line_compl[9]:0 */ + P6_3_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:41 */ + P6_3_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:41 */ + P6_3_LCD_COM41 = 12, /* Digital Deep Sleep - lcd.com[41]:0 */ + P6_3_LCD_SEG41 = 13, /* Digital Deep Sleep - lcd.seg[41]:0 */ + P6_3_SCB3_UART_CTS = 18, /* Digital Active - scb[3].uart_cts:0 */ + P6_3_SCB3_SPI_SELECT0 = 20, /* Digital Active - scb[3].spi_select0:0 */ + P6_3_SCB8_SPI_SELECT0 = 30, /* Digital Deep Sleep - scb[8].spi_select0:0 */ + + /* P6.4 */ + P6_4_GPIO = 0, /* GPIO controls 'out' */ + P6_4_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P6_4_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P6_4_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P6_4_AMUXA = 4, /* Analog mux bus A */ + P6_4_AMUXB = 5, /* Analog mux bus B */ + P6_4_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P6_4_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P6_4_TCPWM0_LINE2 = 8, /* Digital Active - tcpwm[0].line[2]:1 */ + P6_4_TCPWM1_LINE10 = 9, /* Digital Active - tcpwm[1].line[10]:0 */ + P6_4_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:42 */ + P6_4_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:42 */ + P6_4_LCD_COM42 = 12, /* Digital Deep Sleep - lcd.com[42]:0 */ + P6_4_LCD_SEG42 = 13, /* Digital Deep Sleep - lcd.seg[42]:0 */ + P6_4_SCB8_I2C_SCL = 14, /* Digital Deep Sleep - scb[8].i2c_scl:1 */ + P6_4_SCB6_UART_RX = 18, /* Digital Active - scb[6].uart_rx:2 */ + P6_4_SCB6_I2C_SCL = 19, /* Digital Active - scb[6].i2c_scl:2 */ + P6_4_SCB6_SPI_MOSI = 20, /* Digital Active - scb[6].spi_mosi:2 */ + P6_4_PERI_TR_IO_INPUT12 = 24, /* Digital Active - peri.tr_io_input[12]:0 */ + P6_4_PERI_TR_IO_OUTPUT0 = 25, /* Digital Active - peri.tr_io_output[0]:1 */ + P6_4_CPUSS_SWJ_SWO_TDO = 29, /* Digital Deep Sleep - cpuss.swj_swo_tdo */ + P6_4_SCB8_SPI_MOSI = 30, /* Digital Deep Sleep - scb[8].spi_mosi:1 */ + P6_4_SRSS_DDFT_PIN_IN0 = 31, /* Digital Deep Sleep - srss.ddft_pin_in[0]:0 */ + + /* P6.5 */ + P6_5_GPIO = 0, /* GPIO controls 'out' */ + P6_5_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P6_5_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P6_5_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P6_5_AMUXA = 4, /* Analog mux bus A */ + P6_5_AMUXB = 5, /* Analog mux bus B */ + P6_5_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P6_5_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P6_5_TCPWM0_LINE_COMPL2 = 8, /* Digital Active - tcpwm[0].line_compl[2]:1 */ + P6_5_TCPWM1_LINE_COMPL10 = 9, /* Digital Active - tcpwm[1].line_compl[10]:0 */ + P6_5_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:43 */ + P6_5_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:43 */ + P6_5_LCD_COM43 = 12, /* Digital Deep Sleep - lcd.com[43]:0 */ + P6_5_LCD_SEG43 = 13, /* Digital Deep Sleep - lcd.seg[43]:0 */ + P6_5_SCB8_I2C_SDA = 14, /* Digital Deep Sleep - scb[8].i2c_sda:1 */ + P6_5_SCB6_UART_TX = 18, /* Digital Active - scb[6].uart_tx:2 */ + P6_5_SCB6_I2C_SDA = 19, /* Digital Active - scb[6].i2c_sda:2 */ + P6_5_SCB6_SPI_MISO = 20, /* Digital Active - scb[6].spi_miso:2 */ + P6_5_PERI_TR_IO_INPUT13 = 24, /* Digital Active - peri.tr_io_input[13]:0 */ + P6_5_PERI_TR_IO_OUTPUT1 = 25, /* Digital Active - peri.tr_io_output[1]:1 */ + P6_5_CPUSS_SWJ_SWDOE_TDI = 29, /* Digital Deep Sleep - cpuss.swj_swdoe_tdi */ + P6_5_SCB8_SPI_MISO = 30, /* Digital Deep Sleep - scb[8].spi_miso:1 */ + P6_5_SRSS_DDFT_PIN_IN1 = 31, /* Digital Deep Sleep - srss.ddft_pin_in[1]:0 */ + + /* P6.6 */ + P6_6_GPIO = 0, /* GPIO controls 'out' */ + P6_6_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P6_6_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P6_6_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P6_6_AMUXA = 4, /* Analog mux bus A */ + P6_6_AMUXB = 5, /* Analog mux bus B */ + P6_6_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P6_6_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P6_6_TCPWM0_LINE3 = 8, /* Digital Active - tcpwm[0].line[3]:1 */ + P6_6_TCPWM1_LINE11 = 9, /* Digital Active - tcpwm[1].line[11]:0 */ + P6_6_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:44 */ + P6_6_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:44 */ + P6_6_LCD_COM44 = 12, /* Digital Deep Sleep - lcd.com[44]:0 */ + P6_6_LCD_SEG44 = 13, /* Digital Deep Sleep - lcd.seg[44]:0 */ + P6_6_SCB6_UART_RTS = 18, /* Digital Active - scb[6].uart_rts:2 */ + P6_6_SCB6_SPI_CLK = 20, /* Digital Active - scb[6].spi_clk:2 */ + P6_6_CPUSS_SWJ_SWDIO_TMS = 29, /* Digital Deep Sleep - cpuss.swj_swdio_tms */ + P6_6_SCB8_SPI_CLK = 30, /* Digital Deep Sleep - scb[8].spi_clk:1 */ + + /* P6.7 */ + P6_7_GPIO = 0, /* GPIO controls 'out' */ + P6_7_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P6_7_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P6_7_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P6_7_AMUXA = 4, /* Analog mux bus A */ + P6_7_AMUXB = 5, /* Analog mux bus B */ + P6_7_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P6_7_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P6_7_TCPWM0_LINE_COMPL3 = 8, /* Digital Active - tcpwm[0].line_compl[3]:1 */ + P6_7_TCPWM1_LINE_COMPL11 = 9, /* Digital Active - tcpwm[1].line_compl[11]:0 */ + P6_7_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:45 */ + P6_7_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:45 */ + P6_7_LCD_COM45 = 12, /* Digital Deep Sleep - lcd.com[45]:0 */ + P6_7_LCD_SEG45 = 13, /* Digital Deep Sleep - lcd.seg[45]:0 */ + P6_7_SCB6_UART_CTS = 18, /* Digital Active - scb[6].uart_cts:2 */ + P6_7_SCB6_SPI_SELECT0 = 20, /* Digital Active - scb[6].spi_select0:2 */ + P6_7_CPUSS_SWJ_SWCLK_TCLK = 29, /* Digital Deep Sleep - cpuss.swj_swclk_tclk */ + P6_7_SCB8_SPI_SELECT0 = 30, /* Digital Deep Sleep - scb[8].spi_select0:1 */ + + /* P7.0 */ + P7_0_GPIO = 0, /* GPIO controls 'out' */ + P7_0_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P7_0_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P7_0_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P7_0_AMUXA = 4, /* Analog mux bus A */ + P7_0_AMUXB = 5, /* Analog mux bus B */ + P7_0_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P7_0_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P7_0_TCPWM0_LINE4 = 8, /* Digital Active - tcpwm[0].line[4]:1 */ + P7_0_TCPWM1_LINE12 = 9, /* Digital Active - tcpwm[1].line[12]:0 */ + P7_0_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:46 */ + P7_0_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:46 */ + P7_0_LCD_COM46 = 12, /* Digital Deep Sleep - lcd.com[46]:0 */ + P7_0_LCD_SEG46 = 13, /* Digital Deep Sleep - lcd.seg[46]:0 */ + P7_0_SCB4_UART_RX = 18, /* Digital Active - scb[4].uart_rx:1 */ + P7_0_SCB4_I2C_SCL = 19, /* Digital Active - scb[4].i2c_scl:1 */ + P7_0_SCB4_SPI_MOSI = 20, /* Digital Active - scb[4].spi_mosi:1 */ + P7_0_PERI_TR_IO_INPUT14 = 24, /* Digital Active - peri.tr_io_input[14]:0 */ + P7_0_CPUSS_TRACE_CLOCK = 26, /* Digital Active - cpuss.trace_clock */ + + /* P7.1 */ + P7_1_GPIO = 0, /* GPIO controls 'out' */ + P7_1_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P7_1_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P7_1_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P7_1_AMUXA = 4, /* Analog mux bus A */ + P7_1_AMUXB = 5, /* Analog mux bus B */ + P7_1_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P7_1_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P7_1_TCPWM0_LINE_COMPL4 = 8, /* Digital Active - tcpwm[0].line_compl[4]:1 */ + P7_1_TCPWM1_LINE_COMPL12 = 9, /* Digital Active - tcpwm[1].line_compl[12]:0 */ + P7_1_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:47 */ + P7_1_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:47 */ + P7_1_LCD_COM47 = 12, /* Digital Deep Sleep - lcd.com[47]:0 */ + P7_1_LCD_SEG47 = 13, /* Digital Deep Sleep - lcd.seg[47]:0 */ + P7_1_SCB4_UART_TX = 18, /* Digital Active - scb[4].uart_tx:1 */ + P7_1_SCB4_I2C_SDA = 19, /* Digital Active - scb[4].i2c_sda:1 */ + P7_1_SCB4_SPI_MISO = 20, /* Digital Active - scb[4].spi_miso:1 */ + P7_1_PERI_TR_IO_INPUT15 = 24, /* Digital Active - peri.tr_io_input[15]:0 */ + + /* P7.2 */ + P7_2_GPIO = 0, /* GPIO controls 'out' */ + P7_2_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P7_2_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P7_2_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P7_2_AMUXA = 4, /* Analog mux bus A */ + P7_2_AMUXB = 5, /* Analog mux bus B */ + P7_2_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P7_2_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P7_2_TCPWM0_LINE5 = 8, /* Digital Active - tcpwm[0].line[5]:1 */ + P7_2_TCPWM1_LINE13 = 9, /* Digital Active - tcpwm[1].line[13]:0 */ + P7_2_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:48 */ + P7_2_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:48 */ + P7_2_LCD_COM48 = 12, /* Digital Deep Sleep - lcd.com[48]:0 */ + P7_2_LCD_SEG48 = 13, /* Digital Deep Sleep - lcd.seg[48]:0 */ + P7_2_SCB4_UART_RTS = 18, /* Digital Active - scb[4].uart_rts:1 */ + P7_2_SCB4_SPI_CLK = 20, /* Digital Active - scb[4].spi_clk:1 */ + + /* P7.3 */ + P7_3_GPIO = 0, /* GPIO controls 'out' */ + P7_3_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P7_3_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P7_3_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P7_3_AMUXA = 4, /* Analog mux bus A */ + P7_3_AMUXB = 5, /* Analog mux bus B */ + P7_3_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P7_3_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P7_3_TCPWM0_LINE_COMPL5 = 8, /* Digital Active - tcpwm[0].line_compl[5]:1 */ + P7_3_TCPWM1_LINE_COMPL13 = 9, /* Digital Active - tcpwm[1].line_compl[13]:0 */ + P7_3_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:49 */ + P7_3_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:49 */ + P7_3_LCD_COM49 = 12, /* Digital Deep Sleep - lcd.com[49]:0 */ + P7_3_LCD_SEG49 = 13, /* Digital Deep Sleep - lcd.seg[49]:0 */ + P7_3_SCB4_UART_CTS = 18, /* Digital Active - scb[4].uart_cts:1 */ + P7_3_SCB4_SPI_SELECT0 = 20, /* Digital Active - scb[4].spi_select0:1 */ + + /* P7.4 */ + P7_4_GPIO = 0, /* GPIO controls 'out' */ + P7_4_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P7_4_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P7_4_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P7_4_AMUXA = 4, /* Analog mux bus A */ + P7_4_AMUXB = 5, /* Analog mux bus B */ + P7_4_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P7_4_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P7_4_TCPWM0_LINE6 = 8, /* Digital Active - tcpwm[0].line[6]:1 */ + P7_4_TCPWM1_LINE14 = 9, /* Digital Active - tcpwm[1].line[14]:0 */ + P7_4_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:50 */ + P7_4_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:50 */ + P7_4_LCD_COM50 = 12, /* Digital Deep Sleep - lcd.com[50]:0 */ + P7_4_LCD_SEG50 = 13, /* Digital Deep Sleep - lcd.seg[50]:0 */ + P7_4_SCB4_SPI_SELECT1 = 20, /* Digital Active - scb[4].spi_select1:1 */ + P7_4_BLESS_EXT_LNA_RX_CTL_OUT = 26, /* Digital Active - bless.ext_lna_rx_ctl_out */ + P7_4_CPUSS_TRACE_DATA3 = 27, /* Digital Active - cpuss.trace_data[3]:2 */ + + /* P7.5 */ + P7_5_GPIO = 0, /* GPIO controls 'out' */ + P7_5_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P7_5_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P7_5_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P7_5_AMUXA = 4, /* Analog mux bus A */ + P7_5_AMUXB = 5, /* Analog mux bus B */ + P7_5_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P7_5_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P7_5_TCPWM0_LINE_COMPL6 = 8, /* Digital Active - tcpwm[0].line_compl[6]:1 */ + P7_5_TCPWM1_LINE_COMPL14 = 9, /* Digital Active - tcpwm[1].line_compl[14]:0 */ + P7_5_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:51 */ + P7_5_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:51 */ + P7_5_LCD_COM51 = 12, /* Digital Deep Sleep - lcd.com[51]:0 */ + P7_5_LCD_SEG51 = 13, /* Digital Deep Sleep - lcd.seg[51]:0 */ + P7_5_SCB4_SPI_SELECT2 = 20, /* Digital Active - scb[4].spi_select2:1 */ + P7_5_BLESS_EXT_PA_TX_CTL_OUT = 26, /* Digital Active - bless.ext_pa_tx_ctl_out */ + P7_5_CPUSS_TRACE_DATA2 = 27, /* Digital Active - cpuss.trace_data[2]:2 */ + + /* P7.6 */ + P7_6_GPIO = 0, /* GPIO controls 'out' */ + P7_6_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P7_6_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P7_6_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P7_6_AMUXA = 4, /* Analog mux bus A */ + P7_6_AMUXB = 5, /* Analog mux bus B */ + P7_6_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P7_6_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P7_6_TCPWM0_LINE7 = 8, /* Digital Active - tcpwm[0].line[7]:1 */ + P7_6_TCPWM1_LINE15 = 9, /* Digital Active - tcpwm[1].line[15]:0 */ + P7_6_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:52 */ + P7_6_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:52 */ + P7_6_LCD_COM52 = 12, /* Digital Deep Sleep - lcd.com[52]:0 */ + P7_6_LCD_SEG52 = 13, /* Digital Deep Sleep - lcd.seg[52]:0 */ + P7_6_SCB4_SPI_SELECT3 = 20, /* Digital Active - scb[4].spi_select3:1 */ + P7_6_BLESS_EXT_PA_LNA_CHIP_EN_OUT = 26, /* Digital Active - bless.ext_pa_lna_chip_en_out */ + P7_6_CPUSS_TRACE_DATA1 = 27, /* Digital Active - cpuss.trace_data[1]:2 */ + + /* P7.7 */ + P7_7_GPIO = 0, /* GPIO controls 'out' */ + P7_7_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P7_7_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P7_7_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P7_7_AMUXA = 4, /* Analog mux bus A */ + P7_7_AMUXB = 5, /* Analog mux bus B */ + P7_7_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P7_7_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P7_7_TCPWM0_LINE_COMPL7 = 8, /* Digital Active - tcpwm[0].line_compl[7]:1 */ + P7_7_TCPWM1_LINE_COMPL15 = 9, /* Digital Active - tcpwm[1].line_compl[15]:0 */ + P7_7_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:53 */ + P7_7_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:53 */ + P7_7_LCD_COM53 = 12, /* Digital Deep Sleep - lcd.com[53]:0 */ + P7_7_LCD_SEG53 = 13, /* Digital Deep Sleep - lcd.seg[53]:0 */ + P7_7_SCB3_SPI_SELECT1 = 20, /* Digital Active - scb[3].spi_select1:0 */ + P7_7_CPUSS_CLK_FM_PUMP = 21, /* Digital Active - cpuss.clk_fm_pump */ + P7_7_CPUSS_TRACE_DATA0 = 27, /* Digital Active - cpuss.trace_data[0]:2 */ + + /* P8.0 */ + P8_0_GPIO = 0, /* GPIO controls 'out' */ + P8_0_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P8_0_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P8_0_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P8_0_AMUXA = 4, /* Analog mux bus A */ + P8_0_AMUXB = 5, /* Analog mux bus B */ + P8_0_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P8_0_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P8_0_TCPWM0_LINE0 = 8, /* Digital Active - tcpwm[0].line[0]:2 */ + P8_0_TCPWM1_LINE16 = 9, /* Digital Active - tcpwm[1].line[16]:0 */ + P8_0_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:54 */ + P8_0_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:54 */ + P8_0_LCD_COM54 = 12, /* Digital Deep Sleep - lcd.com[54]:0 */ + P8_0_LCD_SEG54 = 13, /* Digital Deep Sleep - lcd.seg[54]:0 */ + P8_0_SCB4_UART_RX = 18, /* Digital Active - scb[4].uart_rx:0 */ + P8_0_SCB4_I2C_SCL = 19, /* Digital Active - scb[4].i2c_scl:0 */ + P8_0_SCB4_SPI_MOSI = 20, /* Digital Active - scb[4].spi_mosi:0 */ + P8_0_PERI_TR_IO_INPUT16 = 24, /* Digital Active - peri.tr_io_input[16]:0 */ + + /* P8.1 */ + P8_1_GPIO = 0, /* GPIO controls 'out' */ + P8_1_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P8_1_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P8_1_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P8_1_AMUXA = 4, /* Analog mux bus A */ + P8_1_AMUXB = 5, /* Analog mux bus B */ + P8_1_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P8_1_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P8_1_TCPWM0_LINE_COMPL0 = 8, /* Digital Active - tcpwm[0].line_compl[0]:2 */ + P8_1_TCPWM1_LINE_COMPL16 = 9, /* Digital Active - tcpwm[1].line_compl[16]:0 */ + P8_1_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:55 */ + P8_1_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:55 */ + P8_1_LCD_COM55 = 12, /* Digital Deep Sleep - lcd.com[55]:0 */ + P8_1_LCD_SEG55 = 13, /* Digital Deep Sleep - lcd.seg[55]:0 */ + P8_1_SCB4_UART_TX = 18, /* Digital Active - scb[4].uart_tx:0 */ + P8_1_SCB4_I2C_SDA = 19, /* Digital Active - scb[4].i2c_sda:0 */ + P8_1_SCB4_SPI_MISO = 20, /* Digital Active - scb[4].spi_miso:0 */ + P8_1_PERI_TR_IO_INPUT17 = 24, /* Digital Active - peri.tr_io_input[17]:0 */ + + /* P8.2 */ + P8_2_GPIO = 0, /* GPIO controls 'out' */ + P8_2_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P8_2_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P8_2_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P8_2_AMUXA = 4, /* Analog mux bus A */ + P8_2_AMUXB = 5, /* Analog mux bus B */ + P8_2_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P8_2_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P8_2_TCPWM0_LINE1 = 8, /* Digital Active - tcpwm[0].line[1]:2 */ + P8_2_TCPWM1_LINE17 = 9, /* Digital Active - tcpwm[1].line[17]:0 */ + P8_2_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:56 */ + P8_2_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:56 */ + P8_2_LCD_COM56 = 12, /* Digital Deep Sleep - lcd.com[56]:0 */ + P8_2_LCD_SEG56 = 13, /* Digital Deep Sleep - lcd.seg[56]:0 */ + P8_2_LPCOMP_DSI_COMP0 = 15, /* Digital Deep Sleep - lpcomp.dsi_comp0:0 */ + P8_2_SCB4_UART_RTS = 18, /* Digital Active - scb[4].uart_rts:0 */ + P8_2_SCB4_SPI_CLK = 20, /* Digital Active - scb[4].spi_clk:0 */ + + /* P8.3 */ + P8_3_GPIO = 0, /* GPIO controls 'out' */ + P8_3_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P8_3_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P8_3_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P8_3_AMUXA = 4, /* Analog mux bus A */ + P8_3_AMUXB = 5, /* Analog mux bus B */ + P8_3_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P8_3_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P8_3_TCPWM0_LINE_COMPL1 = 8, /* Digital Active - tcpwm[0].line_compl[1]:2 */ + P8_3_TCPWM1_LINE_COMPL17 = 9, /* Digital Active - tcpwm[1].line_compl[17]:0 */ + P8_3_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:57 */ + P8_3_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:57 */ + P8_3_LCD_COM57 = 12, /* Digital Deep Sleep - lcd.com[57]:0 */ + P8_3_LCD_SEG57 = 13, /* Digital Deep Sleep - lcd.seg[57]:0 */ + P8_3_LPCOMP_DSI_COMP1 = 15, /* Digital Deep Sleep - lpcomp.dsi_comp1:0 */ + P8_3_SCB4_UART_CTS = 18, /* Digital Active - scb[4].uart_cts:0 */ + P8_3_SCB4_SPI_SELECT0 = 20, /* Digital Active - scb[4].spi_select0:0 */ + + /* P8.4 */ + P8_4_GPIO = 0, /* GPIO controls 'out' */ + P8_4_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P8_4_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P8_4_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P8_4_AMUXA = 4, /* Analog mux bus A */ + P8_4_AMUXB = 5, /* Analog mux bus B */ + P8_4_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P8_4_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P8_4_TCPWM0_LINE2 = 8, /* Digital Active - tcpwm[0].line[2]:2 */ + P8_4_TCPWM1_LINE18 = 9, /* Digital Active - tcpwm[1].line[18]:0 */ + P8_4_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:58 */ + P8_4_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:58 */ + P8_4_LCD_COM58 = 12, /* Digital Deep Sleep - lcd.com[58]:0 */ + P8_4_LCD_SEG58 = 13, /* Digital Deep Sleep - lcd.seg[58]:0 */ + P8_4_SCB4_SPI_SELECT1 = 20, /* Digital Active - scb[4].spi_select1:0 */ + + /* P8.5 */ + P8_5_GPIO = 0, /* GPIO controls 'out' */ + P8_5_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P8_5_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P8_5_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P8_5_AMUXA = 4, /* Analog mux bus A */ + P8_5_AMUXB = 5, /* Analog mux bus B */ + P8_5_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P8_5_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P8_5_TCPWM0_LINE_COMPL2 = 8, /* Digital Active - tcpwm[0].line_compl[2]:2 */ + P8_5_TCPWM1_LINE_COMPL18 = 9, /* Digital Active - tcpwm[1].line_compl[18]:0 */ + P8_5_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:59 */ + P8_5_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:59 */ + P8_5_LCD_COM59 = 12, /* Digital Deep Sleep - lcd.com[59]:0 */ + P8_5_LCD_SEG59 = 13, /* Digital Deep Sleep - lcd.seg[59]:0 */ + P8_5_SCB4_SPI_SELECT2 = 20, /* Digital Active - scb[4].spi_select2:0 */ + + /* P8.6 */ + P8_6_GPIO = 0, /* GPIO controls 'out' */ + P8_6_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P8_6_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P8_6_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P8_6_AMUXA = 4, /* Analog mux bus A */ + P8_6_AMUXB = 5, /* Analog mux bus B */ + P8_6_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P8_6_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P8_6_TCPWM0_LINE3 = 8, /* Digital Active - tcpwm[0].line[3]:2 */ + P8_6_TCPWM1_LINE19 = 9, /* Digital Active - tcpwm[1].line[19]:0 */ + P8_6_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:60 */ + P8_6_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:60 */ + P8_6_LCD_COM60 = 12, /* Digital Deep Sleep - lcd.com[60]:0 */ + P8_6_LCD_SEG60 = 13, /* Digital Deep Sleep - lcd.seg[60]:0 */ + P8_6_SCB4_SPI_SELECT3 = 20, /* Digital Active - scb[4].spi_select3:0 */ + + /* P8.7 */ + P8_7_GPIO = 0, /* GPIO controls 'out' */ + P8_7_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P8_7_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P8_7_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P8_7_AMUXA = 4, /* Analog mux bus A */ + P8_7_AMUXB = 5, /* Analog mux bus B */ + P8_7_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P8_7_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P8_7_TCPWM0_LINE_COMPL3 = 8, /* Digital Active - tcpwm[0].line_compl[3]:2 */ + P8_7_TCPWM1_LINE_COMPL19 = 9, /* Digital Active - tcpwm[1].line_compl[19]:0 */ + P8_7_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:61 */ + P8_7_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:61 */ + P8_7_LCD_COM61 = 12, /* Digital Deep Sleep - lcd.com[61]:0 */ + P8_7_LCD_SEG61 = 13, /* Digital Deep Sleep - lcd.seg[61]:0 */ + P8_7_SCB3_SPI_SELECT2 = 20, /* Digital Active - scb[3].spi_select2:0 */ + + /* P9.0 */ + P9_0_GPIO = 0, /* GPIO controls 'out' */ + P9_0_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P9_0_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P9_0_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P9_0_AMUXA = 4, /* Analog mux bus A */ + P9_0_AMUXB = 5, /* Analog mux bus B */ + P9_0_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P9_0_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P9_0_TCPWM0_LINE4 = 8, /* Digital Active - tcpwm[0].line[4]:2 */ + P9_0_TCPWM1_LINE20 = 9, /* Digital Active - tcpwm[1].line[20]:0 */ + P9_0_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:62 */ + P9_0_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:62 */ + P9_0_LCD_COM0 = 12, /* Digital Deep Sleep - lcd.com[0]:1 */ + P9_0_LCD_SEG0 = 13, /* Digital Deep Sleep - lcd.seg[0]:1 */ + P9_0_SCB2_UART_RX = 18, /* Digital Active - scb[2].uart_rx:0 */ + P9_0_SCB2_I2C_SCL = 19, /* Digital Active - scb[2].i2c_scl:0 */ + P9_0_SCB2_SPI_MOSI = 20, /* Digital Active - scb[2].spi_mosi:0 */ + P9_0_PERI_TR_IO_INPUT18 = 24, /* Digital Active - peri.tr_io_input[18]:0 */ + P9_0_CPUSS_TRACE_DATA3 = 27, /* Digital Active - cpuss.trace_data[3]:0 */ + + /* P9.1 */ + P9_1_GPIO = 0, /* GPIO controls 'out' */ + P9_1_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P9_1_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P9_1_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P9_1_AMUXA = 4, /* Analog mux bus A */ + P9_1_AMUXB = 5, /* Analog mux bus B */ + P9_1_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P9_1_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P9_1_TCPWM0_LINE_COMPL4 = 8, /* Digital Active - tcpwm[0].line_compl[4]:2 */ + P9_1_TCPWM1_LINE_COMPL20 = 9, /* Digital Active - tcpwm[1].line_compl[20]:0 */ + P9_1_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:63 */ + P9_1_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:63 */ + P9_1_LCD_COM1 = 12, /* Digital Deep Sleep - lcd.com[1]:1 */ + P9_1_LCD_SEG1 = 13, /* Digital Deep Sleep - lcd.seg[1]:1 */ + P9_1_SCB2_UART_TX = 18, /* Digital Active - scb[2].uart_tx:0 */ + P9_1_SCB2_I2C_SDA = 19, /* Digital Active - scb[2].i2c_sda:0 */ + P9_1_SCB2_SPI_MISO = 20, /* Digital Active - scb[2].spi_miso:0 */ + P9_1_PERI_TR_IO_INPUT19 = 24, /* Digital Active - peri.tr_io_input[19]:0 */ + P9_1_CPUSS_TRACE_DATA2 = 27, /* Digital Active - cpuss.trace_data[2]:0 */ + P9_1_SRSS_DDFT_PIN_IN0 = 31, /* Digital Deep Sleep - srss.ddft_pin_in[0]:1 */ + + /* P9.2 */ + P9_2_GPIO = 0, /* GPIO controls 'out' */ + P9_2_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P9_2_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P9_2_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P9_2_AMUXA = 4, /* Analog mux bus A */ + P9_2_AMUXB = 5, /* Analog mux bus B */ + P9_2_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P9_2_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P9_2_TCPWM0_LINE5 = 8, /* Digital Active - tcpwm[0].line[5]:2 */ + P9_2_TCPWM1_LINE21 = 9, /* Digital Active - tcpwm[1].line[21]:0 */ + P9_2_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:64 */ + P9_2_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:64 */ + P9_2_LCD_COM2 = 12, /* Digital Deep Sleep - lcd.com[2]:1 */ + P9_2_LCD_SEG2 = 13, /* Digital Deep Sleep - lcd.seg[2]:1 */ + P9_2_SCB2_UART_RTS = 18, /* Digital Active - scb[2].uart_rts:0 */ + P9_2_SCB2_SPI_CLK = 20, /* Digital Active - scb[2].spi_clk:0 */ + P9_2_PASS_DSI_CTB_CMP0 = 22, /* Digital Active - pass.dsi_ctb_cmp0:1 */ + P9_2_CPUSS_TRACE_DATA1 = 27, /* Digital Active - cpuss.trace_data[1]:0 */ + + /* P9.3 */ + P9_3_GPIO = 0, /* GPIO controls 'out' */ + P9_3_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P9_3_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P9_3_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P9_3_AMUXA = 4, /* Analog mux bus A */ + P9_3_AMUXB = 5, /* Analog mux bus B */ + P9_3_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P9_3_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P9_3_TCPWM0_LINE_COMPL5 = 8, /* Digital Active - tcpwm[0].line_compl[5]:2 */ + P9_3_TCPWM1_LINE_COMPL21 = 9, /* Digital Active - tcpwm[1].line_compl[21]:0 */ + P9_3_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:65 */ + P9_3_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:65 */ + P9_3_LCD_COM3 = 12, /* Digital Deep Sleep - lcd.com[3]:1 */ + P9_3_LCD_SEG3 = 13, /* Digital Deep Sleep - lcd.seg[3]:1 */ + P9_3_SCB2_UART_CTS = 18, /* Digital Active - scb[2].uart_cts:0 */ + P9_3_SCB2_SPI_SELECT0 = 20, /* Digital Active - scb[2].spi_select0:0 */ + P9_3_PASS_DSI_CTB_CMP1 = 22, /* Digital Active - pass.dsi_ctb_cmp1:1 */ + P9_3_CPUSS_TRACE_DATA0 = 27, /* Digital Active - cpuss.trace_data[0]:0 */ + P9_3_SRSS_DDFT_PIN_IN1 = 31, /* Digital Deep Sleep - srss.ddft_pin_in[1]:1 */ + + /* P9.4 */ + P9_4_GPIO = 0, /* GPIO controls 'out' */ + P9_4_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P9_4_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P9_4_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P9_4_AMUXA = 4, /* Analog mux bus A */ + P9_4_AMUXB = 5, /* Analog mux bus B */ + P9_4_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P9_4_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P9_4_TCPWM0_LINE7 = 8, /* Digital Active - tcpwm[0].line[7]:5 */ + P9_4_TCPWM1_LINE0 = 9, /* Digital Active - tcpwm[1].line[0]:2 */ + P9_4_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:66 */ + P9_4_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:66 */ + P9_4_LCD_COM4 = 12, /* Digital Deep Sleep - lcd.com[4]:1 */ + P9_4_LCD_SEG4 = 13, /* Digital Deep Sleep - lcd.seg[4]:1 */ + P9_4_SCB2_SPI_SELECT1 = 20, /* Digital Active - scb[2].spi_select1:0 */ + + /* P9.5 */ + P9_5_GPIO = 0, /* GPIO controls 'out' */ + P9_5_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P9_5_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P9_5_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P9_5_AMUXA = 4, /* Analog mux bus A */ + P9_5_AMUXB = 5, /* Analog mux bus B */ + P9_5_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P9_5_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P9_5_TCPWM0_LINE_COMPL7 = 8, /* Digital Active - tcpwm[0].line_compl[7]:5 */ + P9_5_TCPWM1_LINE_COMPL0 = 9, /* Digital Active - tcpwm[1].line_compl[0]:2 */ + P9_5_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:67 */ + P9_5_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:67 */ + P9_5_LCD_COM5 = 12, /* Digital Deep Sleep - lcd.com[5]:1 */ + P9_5_LCD_SEG5 = 13, /* Digital Deep Sleep - lcd.seg[5]:1 */ + P9_5_SCB2_SPI_SELECT2 = 20, /* Digital Active - scb[2].spi_select2:0 */ + + /* P9.6 */ + P9_6_GPIO = 0, /* GPIO controls 'out' */ + P9_6_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P9_6_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P9_6_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P9_6_AMUXA = 4, /* Analog mux bus A */ + P9_6_AMUXB = 5, /* Analog mux bus B */ + P9_6_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P9_6_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P9_6_TCPWM0_LINE0 = 8, /* Digital Active - tcpwm[0].line[0]:6 */ + P9_6_TCPWM1_LINE1 = 9, /* Digital Active - tcpwm[1].line[1]:2 */ + P9_6_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:68 */ + P9_6_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:68 */ + P9_6_LCD_COM6 = 12, /* Digital Deep Sleep - lcd.com[6]:1 */ + P9_6_LCD_SEG6 = 13, /* Digital Deep Sleep - lcd.seg[6]:1 */ + P9_6_SCB2_SPI_SELECT3 = 20, /* Digital Active - scb[2].spi_select3:0 */ + + /* P9.7 */ + P9_7_GPIO = 0, /* GPIO controls 'out' */ + P9_7_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P9_7_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P9_7_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P9_7_AMUXA = 4, /* Analog mux bus A */ + P9_7_AMUXB = 5, /* Analog mux bus B */ + P9_7_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P9_7_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P9_7_TCPWM0_LINE_COMPL0 = 8, /* Digital Active - tcpwm[0].line_compl[0]:6 */ + P9_7_TCPWM1_LINE_COMPL1 = 9, /* Digital Active - tcpwm[1].line_compl[1]:2 */ + P9_7_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:69 */ + P9_7_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:69 */ + P9_7_LCD_COM7 = 12, /* Digital Deep Sleep - lcd.com[7]:1 */ + P9_7_LCD_SEG7 = 13, /* Digital Deep Sleep - lcd.seg[7]:1 */ + + /* P10.0 */ + P10_0_GPIO = 0, /* GPIO controls 'out' */ + P10_0_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P10_0_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P10_0_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P10_0_AMUXA = 4, /* Analog mux bus A */ + P10_0_AMUXB = 5, /* Analog mux bus B */ + P10_0_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P10_0_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P10_0_TCPWM0_LINE6 = 8, /* Digital Active - tcpwm[0].line[6]:2 */ + P10_0_TCPWM1_LINE22 = 9, /* Digital Active - tcpwm[1].line[22]:0 */ + P10_0_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:70 */ + P10_0_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:70 */ + P10_0_LCD_COM8 = 12, /* Digital Deep Sleep - lcd.com[8]:1 */ + P10_0_LCD_SEG8 = 13, /* Digital Deep Sleep - lcd.seg[8]:1 */ + P10_0_SCB1_UART_RX = 18, /* Digital Active - scb[1].uart_rx:1 */ + P10_0_SCB1_I2C_SCL = 19, /* Digital Active - scb[1].i2c_scl:1 */ + P10_0_SCB1_SPI_MOSI = 20, /* Digital Active - scb[1].spi_mosi:1 */ + P10_0_PERI_TR_IO_INPUT20 = 24, /* Digital Active - peri.tr_io_input[20]:0 */ + P10_0_CPUSS_TRACE_DATA3 = 27, /* Digital Active - cpuss.trace_data[3]:1 */ + + /* P10.1 */ + P10_1_GPIO = 0, /* GPIO controls 'out' */ + P10_1_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P10_1_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P10_1_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P10_1_AMUXA = 4, /* Analog mux bus A */ + P10_1_AMUXB = 5, /* Analog mux bus B */ + P10_1_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P10_1_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P10_1_TCPWM0_LINE_COMPL6 = 8, /* Digital Active - tcpwm[0].line_compl[6]:2 */ + P10_1_TCPWM1_LINE_COMPL22 = 9, /* Digital Active - tcpwm[1].line_compl[22]:0 */ + P10_1_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:71 */ + P10_1_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:71 */ + P10_1_LCD_COM9 = 12, /* Digital Deep Sleep - lcd.com[9]:1 */ + P10_1_LCD_SEG9 = 13, /* Digital Deep Sleep - lcd.seg[9]:1 */ + P10_1_SCB1_UART_TX = 18, /* Digital Active - scb[1].uart_tx:1 */ + P10_1_SCB1_I2C_SDA = 19, /* Digital Active - scb[1].i2c_sda:1 */ + P10_1_SCB1_SPI_MISO = 20, /* Digital Active - scb[1].spi_miso:1 */ + P10_1_PERI_TR_IO_INPUT21 = 24, /* Digital Active - peri.tr_io_input[21]:0 */ + P10_1_CPUSS_TRACE_DATA2 = 27, /* Digital Active - cpuss.trace_data[2]:1 */ + + /* P10.2 */ + P10_2_GPIO = 0, /* GPIO controls 'out' */ + P10_2_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P10_2_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P10_2_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P10_2_AMUXA = 4, /* Analog mux bus A */ + P10_2_AMUXB = 5, /* Analog mux bus B */ + P10_2_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P10_2_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P10_2_TCPWM0_LINE7 = 8, /* Digital Active - tcpwm[0].line[7]:2 */ + P10_2_TCPWM1_LINE23 = 9, /* Digital Active - tcpwm[1].line[23]:0 */ + P10_2_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:72 */ + P10_2_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:72 */ + P10_2_LCD_COM10 = 12, /* Digital Deep Sleep - lcd.com[10]:1 */ + P10_2_LCD_SEG10 = 13, /* Digital Deep Sleep - lcd.seg[10]:1 */ + P10_2_SCB1_UART_RTS = 18, /* Digital Active - scb[1].uart_rts:1 */ + P10_2_SCB1_SPI_CLK = 20, /* Digital Active - scb[1].spi_clk:1 */ + P10_2_CPUSS_TRACE_DATA1 = 27, /* Digital Active - cpuss.trace_data[1]:1 */ + + /* P10.3 */ + P10_3_GPIO = 0, /* GPIO controls 'out' */ + P10_3_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P10_3_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P10_3_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P10_3_AMUXA = 4, /* Analog mux bus A */ + P10_3_AMUXB = 5, /* Analog mux bus B */ + P10_3_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P10_3_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P10_3_TCPWM0_LINE_COMPL7 = 8, /* Digital Active - tcpwm[0].line_compl[7]:2 */ + P10_3_TCPWM1_LINE_COMPL23 = 9, /* Digital Active - tcpwm[1].line_compl[23]:0 */ + P10_3_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:73 */ + P10_3_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:73 */ + P10_3_LCD_COM11 = 12, /* Digital Deep Sleep - lcd.com[11]:1 */ + P10_3_LCD_SEG11 = 13, /* Digital Deep Sleep - lcd.seg[11]:1 */ + P10_3_SCB1_UART_CTS = 18, /* Digital Active - scb[1].uart_cts:1 */ + P10_3_SCB1_SPI_SELECT0 = 20, /* Digital Active - scb[1].spi_select0:1 */ + P10_3_CPUSS_TRACE_DATA0 = 27, /* Digital Active - cpuss.trace_data[0]:1 */ + + /* P10.4 */ + P10_4_GPIO = 0, /* GPIO controls 'out' */ + P10_4_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P10_4_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P10_4_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P10_4_AMUXA = 4, /* Analog mux bus A */ + P10_4_AMUXB = 5, /* Analog mux bus B */ + P10_4_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P10_4_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P10_4_TCPWM0_LINE0 = 8, /* Digital Active - tcpwm[0].line[0]:3 */ + P10_4_TCPWM1_LINE0 = 9, /* Digital Active - tcpwm[1].line[0]:1 */ + P10_4_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:74 */ + P10_4_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:74 */ + P10_4_LCD_COM12 = 12, /* Digital Deep Sleep - lcd.com[12]:1 */ + P10_4_LCD_SEG12 = 13, /* Digital Deep Sleep - lcd.seg[12]:1 */ + P10_4_SCB1_SPI_SELECT1 = 20, /* Digital Active - scb[1].spi_select1:1 */ + P10_4_AUDIOSS_PDM_CLK = 21, /* Digital Active - audioss.pdm_clk:0 */ + + /* P10.5 */ + P10_5_GPIO = 0, /* GPIO controls 'out' */ + P10_5_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P10_5_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P10_5_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P10_5_AMUXA = 4, /* Analog mux bus A */ + P10_5_AMUXB = 5, /* Analog mux bus B */ + P10_5_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P10_5_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P10_5_TCPWM0_LINE_COMPL0 = 8, /* Digital Active - tcpwm[0].line_compl[0]:3 */ + P10_5_TCPWM1_LINE_COMPL0 = 9, /* Digital Active - tcpwm[1].line_compl[0]:1 */ + P10_5_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:75 */ + P10_5_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:75 */ + P10_5_LCD_COM13 = 12, /* Digital Deep Sleep - lcd.com[13]:1 */ + P10_5_LCD_SEG13 = 13, /* Digital Deep Sleep - lcd.seg[13]:1 */ + P10_5_SCB1_SPI_SELECT2 = 20, /* Digital Active - scb[1].spi_select2:1 */ + P10_5_AUDIOSS_PDM_DATA = 21, /* Digital Active - audioss.pdm_data:0 */ + + /* P10.6 */ + P10_6_GPIO = 0, /* GPIO controls 'out' */ + P10_6_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P10_6_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P10_6_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P10_6_AMUXA = 4, /* Analog mux bus A */ + P10_6_AMUXB = 5, /* Analog mux bus B */ + P10_6_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P10_6_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P10_6_TCPWM0_LINE1 = 8, /* Digital Active - tcpwm[0].line[1]:6 */ + P10_6_TCPWM1_LINE2 = 9, /* Digital Active - tcpwm[1].line[2]:2 */ + P10_6_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:76 */ + P10_6_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:76 */ + P10_6_LCD_COM14 = 12, /* Digital Deep Sleep - lcd.com[14]:1 */ + P10_6_LCD_SEG14 = 13, /* Digital Deep Sleep - lcd.seg[14]:1 */ + P10_6_SCB1_SPI_SELECT3 = 20, /* Digital Active - scb[1].spi_select3:1 */ + + /* P11.0 */ + P11_0_GPIO = 0, /* GPIO controls 'out' */ + P11_0_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P11_0_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P11_0_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P11_0_AMUXA = 4, /* Analog mux bus A */ + P11_0_AMUXB = 5, /* Analog mux bus B */ + P11_0_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P11_0_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P11_0_TCPWM0_LINE1 = 8, /* Digital Active - tcpwm[0].line[1]:3 */ + P11_0_TCPWM1_LINE1 = 9, /* Digital Active - tcpwm[1].line[1]:1 */ + P11_0_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:78 */ + P11_0_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:78 */ + P11_0_LCD_COM16 = 12, /* Digital Deep Sleep - lcd.com[16]:1 */ + P11_0_LCD_SEG16 = 13, /* Digital Deep Sleep - lcd.seg[16]:1 */ + P11_0_SMIF_SPI_SELECT2 = 17, /* Digital Active - smif.spi_select2 */ + P11_0_SCB5_UART_RX = 18, /* Digital Active - scb[5].uart_rx:1 */ + P11_0_SCB5_I2C_SCL = 19, /* Digital Active - scb[5].i2c_scl:1 */ + P11_0_SCB5_SPI_MOSI = 20, /* Digital Active - scb[5].spi_mosi:1 */ + P11_0_PERI_TR_IO_INPUT22 = 24, /* Digital Active - peri.tr_io_input[22]:0 */ + + /* P11.1 */ + P11_1_GPIO = 0, /* GPIO controls 'out' */ + P11_1_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P11_1_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P11_1_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P11_1_AMUXA = 4, /* Analog mux bus A */ + P11_1_AMUXB = 5, /* Analog mux bus B */ + P11_1_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P11_1_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P11_1_TCPWM0_LINE_COMPL1 = 8, /* Digital Active - tcpwm[0].line_compl[1]:3 */ + P11_1_TCPWM1_LINE_COMPL1 = 9, /* Digital Active - tcpwm[1].line_compl[1]:1 */ + P11_1_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:79 */ + P11_1_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:79 */ + P11_1_LCD_COM17 = 12, /* Digital Deep Sleep - lcd.com[17]:1 */ + P11_1_LCD_SEG17 = 13, /* Digital Deep Sleep - lcd.seg[17]:1 */ + P11_1_SMIF_SPI_SELECT1 = 17, /* Digital Active - smif.spi_select1 */ + P11_1_SCB5_UART_TX = 18, /* Digital Active - scb[5].uart_tx:1 */ + P11_1_SCB5_I2C_SDA = 19, /* Digital Active - scb[5].i2c_sda:1 */ + P11_1_SCB5_SPI_MISO = 20, /* Digital Active - scb[5].spi_miso:1 */ + P11_1_PERI_TR_IO_INPUT23 = 24, /* Digital Active - peri.tr_io_input[23]:0 */ + + /* P11.2 */ + P11_2_GPIO = 0, /* GPIO controls 'out' */ + P11_2_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P11_2_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P11_2_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P11_2_AMUXA = 4, /* Analog mux bus A */ + P11_2_AMUXB = 5, /* Analog mux bus B */ + P11_2_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P11_2_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P11_2_TCPWM0_LINE2 = 8, /* Digital Active - tcpwm[0].line[2]:3 */ + P11_2_TCPWM1_LINE2 = 9, /* Digital Active - tcpwm[1].line[2]:1 */ + P11_2_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:80 */ + P11_2_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:80 */ + P11_2_LCD_COM18 = 12, /* Digital Deep Sleep - lcd.com[18]:1 */ + P11_2_LCD_SEG18 = 13, /* Digital Deep Sleep - lcd.seg[18]:1 */ + P11_2_SMIF_SPI_SELECT0 = 17, /* Digital Active - smif.spi_select0 */ + P11_2_SCB5_UART_RTS = 18, /* Digital Active - scb[5].uart_rts:1 */ + P11_2_SCB5_SPI_CLK = 20, /* Digital Active - scb[5].spi_clk:1 */ + + /* P11.3 */ + P11_3_GPIO = 0, /* GPIO controls 'out' */ + P11_3_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P11_3_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P11_3_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P11_3_AMUXA = 4, /* Analog mux bus A */ + P11_3_AMUXB = 5, /* Analog mux bus B */ + P11_3_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P11_3_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P11_3_TCPWM0_LINE_COMPL2 = 8, /* Digital Active - tcpwm[0].line_compl[2]:3 */ + P11_3_TCPWM1_LINE_COMPL2 = 9, /* Digital Active - tcpwm[1].line_compl[2]:1 */ + P11_3_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:81 */ + P11_3_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:81 */ + P11_3_LCD_COM19 = 12, /* Digital Deep Sleep - lcd.com[19]:1 */ + P11_3_LCD_SEG19 = 13, /* Digital Deep Sleep - lcd.seg[19]:1 */ + P11_3_SMIF_SPI_DATA3 = 17, /* Digital Active - smif.spi_data3 */ + P11_3_SCB5_UART_CTS = 18, /* Digital Active - scb[5].uart_cts:1 */ + P11_3_SCB5_SPI_SELECT0 = 20, /* Digital Active - scb[5].spi_select0:1 */ + P11_3_PERI_TR_IO_OUTPUT0 = 25, /* Digital Active - peri.tr_io_output[0]:0 */ + + /* P11.4 */ + P11_4_GPIO = 0, /* GPIO controls 'out' */ + P11_4_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P11_4_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P11_4_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P11_4_AMUXA = 4, /* Analog mux bus A */ + P11_4_AMUXB = 5, /* Analog mux bus B */ + P11_4_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P11_4_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P11_4_TCPWM0_LINE3 = 8, /* Digital Active - tcpwm[0].line[3]:3 */ + P11_4_TCPWM1_LINE3 = 9, /* Digital Active - tcpwm[1].line[3]:1 */ + P11_4_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:82 */ + P11_4_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:82 */ + P11_4_LCD_COM20 = 12, /* Digital Deep Sleep - lcd.com[20]:1 */ + P11_4_LCD_SEG20 = 13, /* Digital Deep Sleep - lcd.seg[20]:1 */ + P11_4_SMIF_SPI_DATA2 = 17, /* Digital Active - smif.spi_data2 */ + P11_4_SCB5_SPI_SELECT1 = 20, /* Digital Active - scb[5].spi_select1:1 */ + P11_4_PERI_TR_IO_OUTPUT1 = 25, /* Digital Active - peri.tr_io_output[1]:0 */ + + /* P11.5 */ + P11_5_GPIO = 0, /* GPIO controls 'out' */ + P11_5_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P11_5_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P11_5_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P11_5_AMUXA = 4, /* Analog mux bus A */ + P11_5_AMUXB = 5, /* Analog mux bus B */ + P11_5_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P11_5_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P11_5_TCPWM0_LINE_COMPL3 = 8, /* Digital Active - tcpwm[0].line_compl[3]:3 */ + P11_5_TCPWM1_LINE_COMPL3 = 9, /* Digital Active - tcpwm[1].line_compl[3]:1 */ + P11_5_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:83 */ + P11_5_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:83 */ + P11_5_LCD_COM21 = 12, /* Digital Deep Sleep - lcd.com[21]:1 */ + P11_5_LCD_SEG21 = 13, /* Digital Deep Sleep - lcd.seg[21]:1 */ + P11_5_SMIF_SPI_DATA1 = 17, /* Digital Active - smif.spi_data1 */ + P11_5_SCB5_SPI_SELECT2 = 20, /* Digital Active - scb[5].spi_select2:1 */ + + /* P11.6 */ + P11_6_GPIO = 0, /* GPIO controls 'out' */ + P11_6_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P11_6_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P11_6_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P11_6_AMUXA = 4, /* Analog mux bus A */ + P11_6_AMUXB = 5, /* Analog mux bus B */ + P11_6_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P11_6_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P11_6_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:84 */ + P11_6_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:84 */ + P11_6_LCD_COM22 = 12, /* Digital Deep Sleep - lcd.com[22]:1 */ + P11_6_LCD_SEG22 = 13, /* Digital Deep Sleep - lcd.seg[22]:1 */ + P11_6_SMIF_SPI_DATA0 = 17, /* Digital Active - smif.spi_data0 */ + P11_6_SCB5_SPI_SELECT3 = 20, /* Digital Active - scb[5].spi_select3:1 */ + + /* P11.7 */ + P11_7_GPIO = 0, /* GPIO controls 'out' */ + P11_7_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P11_7_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P11_7_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P11_7_AMUXA = 4, /* Analog mux bus A */ + P11_7_AMUXB = 5, /* Analog mux bus B */ + P11_7_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P11_7_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P11_7_SMIF_SPI_CLK = 17, /* Digital Active - smif.spi_clk */ + + /* P12.0 */ + P12_0_GPIO = 0, /* GPIO controls 'out' */ + P12_0_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P12_0_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P12_0_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P12_0_AMUXA = 4, /* Analog mux bus A */ + P12_0_AMUXB = 5, /* Analog mux bus B */ + P12_0_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P12_0_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P12_0_TCPWM0_LINE4 = 8, /* Digital Active - tcpwm[0].line[4]:3 */ + P12_0_TCPWM1_LINE4 = 9, /* Digital Active - tcpwm[1].line[4]:1 */ + P12_0_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:85 */ + P12_0_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:85 */ + P12_0_LCD_COM23 = 12, /* Digital Deep Sleep - lcd.com[23]:1 */ + P12_0_LCD_SEG23 = 13, /* Digital Deep Sleep - lcd.seg[23]:1 */ + P12_0_SMIF_SPI_DATA4 = 17, /* Digital Active - smif.spi_data4 */ + P12_0_SCB6_UART_RX = 18, /* Digital Active - scb[6].uart_rx:0 */ + P12_0_SCB6_I2C_SCL = 19, /* Digital Active - scb[6].i2c_scl:0 */ + P12_0_SCB6_SPI_MOSI = 20, /* Digital Active - scb[6].spi_mosi:0 */ + P12_0_PERI_TR_IO_INPUT24 = 24, /* Digital Active - peri.tr_io_input[24]:0 */ + + /* P12.1 */ + P12_1_GPIO = 0, /* GPIO controls 'out' */ + P12_1_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P12_1_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P12_1_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P12_1_AMUXA = 4, /* Analog mux bus A */ + P12_1_AMUXB = 5, /* Analog mux bus B */ + P12_1_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P12_1_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P12_1_TCPWM0_LINE_COMPL4 = 8, /* Digital Active - tcpwm[0].line_compl[4]:3 */ + P12_1_TCPWM1_LINE_COMPL4 = 9, /* Digital Active - tcpwm[1].line_compl[4]:1 */ + P12_1_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:86 */ + P12_1_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:86 */ + P12_1_LCD_COM24 = 12, /* Digital Deep Sleep - lcd.com[24]:1 */ + P12_1_LCD_SEG24 = 13, /* Digital Deep Sleep - lcd.seg[24]:1 */ + P12_1_SMIF_SPI_DATA5 = 17, /* Digital Active - smif.spi_data5 */ + P12_1_SCB6_UART_TX = 18, /* Digital Active - scb[6].uart_tx:0 */ + P12_1_SCB6_I2C_SDA = 19, /* Digital Active - scb[6].i2c_sda:0 */ + P12_1_SCB6_SPI_MISO = 20, /* Digital Active - scb[6].spi_miso:0 */ + P12_1_PERI_TR_IO_INPUT25 = 24, /* Digital Active - peri.tr_io_input[25]:0 */ + + /* P12.2 */ + P12_2_GPIO = 0, /* GPIO controls 'out' */ + P12_2_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P12_2_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P12_2_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P12_2_AMUXA = 4, /* Analog mux bus A */ + P12_2_AMUXB = 5, /* Analog mux bus B */ + P12_2_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P12_2_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P12_2_TCPWM0_LINE5 = 8, /* Digital Active - tcpwm[0].line[5]:3 */ + P12_2_TCPWM1_LINE5 = 9, /* Digital Active - tcpwm[1].line[5]:1 */ + P12_2_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:87 */ + P12_2_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:87 */ + P12_2_LCD_COM25 = 12, /* Digital Deep Sleep - lcd.com[25]:1 */ + P12_2_LCD_SEG25 = 13, /* Digital Deep Sleep - lcd.seg[25]:1 */ + P12_2_SMIF_SPI_DATA6 = 17, /* Digital Active - smif.spi_data6 */ + P12_2_SCB6_UART_RTS = 18, /* Digital Active - scb[6].uart_rts:0 */ + P12_2_SCB6_SPI_CLK = 20, /* Digital Active - scb[6].spi_clk:0 */ + + /* P12.3 */ + P12_3_GPIO = 0, /* GPIO controls 'out' */ + P12_3_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P12_3_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P12_3_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P12_3_AMUXA = 4, /* Analog mux bus A */ + P12_3_AMUXB = 5, /* Analog mux bus B */ + P12_3_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P12_3_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P12_3_TCPWM0_LINE_COMPL5 = 8, /* Digital Active - tcpwm[0].line_compl[5]:3 */ + P12_3_TCPWM1_LINE_COMPL5 = 9, /* Digital Active - tcpwm[1].line_compl[5]:1 */ + P12_3_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:88 */ + P12_3_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:88 */ + P12_3_LCD_COM26 = 12, /* Digital Deep Sleep - lcd.com[26]:1 */ + P12_3_LCD_SEG26 = 13, /* Digital Deep Sleep - lcd.seg[26]:1 */ + P12_3_SMIF_SPI_DATA7 = 17, /* Digital Active - smif.spi_data7 */ + P12_3_SCB6_UART_CTS = 18, /* Digital Active - scb[6].uart_cts:0 */ + P12_3_SCB6_SPI_SELECT0 = 20, /* Digital Active - scb[6].spi_select0:0 */ + + /* P12.4 */ + P12_4_GPIO = 0, /* GPIO controls 'out' */ + P12_4_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P12_4_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P12_4_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P12_4_AMUXA = 4, /* Analog mux bus A */ + P12_4_AMUXB = 5, /* Analog mux bus B */ + P12_4_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P12_4_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P12_4_TCPWM0_LINE6 = 8, /* Digital Active - tcpwm[0].line[6]:3 */ + P12_4_TCPWM1_LINE6 = 9, /* Digital Active - tcpwm[1].line[6]:1 */ + P12_4_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:89 */ + P12_4_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:89 */ + P12_4_LCD_COM27 = 12, /* Digital Deep Sleep - lcd.com[27]:1 */ + P12_4_LCD_SEG27 = 13, /* Digital Deep Sleep - lcd.seg[27]:1 */ + P12_4_SMIF_SPI_SELECT3 = 17, /* Digital Active - smif.spi_select3 */ + P12_4_SCB6_SPI_SELECT1 = 20, /* Digital Active - scb[6].spi_select1:0 */ + P12_4_AUDIOSS_PDM_CLK = 21, /* Digital Active - audioss.pdm_clk:1 */ + + /* P12.5 */ + P12_5_GPIO = 0, /* GPIO controls 'out' */ + P12_5_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P12_5_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P12_5_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P12_5_AMUXA = 4, /* Analog mux bus A */ + P12_5_AMUXB = 5, /* Analog mux bus B */ + P12_5_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P12_5_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P12_5_TCPWM0_LINE_COMPL6 = 8, /* Digital Active - tcpwm[0].line_compl[6]:3 */ + P12_5_TCPWM1_LINE_COMPL6 = 9, /* Digital Active - tcpwm[1].line_compl[6]:1 */ + P12_5_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:90 */ + P12_5_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:90 */ + P12_5_LCD_COM28 = 12, /* Digital Deep Sleep - lcd.com[28]:1 */ + P12_5_LCD_SEG28 = 13, /* Digital Deep Sleep - lcd.seg[28]:1 */ + P12_5_SCB6_SPI_SELECT2 = 20, /* Digital Active - scb[6].spi_select2:0 */ + P12_5_AUDIOSS_PDM_DATA = 21, /* Digital Active - audioss.pdm_data:1 */ + + /* P12.6 */ + P12_6_GPIO = 0, /* GPIO controls 'out' */ + P12_6_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P12_6_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P12_6_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P12_6_AMUXA = 4, /* Analog mux bus A */ + P12_6_AMUXB = 5, /* Analog mux bus B */ + P12_6_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P12_6_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P12_6_TCPWM0_LINE7 = 8, /* Digital Active - tcpwm[0].line[7]:3 */ + P12_6_TCPWM1_LINE7 = 9, /* Digital Active - tcpwm[1].line[7]:1 */ + P12_6_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:91 */ + P12_6_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:91 */ + P12_6_LCD_COM29 = 12, /* Digital Deep Sleep - lcd.com[29]:1 */ + P12_6_LCD_SEG29 = 13, /* Digital Deep Sleep - lcd.seg[29]:1 */ + P12_6_SCB6_SPI_SELECT3 = 20, /* Digital Active - scb[6].spi_select3:0 */ + + /* P12.7 */ + P12_7_GPIO = 0, /* GPIO controls 'out' */ + P12_7_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P12_7_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P12_7_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P12_7_AMUXA = 4, /* Analog mux bus A */ + P12_7_AMUXB = 5, /* Analog mux bus B */ + P12_7_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P12_7_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P12_7_TCPWM0_LINE_COMPL7 = 8, /* Digital Active - tcpwm[0].line_compl[7]:3 */ + P12_7_TCPWM1_LINE_COMPL7 = 9, /* Digital Active - tcpwm[1].line_compl[7]:1 */ + P12_7_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:92 */ + P12_7_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:92 */ + P12_7_LCD_COM30 = 12, /* Digital Deep Sleep - lcd.com[30]:1 */ + P12_7_LCD_SEG30 = 13, /* Digital Deep Sleep - lcd.seg[30]:1 */ + + /* P13.0 */ + P13_0_GPIO = 0, /* GPIO controls 'out' */ + P13_0_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P13_0_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P13_0_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P13_0_AMUXA = 4, /* Analog mux bus A */ + P13_0_AMUXB = 5, /* Analog mux bus B */ + P13_0_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P13_0_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P13_0_TCPWM0_LINE0 = 8, /* Digital Active - tcpwm[0].line[0]:4 */ + P13_0_TCPWM1_LINE8 = 9, /* Digital Active - tcpwm[1].line[8]:1 */ + P13_0_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:93 */ + P13_0_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:93 */ + P13_0_LCD_COM31 = 12, /* Digital Deep Sleep - lcd.com[31]:1 */ + P13_0_LCD_SEG31 = 13, /* Digital Deep Sleep - lcd.seg[31]:1 */ + P13_0_SCB6_UART_RX = 18, /* Digital Active - scb[6].uart_rx:1 */ + P13_0_SCB6_I2C_SCL = 19, /* Digital Active - scb[6].i2c_scl:1 */ + P13_0_SCB6_SPI_MOSI = 20, /* Digital Active - scb[6].spi_mosi:1 */ + P13_0_PERI_TR_IO_INPUT26 = 24, /* Digital Active - peri.tr_io_input[26]:0 */ + + /* P13.1 */ + P13_1_GPIO = 0, /* GPIO controls 'out' */ + P13_1_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P13_1_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P13_1_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P13_1_AMUXA = 4, /* Analog mux bus A */ + P13_1_AMUXB = 5, /* Analog mux bus B */ + P13_1_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P13_1_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P13_1_TCPWM0_LINE_COMPL0 = 8, /* Digital Active - tcpwm[0].line_compl[0]:4 */ + P13_1_TCPWM1_LINE_COMPL8 = 9, /* Digital Active - tcpwm[1].line_compl[8]:1 */ + P13_1_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:94 */ + P13_1_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:94 */ + P13_1_LCD_COM32 = 12, /* Digital Deep Sleep - lcd.com[32]:1 */ + P13_1_LCD_SEG32 = 13, /* Digital Deep Sleep - lcd.seg[32]:1 */ + P13_1_SCB6_UART_TX = 18, /* Digital Active - scb[6].uart_tx:1 */ + P13_1_SCB6_I2C_SDA = 19, /* Digital Active - scb[6].i2c_sda:1 */ + P13_1_SCB6_SPI_MISO = 20, /* Digital Active - scb[6].spi_miso:1 */ + P13_1_PERI_TR_IO_INPUT27 = 24, /* Digital Active - peri.tr_io_input[27]:0 */ + + /* P13.6 */ + P13_6_GPIO = 0, /* GPIO controls 'out' */ + P13_6_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P13_6_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P13_6_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P13_6_AMUXA = 4, /* Analog mux bus A */ + P13_6_AMUXB = 5, /* Analog mux bus B */ + P13_6_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P13_6_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P13_6_TCPWM0_LINE3 = 8, /* Digital Active - tcpwm[0].line[3]:4 */ + P13_6_TCPWM1_LINE11 = 9, /* Digital Active - tcpwm[1].line[11]:1 */ + P13_6_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:99 */ + P13_6_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:99 */ + P13_6_LCD_COM37 = 12, /* Digital Deep Sleep - lcd.com[37]:1 */ + P13_6_LCD_SEG37 = 13, /* Digital Deep Sleep - lcd.seg[37]:1 */ + P13_6_SCB6_SPI_SELECT3 = 20, /* Digital Active - scb[6].spi_select3:1 */ + + /* P13.7 */ + P13_7_GPIO = 0, /* GPIO controls 'out' */ + P13_7_GPIO_DSI = 1, /* GPIO controls 'out', DSI controls 'output enable' */ + P13_7_DSI_DSI = 2, /* DSI controls 'out' and 'output enable' */ + P13_7_DSI_GPIO = 3, /* DSI controls 'out', GPIO controls 'output enable' */ + P13_7_AMUXA = 4, /* Analog mux bus A */ + P13_7_AMUXB = 5, /* Analog mux bus B */ + P13_7_AMUXA_DSI = 6, /* Analog mux bus A, DSI control */ + P13_7_AMUXB_DSI = 7, /* Analog mux bus B, DSI control */ + P13_7_TCPWM0_LINE_COMPL3 = 8, /* Digital Active - tcpwm[0].line_compl[3]:4 */ + P13_7_TCPWM1_LINE_COMPL11 = 9, /* Digital Active - tcpwm[1].line_compl[11]:1 */ + P13_7_CSD_CSD_TX = 10, /* Digital Active - csd.csd_tx:100 */ + P13_7_CSD_CSD_TX_N = 11, /* Digital Active - csd.csd_tx_n:100 */ + P13_7_LCD_COM38 = 12, /* Digital Deep Sleep - lcd.com[38]:1 */ + P13_7_LCD_SEG38 = 13 /* Digital Deep Sleep - lcd.seg[38]:1 */ +} en_hsiom_sel_t; + +#endif /* _GPIO_PSOC63_116_BGA_BLE_H_ */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/psoc63_config.h b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/psoc63_config.h new file mode 100644 index 0000000000..f166c7e62d --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/psoc63_config.h @@ -0,0 +1,3000 @@ +/***************************************************************************//** +* \file psoc63_config.h +* +* \brief +* PSoC 63 device configuration header +* +* \note +* Generator version: 1.2.0.117 +* Database revision: rev#1034984 +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#ifndef _PSOC63_CONFIG_H_ +#define _PSOC63_CONFIG_H_ + +/* Clock Connections */ +typedef enum +{ + PCLK_SCB0_CLOCK = 0, /* scb[0].clock */ + PCLK_SCB1_CLOCK = 1, /* scb[1].clock */ + PCLK_SCB2_CLOCK = 2, /* scb[2].clock */ + PCLK_SCB3_CLOCK = 3, /* scb[3].clock */ + PCLK_SCB4_CLOCK = 4, /* scb[4].clock */ + PCLK_SCB5_CLOCK = 5, /* scb[5].clock */ + PCLK_SCB6_CLOCK = 6, /* scb[6].clock */ + PCLK_SCB7_CLOCK = 7, /* scb[7].clock */ + PCLK_SCB8_CLOCK = 8, /* scb[8].clock */ + PCLK_UDB_CLOCKS0 = 9, /* udb.clocks[0] */ + PCLK_UDB_CLOCKS1 = 10, /* udb.clocks[1] */ + PCLK_UDB_CLOCKS2 = 11, /* udb.clocks[2] */ + PCLK_UDB_CLOCKS3 = 12, /* udb.clocks[3] */ + PCLK_UDB_CLOCKS4 = 13, /* udb.clocks[4] */ + PCLK_UDB_CLOCKS5 = 14, /* udb.clocks[5] */ + PCLK_UDB_CLOCKS6 = 15, /* udb.clocks[6] */ + PCLK_UDB_CLOCKS7 = 16, /* udb.clocks[7] */ + PCLK_SMARTIO8_CLOCK = 17, /* smartio[8].clock */ + PCLK_SMARTIO9_CLOCK = 18, /* smartio[9].clock */ + PCLK_TCPWM0_CLOCKS0 = 19, /* tcpwm[0].clocks[0] */ + PCLK_TCPWM0_CLOCKS1 = 20, /* tcpwm[0].clocks[1] */ + PCLK_TCPWM0_CLOCKS2 = 21, /* tcpwm[0].clocks[2] */ + PCLK_TCPWM0_CLOCKS3 = 22, /* tcpwm[0].clocks[3] */ + PCLK_TCPWM0_CLOCKS4 = 23, /* tcpwm[0].clocks[4] */ + PCLK_TCPWM0_CLOCKS5 = 24, /* tcpwm[0].clocks[5] */ + PCLK_TCPWM0_CLOCKS6 = 25, /* tcpwm[0].clocks[6] */ + PCLK_TCPWM0_CLOCKS7 = 26, /* tcpwm[0].clocks[7] */ + PCLK_TCPWM1_CLOCKS0 = 27, /* tcpwm[1].clocks[0] */ + PCLK_TCPWM1_CLOCKS1 = 28, /* tcpwm[1].clocks[1] */ + PCLK_TCPWM1_CLOCKS2 = 29, /* tcpwm[1].clocks[2] */ + PCLK_TCPWM1_CLOCKS3 = 30, /* tcpwm[1].clocks[3] */ + PCLK_TCPWM1_CLOCKS4 = 31, /* tcpwm[1].clocks[4] */ + PCLK_TCPWM1_CLOCKS5 = 32, /* tcpwm[1].clocks[5] */ + PCLK_TCPWM1_CLOCKS6 = 33, /* tcpwm[1].clocks[6] */ + PCLK_TCPWM1_CLOCKS7 = 34, /* tcpwm[1].clocks[7] */ + PCLK_TCPWM1_CLOCKS8 = 35, /* tcpwm[1].clocks[8] */ + PCLK_TCPWM1_CLOCKS9 = 36, /* tcpwm[1].clocks[9] */ + PCLK_TCPWM1_CLOCKS10 = 37, /* tcpwm[1].clocks[10] */ + PCLK_TCPWM1_CLOCKS11 = 38, /* tcpwm[1].clocks[11] */ + PCLK_TCPWM1_CLOCKS12 = 39, /* tcpwm[1].clocks[12] */ + PCLK_TCPWM1_CLOCKS13 = 40, /* tcpwm[1].clocks[13] */ + PCLK_TCPWM1_CLOCKS14 = 41, /* tcpwm[1].clocks[14] */ + PCLK_TCPWM1_CLOCKS15 = 42, /* tcpwm[1].clocks[15] */ + PCLK_TCPWM1_CLOCKS16 = 43, /* tcpwm[1].clocks[16] */ + PCLK_TCPWM1_CLOCKS17 = 44, /* tcpwm[1].clocks[17] */ + PCLK_TCPWM1_CLOCKS18 = 45, /* tcpwm[1].clocks[18] */ + PCLK_TCPWM1_CLOCKS19 = 46, /* tcpwm[1].clocks[19] */ + PCLK_TCPWM1_CLOCKS20 = 47, /* tcpwm[1].clocks[20] */ + PCLK_TCPWM1_CLOCKS21 = 48, /* tcpwm[1].clocks[21] */ + PCLK_TCPWM1_CLOCKS22 = 49, /* tcpwm[1].clocks[22] */ + PCLK_TCPWM1_CLOCKS23 = 50, /* tcpwm[1].clocks[23] */ + PCLK_CSD_CLOCK = 51, /* csd.clock */ + PCLK_LCD_CLOCK = 52, /* lcd.clock */ + PCLK_PROFILE_CLOCK_PROFILE = 53, /* profile.clock_profile */ + PCLK_CPUSS_CLOCK_TRACE_IN = 54, /* cpuss.clock_trace_in */ + PCLK_PASS_CLOCK_CTDAC = 55, /* pass.clock_ctdac */ + PCLK_PASS_CLOCK_PUMP_PERI = 56, /* pass.clock_pump_peri */ + PCLK_PASS_CLOCK_SAR = 57, /* pass.clock_sar */ + PCLK_USB_CLOCK_DEV_BRS = 58 /* usb.clock_dev_brs */ +} en_clk_dst_t; + +/* Trigger Group */ +/* This section contains the enums related to the Trigger multiplexer (TrigMux) driver. +* The constants are divided into four types because each signal of the TrigMux driver has a path +* through two multiplexers: the reduction multiplexer and the distribution multiplexer. This +* requires two calls for Cy_TrigMux_Connect() function. The first call - for the reduction +* multiplexer, the second call - for the distribution multiplexer. +* +* The four types of inputs/output parameters: +* 1) Parameters for reduction multiplexer's inputs (input signals of TrigMux) +* 2) Parameters for reduction multiplexer's outputs (intermediate signals); +* 3) Parameters for distribution multiplexer's inputs (intermediate signals); +* 4) Parameters for distribution multiplexer's outputs (output signals of TrigMux). +* +* The Cy_TrigMux_Connect() inTrig parameter can have 1) and 3) types parameters. The outTrig +* parameter can have 2) and 4) types parameters. +* The names of the constants for these parameters have the following format: +* +* 1) For reduction multiplexer's inputs: +* TRIG_IN_ +* the reduction multiplexer number; +* - the name of the IP block which is the source of the signal; +* - the source signal number in the IP block. +* +* Example: +* TRIG11_IN_TCPWM0_TR_OVERFLOW3 - the TCPWM0 tr_overflow[3] input of reduction multiplexer#11. +* +* 2) For reduction multiplexer's outputs: +* TRIG_OUT_TR_GROUP_INPUT +* - the reduction multiplexer number; +* - the distribution multiplexer number; +* - the input number of the distribution multiplexer. +* +* Example: +* TRIG11_OUT_TR_GROUP0_INPUT23 - Input#23 of the distribution multiplexer#0 is the destination +* of the reduction multiplexer#11. +* +* 3) For distribution multiplexer's inputs: +* TRIG_IN_TR_GROUP_OUTPUT +* - the reduction multiplexer number; +* - the distribution multiplexer number; +* - the output number of the reduction multiplexer; +* +* Example: +* TRIG0_IN_TR_GROUP11_OUTPUT15 - Output#15 of the reduction multiplexer#11 is the source of the +* distribution multiplexer#0. +* +* 4) For distribution multiplexer's outputs: +* TRIG_OUT_ +* - the distribution multiplexer number; +* - the name of the IP block which is the destination of the signal; +* - the input signal number in the IP block. +* +* Example: +* TRIG0_OUT_CPUSS_DW0_TR_IN3 - the DW0 tr_out[3] ouput of the distribution multiplexer 0.*/ +/* Trigger Group Inputs */ +/* Trigger Input Group 0 - DMA Request Assignments */ +typedef enum +{ + TRIG0_IN_CPUSS_ZERO = 0x00000000u, /* cpuss.zero */ + TRIG0_IN_TR_GROUP10_OUTPUT0 = 0x00000001u, /* tr_group[10].output[0] */ + TRIG0_IN_TR_GROUP10_OUTPUT1 = 0x00000002u, /* tr_group[10].output[1] */ + TRIG0_IN_TR_GROUP10_OUTPUT2 = 0x00000003u, /* tr_group[10].output[2] */ + TRIG0_IN_TR_GROUP10_OUTPUT3 = 0x00000004u, /* tr_group[10].output[3] */ + TRIG0_IN_TR_GROUP10_OUTPUT4 = 0x00000005u, /* tr_group[10].output[4] */ + TRIG0_IN_TR_GROUP10_OUTPUT5 = 0x00000006u, /* tr_group[10].output[5] */ + TRIG0_IN_TR_GROUP10_OUTPUT6 = 0x00000007u, /* tr_group[10].output[6] */ + TRIG0_IN_TR_GROUP10_OUTPUT7 = 0x00000008u, /* tr_group[10].output[7] */ + TRIG0_IN_TR_GROUP11_OUTPUT0 = 0x00000009u, /* tr_group[11].output[0] */ + TRIG0_IN_TR_GROUP11_OUTPUT1 = 0x0000000Au, /* tr_group[11].output[1] */ + TRIG0_IN_TR_GROUP11_OUTPUT2 = 0x0000000Bu, /* tr_group[11].output[2] */ + TRIG0_IN_TR_GROUP11_OUTPUT3 = 0x0000000Cu, /* tr_group[11].output[3] */ + TRIG0_IN_TR_GROUP11_OUTPUT4 = 0x0000000Du, /* tr_group[11].output[4] */ + TRIG0_IN_TR_GROUP11_OUTPUT5 = 0x0000000Eu, /* tr_group[11].output[5] */ + TRIG0_IN_TR_GROUP11_OUTPUT6 = 0x0000000Fu, /* tr_group[11].output[6] */ + TRIG0_IN_TR_GROUP11_OUTPUT7 = 0x00000010u, /* tr_group[11].output[7] */ + TRIG0_IN_TR_GROUP11_OUTPUT8 = 0x00000011u, /* tr_group[11].output[8] */ + TRIG0_IN_TR_GROUP11_OUTPUT9 = 0x00000012u, /* tr_group[11].output[9] */ + TRIG0_IN_TR_GROUP11_OUTPUT10 = 0x00000013u, /* tr_group[11].output[10] */ + TRIG0_IN_TR_GROUP11_OUTPUT11 = 0x00000014u, /* tr_group[11].output[11] */ + TRIG0_IN_TR_GROUP11_OUTPUT12 = 0x00000015u, /* tr_group[11].output[12] */ + TRIG0_IN_TR_GROUP11_OUTPUT13 = 0x00000016u, /* tr_group[11].output[13] */ + TRIG0_IN_TR_GROUP11_OUTPUT14 = 0x00000017u, /* tr_group[11].output[14] */ + TRIG0_IN_TR_GROUP11_OUTPUT15 = 0x00000018u, /* tr_group[11].output[15] */ + TRIG0_IN_TR_GROUP12_OUTPUT8 = 0x00000019u, /* tr_group[12].output[8] */ + TRIG0_IN_TR_GROUP12_OUTPUT9 = 0x0000001Au, /* tr_group[12].output[9] */ + TRIG0_IN_TR_GROUP13_OUTPUT0 = 0x0000001Bu, /* tr_group[13].output[0] */ + TRIG0_IN_TR_GROUP13_OUTPUT1 = 0x0000001Cu, /* tr_group[13].output[1] */ + TRIG0_IN_TR_GROUP13_OUTPUT2 = 0x0000001Du, /* tr_group[13].output[2] */ + TRIG0_IN_TR_GROUP13_OUTPUT3 = 0x0000001Eu, /* tr_group[13].output[3] */ + TRIG0_IN_TR_GROUP13_OUTPUT4 = 0x0000001Fu, /* tr_group[13].output[4] */ + TRIG0_IN_TR_GROUP13_OUTPUT5 = 0x00000020u, /* tr_group[13].output[5] */ + TRIG0_IN_TR_GROUP13_OUTPUT6 = 0x00000021u, /* tr_group[13].output[6] */ + TRIG0_IN_TR_GROUP13_OUTPUT7 = 0x00000022u, /* tr_group[13].output[7] */ + TRIG0_IN_TR_GROUP13_OUTPUT8 = 0x00000023u, /* tr_group[13].output[8] */ + TRIG0_IN_TR_GROUP13_OUTPUT9 = 0x00000024u, /* tr_group[13].output[9] */ + TRIG0_IN_TR_GROUP13_OUTPUT10 = 0x00000025u, /* tr_group[13].output[10] */ + TRIG0_IN_TR_GROUP13_OUTPUT11 = 0x00000026u, /* tr_group[13].output[11] */ + TRIG0_IN_TR_GROUP13_OUTPUT12 = 0x00000027u, /* tr_group[13].output[12] */ + TRIG0_IN_TR_GROUP13_OUTPUT13 = 0x00000028u, /* tr_group[13].output[13] */ + TRIG0_IN_TR_GROUP13_OUTPUT14 = 0x00000029u, /* tr_group[13].output[14] */ + TRIG0_IN_TR_GROUP13_OUTPUT15 = 0x0000002Au, /* tr_group[13].output[15] */ + TRIG0_IN_TR_GROUP14_OUTPUT0 = 0x0000002Bu, /* tr_group[14].output[0] */ + TRIG0_IN_TR_GROUP14_OUTPUT1 = 0x0000002Cu, /* tr_group[14].output[1] */ + TRIG0_IN_TR_GROUP14_OUTPUT2 = 0x0000002Du, /* tr_group[14].output[2] */ + TRIG0_IN_TR_GROUP14_OUTPUT3 = 0x0000002Eu, /* tr_group[14].output[3] */ + TRIG0_IN_TR_GROUP14_OUTPUT4 = 0x0000002Fu, /* tr_group[14].output[4] */ + TRIG0_IN_TR_GROUP14_OUTPUT5 = 0x00000030u, /* tr_group[14].output[5] */ + TRIG0_IN_TR_GROUP14_OUTPUT6 = 0x00000031u, /* tr_group[14].output[6] */ + TRIG0_IN_TR_GROUP14_OUTPUT7 = 0x00000032u /* tr_group[14].output[7] */ +} en_trig_input_grp0_t; + +/* Trigger Input Group 1 - DMA Request Assignments */ +typedef enum +{ + TRIG1_IN_CPUSS_ZERO = 0x00000100u, /* cpuss.zero */ + TRIG1_IN_TR_GROUP10_OUTPUT0 = 0x00000101u, /* tr_group[10].output[0] */ + TRIG1_IN_TR_GROUP10_OUTPUT1 = 0x00000102u, /* tr_group[10].output[1] */ + TRIG1_IN_TR_GROUP10_OUTPUT2 = 0x00000103u, /* tr_group[10].output[2] */ + TRIG1_IN_TR_GROUP10_OUTPUT3 = 0x00000104u, /* tr_group[10].output[3] */ + TRIG1_IN_TR_GROUP10_OUTPUT4 = 0x00000105u, /* tr_group[10].output[4] */ + TRIG1_IN_TR_GROUP10_OUTPUT5 = 0x00000106u, /* tr_group[10].output[5] */ + TRIG1_IN_TR_GROUP10_OUTPUT6 = 0x00000107u, /* tr_group[10].output[6] */ + TRIG1_IN_TR_GROUP10_OUTPUT7 = 0x00000108u, /* tr_group[10].output[7] */ + TRIG1_IN_TR_GROUP11_OUTPUT0 = 0x00000109u, /* tr_group[11].output[0] */ + TRIG1_IN_TR_GROUP11_OUTPUT1 = 0x0000010Au, /* tr_group[11].output[1] */ + TRIG1_IN_TR_GROUP11_OUTPUT2 = 0x0000010Bu, /* tr_group[11].output[2] */ + TRIG1_IN_TR_GROUP11_OUTPUT3 = 0x0000010Cu, /* tr_group[11].output[3] */ + TRIG1_IN_TR_GROUP11_OUTPUT4 = 0x0000010Du, /* tr_group[11].output[4] */ + TRIG1_IN_TR_GROUP11_OUTPUT5 = 0x0000010Eu, /* tr_group[11].output[5] */ + TRIG1_IN_TR_GROUP11_OUTPUT6 = 0x0000010Fu, /* tr_group[11].output[6] */ + TRIG1_IN_TR_GROUP11_OUTPUT7 = 0x00000110u, /* tr_group[11].output[7] */ + TRIG1_IN_TR_GROUP11_OUTPUT8 = 0x00000111u, /* tr_group[11].output[8] */ + TRIG1_IN_TR_GROUP11_OUTPUT9 = 0x00000112u, /* tr_group[11].output[9] */ + TRIG1_IN_TR_GROUP11_OUTPUT10 = 0x00000113u, /* tr_group[11].output[10] */ + TRIG1_IN_TR_GROUP11_OUTPUT11 = 0x00000114u, /* tr_group[11].output[11] */ + TRIG1_IN_TR_GROUP11_OUTPUT12 = 0x00000115u, /* tr_group[11].output[12] */ + TRIG1_IN_TR_GROUP11_OUTPUT13 = 0x00000116u, /* tr_group[11].output[13] */ + TRIG1_IN_TR_GROUP11_OUTPUT14 = 0x00000117u, /* tr_group[11].output[14] */ + TRIG1_IN_TR_GROUP11_OUTPUT15 = 0x00000118u, /* tr_group[11].output[15] */ + TRIG1_IN_TR_GROUP12_OUTPUT8 = 0x00000119u, /* tr_group[12].output[8] */ + TRIG1_IN_TR_GROUP12_OUTPUT9 = 0x0000011Au, /* tr_group[12].output[9] */ + TRIG1_IN_TR_GROUP13_OUTPUT0 = 0x0000011Bu, /* tr_group[13].output[0] */ + TRIG1_IN_TR_GROUP13_OUTPUT1 = 0x0000011Cu, /* tr_group[13].output[1] */ + TRIG1_IN_TR_GROUP13_OUTPUT2 = 0x0000011Du, /* tr_group[13].output[2] */ + TRIG1_IN_TR_GROUP13_OUTPUT3 = 0x0000011Eu, /* tr_group[13].output[3] */ + TRIG1_IN_TR_GROUP13_OUTPUT4 = 0x0000011Fu, /* tr_group[13].output[4] */ + TRIG1_IN_TR_GROUP13_OUTPUT5 = 0x00000120u, /* tr_group[13].output[5] */ + TRIG1_IN_TR_GROUP13_OUTPUT6 = 0x00000121u, /* tr_group[13].output[6] */ + TRIG1_IN_TR_GROUP13_OUTPUT7 = 0x00000122u, /* tr_group[13].output[7] */ + TRIG1_IN_TR_GROUP13_OUTPUT8 = 0x00000123u, /* tr_group[13].output[8] */ + TRIG1_IN_TR_GROUP13_OUTPUT9 = 0x00000124u, /* tr_group[13].output[9] */ + TRIG1_IN_TR_GROUP13_OUTPUT10 = 0x00000125u, /* tr_group[13].output[10] */ + TRIG1_IN_TR_GROUP13_OUTPUT11 = 0x00000126u, /* tr_group[13].output[11] */ + TRIG1_IN_TR_GROUP13_OUTPUT12 = 0x00000127u, /* tr_group[13].output[12] */ + TRIG1_IN_TR_GROUP13_OUTPUT13 = 0x00000128u, /* tr_group[13].output[13] */ + TRIG1_IN_TR_GROUP13_OUTPUT14 = 0x00000129u, /* tr_group[13].output[14] */ + TRIG1_IN_TR_GROUP13_OUTPUT15 = 0x0000012Au, /* tr_group[13].output[15] */ + TRIG1_IN_TR_GROUP14_OUTPUT0 = 0x0000012Bu, /* tr_group[14].output[0] */ + TRIG1_IN_TR_GROUP14_OUTPUT1 = 0x0000012Cu, /* tr_group[14].output[1] */ + TRIG1_IN_TR_GROUP14_OUTPUT2 = 0x0000012Du, /* tr_group[14].output[2] */ + TRIG1_IN_TR_GROUP14_OUTPUT3 = 0x0000012Eu, /* tr_group[14].output[3] */ + TRIG1_IN_TR_GROUP14_OUTPUT4 = 0x0000012Fu, /* tr_group[14].output[4] */ + TRIG1_IN_TR_GROUP14_OUTPUT5 = 0x00000130u, /* tr_group[14].output[5] */ + TRIG1_IN_TR_GROUP14_OUTPUT6 = 0x00000131u, /* tr_group[14].output[6] */ + TRIG1_IN_TR_GROUP14_OUTPUT7 = 0x00000132u /* tr_group[14].output[7] */ +} en_trig_input_grp1_t; + +/* Trigger Input Group 2 - TCPWM trigger inputs */ +typedef enum +{ + TRIG2_IN_CPUSS_ZERO = 0x00000200u, /* cpuss.zero */ + TRIG2_IN_TR_GROUP10_OUTPUT0 = 0x00000201u, /* tr_group[10].output[0] */ + TRIG2_IN_TR_GROUP10_OUTPUT1 = 0x00000202u, /* tr_group[10].output[1] */ + TRIG2_IN_TR_GROUP10_OUTPUT2 = 0x00000203u, /* tr_group[10].output[2] */ + TRIG2_IN_TR_GROUP10_OUTPUT3 = 0x00000204u, /* tr_group[10].output[3] */ + TRIG2_IN_TR_GROUP10_OUTPUT4 = 0x00000205u, /* tr_group[10].output[4] */ + TRIG2_IN_TR_GROUP10_OUTPUT5 = 0x00000206u, /* tr_group[10].output[5] */ + TRIG2_IN_TR_GROUP10_OUTPUT6 = 0x00000207u, /* tr_group[10].output[6] */ + TRIG2_IN_TR_GROUP10_OUTPUT7 = 0x00000208u, /* tr_group[10].output[7] */ + TRIG2_IN_TR_GROUP11_OUTPUT0 = 0x00000209u, /* tr_group[11].output[0] */ + TRIG2_IN_TR_GROUP11_OUTPUT1 = 0x0000020Au, /* tr_group[11].output[1] */ + TRIG2_IN_TR_GROUP11_OUTPUT2 = 0x0000020Bu, /* tr_group[11].output[2] */ + TRIG2_IN_TR_GROUP11_OUTPUT3 = 0x0000020Cu, /* tr_group[11].output[3] */ + TRIG2_IN_TR_GROUP11_OUTPUT4 = 0x0000020Du, /* tr_group[11].output[4] */ + TRIG2_IN_TR_GROUP11_OUTPUT5 = 0x0000020Eu, /* tr_group[11].output[5] */ + TRIG2_IN_TR_GROUP11_OUTPUT6 = 0x0000020Fu, /* tr_group[11].output[6] */ + TRIG2_IN_TR_GROUP11_OUTPUT7 = 0x00000210u, /* tr_group[11].output[7] */ + TRIG2_IN_TR_GROUP11_OUTPUT8 = 0x00000211u, /* tr_group[11].output[8] */ + TRIG2_IN_TR_GROUP11_OUTPUT9 = 0x00000212u, /* tr_group[11].output[9] */ + TRIG2_IN_TR_GROUP11_OUTPUT10 = 0x00000213u, /* tr_group[11].output[10] */ + TRIG2_IN_TR_GROUP11_OUTPUT11 = 0x00000214u, /* tr_group[11].output[11] */ + TRIG2_IN_TR_GROUP11_OUTPUT12 = 0x00000215u, /* tr_group[11].output[12] */ + TRIG2_IN_TR_GROUP11_OUTPUT13 = 0x00000216u, /* tr_group[11].output[13] */ + TRIG2_IN_TR_GROUP11_OUTPUT14 = 0x00000217u, /* tr_group[11].output[14] */ + TRIG2_IN_TR_GROUP11_OUTPUT15 = 0x00000218u, /* tr_group[11].output[15] */ + TRIG2_IN_TR_GROUP12_OUTPUT0 = 0x00000219u, /* tr_group[12].output[0] */ + TRIG2_IN_TR_GROUP12_OUTPUT1 = 0x0000021Au, /* tr_group[12].output[1] */ + TRIG2_IN_TR_GROUP12_OUTPUT2 = 0x0000021Bu, /* tr_group[12].output[2] */ + TRIG2_IN_TR_GROUP12_OUTPUT3 = 0x0000021Cu, /* tr_group[12].output[3] */ + TRIG2_IN_TR_GROUP12_OUTPUT4 = 0x0000021Du, /* tr_group[12].output[4] */ + TRIG2_IN_TR_GROUP12_OUTPUT5 = 0x0000021Eu, /* tr_group[12].output[5] */ + TRIG2_IN_TR_GROUP12_OUTPUT6 = 0x0000021Fu, /* tr_group[12].output[6] */ + TRIG2_IN_TR_GROUP12_OUTPUT7 = 0x00000220u, /* tr_group[12].output[7] */ + TRIG2_IN_TR_GROUP13_OUTPUT16 = 0x00000221u, /* tr_group[13].output[16] */ + TRIG2_IN_TR_GROUP13_OUTPUT17 = 0x00000222u, /* tr_group[13].output[17] */ + TRIG2_IN_TR_GROUP14_OUTPUT8 = 0x00000223u, /* tr_group[14].output[8] */ + TRIG2_IN_TR_GROUP14_OUTPUT9 = 0x00000224u, /* tr_group[14].output[9] */ + TRIG2_IN_TR_GROUP14_OUTPUT10 = 0x00000225u, /* tr_group[14].output[10] */ + TRIG2_IN_TR_GROUP14_OUTPUT11 = 0x00000226u, /* tr_group[14].output[11] */ + TRIG2_IN_TR_GROUP14_OUTPUT12 = 0x00000227u, /* tr_group[14].output[12] */ + TRIG2_IN_TR_GROUP14_OUTPUT13 = 0x00000228u, /* tr_group[14].output[13] */ + TRIG2_IN_TR_GROUP14_OUTPUT14 = 0x00000229u, /* tr_group[14].output[14] */ + TRIG2_IN_TR_GROUP14_OUTPUT15 = 0x0000022Au /* tr_group[14].output[15] */ +} en_trig_input_grp2_t; + +/* Trigger Input Group 3 - TCPWM trigger inputs */ +typedef enum +{ + TRIG3_IN_CPUSS_ZERO = 0x00000300u, /* cpuss.zero */ + TRIG3_IN_TR_GROUP10_OUTPUT0 = 0x00000301u, /* tr_group[10].output[0] */ + TRIG3_IN_TR_GROUP10_OUTPUT1 = 0x00000302u, /* tr_group[10].output[1] */ + TRIG3_IN_TR_GROUP10_OUTPUT2 = 0x00000303u, /* tr_group[10].output[2] */ + TRIG3_IN_TR_GROUP10_OUTPUT3 = 0x00000304u, /* tr_group[10].output[3] */ + TRIG3_IN_TR_GROUP10_OUTPUT4 = 0x00000305u, /* tr_group[10].output[4] */ + TRIG3_IN_TR_GROUP10_OUTPUT5 = 0x00000306u, /* tr_group[10].output[5] */ + TRIG3_IN_TR_GROUP10_OUTPUT6 = 0x00000307u, /* tr_group[10].output[6] */ + TRIG3_IN_TR_GROUP10_OUTPUT7 = 0x00000308u, /* tr_group[10].output[7] */ + TRIG3_IN_TR_GROUP11_OUTPUT0 = 0x00000309u, /* tr_group[11].output[0] */ + TRIG3_IN_TR_GROUP11_OUTPUT1 = 0x0000030Au, /* tr_group[11].output[1] */ + TRIG3_IN_TR_GROUP11_OUTPUT2 = 0x0000030Bu, /* tr_group[11].output[2] */ + TRIG3_IN_TR_GROUP11_OUTPUT3 = 0x0000030Cu, /* tr_group[11].output[3] */ + TRIG3_IN_TR_GROUP11_OUTPUT4 = 0x0000030Du, /* tr_group[11].output[4] */ + TRIG3_IN_TR_GROUP11_OUTPUT5 = 0x0000030Eu, /* tr_group[11].output[5] */ + TRIG3_IN_TR_GROUP11_OUTPUT6 = 0x0000030Fu, /* tr_group[11].output[6] */ + TRIG3_IN_TR_GROUP11_OUTPUT7 = 0x00000310u, /* tr_group[11].output[7] */ + TRIG3_IN_TR_GROUP11_OUTPUT8 = 0x00000311u, /* tr_group[11].output[8] */ + TRIG3_IN_TR_GROUP11_OUTPUT9 = 0x00000312u, /* tr_group[11].output[9] */ + TRIG3_IN_TR_GROUP11_OUTPUT10 = 0x00000313u, /* tr_group[11].output[10] */ + TRIG3_IN_TR_GROUP11_OUTPUT11 = 0x00000314u, /* tr_group[11].output[11] */ + TRIG3_IN_TR_GROUP11_OUTPUT12 = 0x00000315u, /* tr_group[11].output[12] */ + TRIG3_IN_TR_GROUP11_OUTPUT13 = 0x00000316u, /* tr_group[11].output[13] */ + TRIG3_IN_TR_GROUP11_OUTPUT14 = 0x00000317u, /* tr_group[11].output[14] */ + TRIG3_IN_TR_GROUP11_OUTPUT15 = 0x00000318u, /* tr_group[11].output[15] */ + TRIG3_IN_TR_GROUP12_OUTPUT0 = 0x00000319u, /* tr_group[12].output[0] */ + TRIG3_IN_TR_GROUP12_OUTPUT1 = 0x0000031Au, /* tr_group[12].output[1] */ + TRIG3_IN_TR_GROUP12_OUTPUT2 = 0x0000031Bu, /* tr_group[12].output[2] */ + TRIG3_IN_TR_GROUP12_OUTPUT3 = 0x0000031Cu, /* tr_group[12].output[3] */ + TRIG3_IN_TR_GROUP12_OUTPUT4 = 0x0000031Du, /* tr_group[12].output[4] */ + TRIG3_IN_TR_GROUP12_OUTPUT5 = 0x0000031Eu, /* tr_group[12].output[5] */ + TRIG3_IN_TR_GROUP12_OUTPUT6 = 0x0000031Fu, /* tr_group[12].output[6] */ + TRIG3_IN_TR_GROUP12_OUTPUT7 = 0x00000320u, /* tr_group[12].output[7] */ + TRIG3_IN_TR_GROUP13_OUTPUT16 = 0x00000321u, /* tr_group[13].output[16] */ + TRIG3_IN_TR_GROUP13_OUTPUT17 = 0x00000322u, /* tr_group[13].output[17] */ + TRIG3_IN_TR_GROUP14_OUTPUT8 = 0x00000323u, /* tr_group[14].output[8] */ + TRIG3_IN_TR_GROUP14_OUTPUT9 = 0x00000324u, /* tr_group[14].output[9] */ + TRIG3_IN_TR_GROUP14_OUTPUT10 = 0x00000325u, /* tr_group[14].output[10] */ + TRIG3_IN_TR_GROUP14_OUTPUT11 = 0x00000326u, /* tr_group[14].output[11] */ + TRIG3_IN_TR_GROUP14_OUTPUT12 = 0x00000327u, /* tr_group[14].output[12] */ + TRIG3_IN_TR_GROUP14_OUTPUT13 = 0x00000328u, /* tr_group[14].output[13] */ + TRIG3_IN_TR_GROUP14_OUTPUT14 = 0x00000329u, /* tr_group[14].output[14] */ + TRIG3_IN_TR_GROUP14_OUTPUT15 = 0x0000032Au /* tr_group[14].output[15] */ +} en_trig_input_grp3_t; + +/* Trigger Input Group 4 - PROFILE trigger multiplexer */ +typedef enum +{ + TRIG4_IN_CPUSS_ZERO = 0x00000400u, /* cpuss.zero */ + TRIG4_IN_TR_GROUP10_OUTPUT0 = 0x00000401u, /* tr_group[10].output[0] */ + TRIG4_IN_TR_GROUP10_OUTPUT1 = 0x00000402u, /* tr_group[10].output[1] */ + TRIG4_IN_TR_GROUP10_OUTPUT2 = 0x00000403u, /* tr_group[10].output[2] */ + TRIG4_IN_TR_GROUP10_OUTPUT3 = 0x00000404u, /* tr_group[10].output[3] */ + TRIG4_IN_TR_GROUP10_OUTPUT4 = 0x00000405u, /* tr_group[10].output[4] */ + TRIG4_IN_TR_GROUP10_OUTPUT5 = 0x00000406u, /* tr_group[10].output[5] */ + TRIG4_IN_TR_GROUP10_OUTPUT6 = 0x00000407u, /* tr_group[10].output[6] */ + TRIG4_IN_TR_GROUP10_OUTPUT7 = 0x00000408u, /* tr_group[10].output[7] */ + TRIG4_IN_TR_GROUP11_OUTPUT0 = 0x00000409u, /* tr_group[11].output[0] */ + TRIG4_IN_TR_GROUP11_OUTPUT1 = 0x0000040Au, /* tr_group[11].output[1] */ + TRIG4_IN_TR_GROUP11_OUTPUT2 = 0x0000040Bu, /* tr_group[11].output[2] */ + TRIG4_IN_TR_GROUP11_OUTPUT3 = 0x0000040Cu, /* tr_group[11].output[3] */ + TRIG4_IN_TR_GROUP11_OUTPUT4 = 0x0000040Du, /* tr_group[11].output[4] */ + TRIG4_IN_TR_GROUP11_OUTPUT5 = 0x0000040Eu, /* tr_group[11].output[5] */ + TRIG4_IN_TR_GROUP11_OUTPUT6 = 0x0000040Fu, /* tr_group[11].output[6] */ + TRIG4_IN_TR_GROUP11_OUTPUT7 = 0x00000410u, /* tr_group[11].output[7] */ + TRIG4_IN_TR_GROUP11_OUTPUT8 = 0x00000411u, /* tr_group[11].output[8] */ + TRIG4_IN_TR_GROUP11_OUTPUT9 = 0x00000412u, /* tr_group[11].output[9] */ + TRIG4_IN_TR_GROUP11_OUTPUT10 = 0x00000413u, /* tr_group[11].output[10] */ + TRIG4_IN_TR_GROUP11_OUTPUT11 = 0x00000414u, /* tr_group[11].output[11] */ + TRIG4_IN_TR_GROUP11_OUTPUT12 = 0x00000415u, /* tr_group[11].output[12] */ + TRIG4_IN_TR_GROUP11_OUTPUT13 = 0x00000416u, /* tr_group[11].output[13] */ + TRIG4_IN_TR_GROUP11_OUTPUT14 = 0x00000417u, /* tr_group[11].output[14] */ + TRIG4_IN_TR_GROUP11_OUTPUT15 = 0x00000418u, /* tr_group[11].output[15] */ + TRIG4_IN_TR_GROUP12_OUTPUT0 = 0x00000419u, /* tr_group[12].output[0] */ + TRIG4_IN_TR_GROUP12_OUTPUT1 = 0x0000041Au, /* tr_group[12].output[1] */ + TRIG4_IN_TR_GROUP12_OUTPUT2 = 0x0000041Bu, /* tr_group[12].output[2] */ + TRIG4_IN_TR_GROUP12_OUTPUT3 = 0x0000041Cu, /* tr_group[12].output[3] */ + TRIG4_IN_TR_GROUP12_OUTPUT4 = 0x0000041Du, /* tr_group[12].output[4] */ + TRIG4_IN_TR_GROUP12_OUTPUT5 = 0x0000041Eu, /* tr_group[12].output[5] */ + TRIG4_IN_TR_GROUP12_OUTPUT6 = 0x0000041Fu, /* tr_group[12].output[6] */ + TRIG4_IN_TR_GROUP12_OUTPUT7 = 0x00000420u, /* tr_group[12].output[7] */ + TRIG4_IN_TR_GROUP13_OUTPUT16 = 0x00000421u, /* tr_group[13].output[16] */ + TRIG4_IN_TR_GROUP13_OUTPUT17 = 0x00000422u, /* tr_group[13].output[17] */ + TRIG4_IN_TR_GROUP14_OUTPUT8 = 0x00000423u, /* tr_group[14].output[8] */ + TRIG4_IN_TR_GROUP14_OUTPUT9 = 0x00000424u, /* tr_group[14].output[9] */ + TRIG4_IN_TR_GROUP14_OUTPUT10 = 0x00000425u, /* tr_group[14].output[10] */ + TRIG4_IN_TR_GROUP14_OUTPUT11 = 0x00000426u, /* tr_group[14].output[11] */ + TRIG4_IN_TR_GROUP14_OUTPUT12 = 0x00000427u, /* tr_group[14].output[12] */ + TRIG4_IN_TR_GROUP14_OUTPUT13 = 0x00000428u, /* tr_group[14].output[13] */ + TRIG4_IN_TR_GROUP14_OUTPUT14 = 0x00000429u, /* tr_group[14].output[14] */ + TRIG4_IN_TR_GROUP14_OUTPUT15 = 0x0000042Au /* tr_group[14].output[15] */ +} en_trig_input_grp4_t; + +/* Trigger Input Group 5 - CPUSS.CTI trigger multiplexer */ +typedef enum +{ + TRIG5_IN_CPUSS_ZERO = 0x00000500u, /* cpuss.zero */ + TRIG5_IN_TR_GROUP10_OUTPUT0 = 0x00000501u, /* tr_group[10].output[0] */ + TRIG5_IN_TR_GROUP10_OUTPUT1 = 0x00000502u, /* tr_group[10].output[1] */ + TRIG5_IN_TR_GROUP10_OUTPUT2 = 0x00000503u, /* tr_group[10].output[2] */ + TRIG5_IN_TR_GROUP10_OUTPUT3 = 0x00000504u, /* tr_group[10].output[3] */ + TRIG5_IN_TR_GROUP10_OUTPUT4 = 0x00000505u, /* tr_group[10].output[4] */ + TRIG5_IN_TR_GROUP10_OUTPUT5 = 0x00000506u, /* tr_group[10].output[5] */ + TRIG5_IN_TR_GROUP10_OUTPUT6 = 0x00000507u, /* tr_group[10].output[6] */ + TRIG5_IN_TR_GROUP10_OUTPUT7 = 0x00000508u, /* tr_group[10].output[7] */ + TRIG5_IN_TR_GROUP11_OUTPUT0 = 0x00000509u, /* tr_group[11].output[0] */ + TRIG5_IN_TR_GROUP11_OUTPUT1 = 0x0000050Au, /* tr_group[11].output[1] */ + TRIG5_IN_TR_GROUP11_OUTPUT2 = 0x0000050Bu, /* tr_group[11].output[2] */ + TRIG5_IN_TR_GROUP11_OUTPUT3 = 0x0000050Cu, /* tr_group[11].output[3] */ + TRIG5_IN_TR_GROUP11_OUTPUT4 = 0x0000050Du, /* tr_group[11].output[4] */ + TRIG5_IN_TR_GROUP11_OUTPUT5 = 0x0000050Eu, /* tr_group[11].output[5] */ + TRIG5_IN_TR_GROUP11_OUTPUT6 = 0x0000050Fu, /* tr_group[11].output[6] */ + TRIG5_IN_TR_GROUP11_OUTPUT7 = 0x00000510u, /* tr_group[11].output[7] */ + TRIG5_IN_TR_GROUP11_OUTPUT8 = 0x00000511u, /* tr_group[11].output[8] */ + TRIG5_IN_TR_GROUP11_OUTPUT9 = 0x00000512u, /* tr_group[11].output[9] */ + TRIG5_IN_TR_GROUP11_OUTPUT10 = 0x00000513u, /* tr_group[11].output[10] */ + TRIG5_IN_TR_GROUP11_OUTPUT11 = 0x00000514u, /* tr_group[11].output[11] */ + TRIG5_IN_TR_GROUP11_OUTPUT12 = 0x00000515u, /* tr_group[11].output[12] */ + TRIG5_IN_TR_GROUP11_OUTPUT13 = 0x00000516u, /* tr_group[11].output[13] */ + TRIG5_IN_TR_GROUP11_OUTPUT14 = 0x00000517u, /* tr_group[11].output[14] */ + TRIG5_IN_TR_GROUP11_OUTPUT15 = 0x00000518u, /* tr_group[11].output[15] */ + TRIG5_IN_TR_GROUP12_OUTPUT0 = 0x00000519u, /* tr_group[12].output[0] */ + TRIG5_IN_TR_GROUP12_OUTPUT1 = 0x0000051Au, /* tr_group[12].output[1] */ + TRIG5_IN_TR_GROUP12_OUTPUT2 = 0x0000051Bu, /* tr_group[12].output[2] */ + TRIG5_IN_TR_GROUP12_OUTPUT3 = 0x0000051Cu, /* tr_group[12].output[3] */ + TRIG5_IN_TR_GROUP12_OUTPUT4 = 0x0000051Du, /* tr_group[12].output[4] */ + TRIG5_IN_TR_GROUP12_OUTPUT5 = 0x0000051Eu, /* tr_group[12].output[5] */ + TRIG5_IN_TR_GROUP12_OUTPUT6 = 0x0000051Fu, /* tr_group[12].output[6] */ + TRIG5_IN_TR_GROUP12_OUTPUT7 = 0x00000520u, /* tr_group[12].output[7] */ + TRIG5_IN_TR_GROUP13_OUTPUT16 = 0x00000521u, /* tr_group[13].output[16] */ + TRIG5_IN_TR_GROUP13_OUTPUT17 = 0x00000522u, /* tr_group[13].output[17] */ + TRIG5_IN_TR_GROUP14_OUTPUT8 = 0x00000523u, /* tr_group[14].output[8] */ + TRIG5_IN_TR_GROUP14_OUTPUT9 = 0x00000524u, /* tr_group[14].output[9] */ + TRIG5_IN_TR_GROUP14_OUTPUT10 = 0x00000525u, /* tr_group[14].output[10] */ + TRIG5_IN_TR_GROUP14_OUTPUT11 = 0x00000526u, /* tr_group[14].output[11] */ + TRIG5_IN_TR_GROUP14_OUTPUT12 = 0x00000527u, /* tr_group[14].output[12] */ + TRIG5_IN_TR_GROUP14_OUTPUT13 = 0x00000528u, /* tr_group[14].output[13] */ + TRIG5_IN_TR_GROUP14_OUTPUT14 = 0x00000529u, /* tr_group[14].output[14] */ + TRIG5_IN_TR_GROUP14_OUTPUT15 = 0x0000052Au /* tr_group[14].output[15] */ +} en_trig_input_grp5_t; + +/* Trigger Input Group 6 - PASS trigger multiplexer */ +typedef enum +{ + TRIG6_IN_CPUSS_ZERO = 0x00000600u, /* cpuss.zero */ + TRIG6_IN_TR_GROUP10_OUTPUT0 = 0x00000601u, /* tr_group[10].output[0] */ + TRIG6_IN_TR_GROUP10_OUTPUT1 = 0x00000602u, /* tr_group[10].output[1] */ + TRIG6_IN_TR_GROUP10_OUTPUT2 = 0x00000603u, /* tr_group[10].output[2] */ + TRIG6_IN_TR_GROUP10_OUTPUT3 = 0x00000604u, /* tr_group[10].output[3] */ + TRIG6_IN_TR_GROUP10_OUTPUT4 = 0x00000605u, /* tr_group[10].output[4] */ + TRIG6_IN_TR_GROUP10_OUTPUT5 = 0x00000606u, /* tr_group[10].output[5] */ + TRIG6_IN_TR_GROUP10_OUTPUT6 = 0x00000607u, /* tr_group[10].output[6] */ + TRIG6_IN_TR_GROUP10_OUTPUT7 = 0x00000608u, /* tr_group[10].output[7] */ + TRIG6_IN_TR_GROUP11_OUTPUT0 = 0x00000609u, /* tr_group[11].output[0] */ + TRIG6_IN_TR_GROUP11_OUTPUT1 = 0x0000060Au, /* tr_group[11].output[1] */ + TRIG6_IN_TR_GROUP11_OUTPUT2 = 0x0000060Bu, /* tr_group[11].output[2] */ + TRIG6_IN_TR_GROUP11_OUTPUT3 = 0x0000060Cu, /* tr_group[11].output[3] */ + TRIG6_IN_TR_GROUP11_OUTPUT4 = 0x0000060Du, /* tr_group[11].output[4] */ + TRIG6_IN_TR_GROUP11_OUTPUT5 = 0x0000060Eu, /* tr_group[11].output[5] */ + TRIG6_IN_TR_GROUP11_OUTPUT6 = 0x0000060Fu, /* tr_group[11].output[6] */ + TRIG6_IN_TR_GROUP11_OUTPUT7 = 0x00000610u, /* tr_group[11].output[7] */ + TRIG6_IN_TR_GROUP11_OUTPUT8 = 0x00000611u, /* tr_group[11].output[8] */ + TRIG6_IN_TR_GROUP11_OUTPUT9 = 0x00000612u, /* tr_group[11].output[9] */ + TRIG6_IN_TR_GROUP11_OUTPUT10 = 0x00000613u, /* tr_group[11].output[10] */ + TRIG6_IN_TR_GROUP11_OUTPUT11 = 0x00000614u, /* tr_group[11].output[11] */ + TRIG6_IN_TR_GROUP11_OUTPUT12 = 0x00000615u, /* tr_group[11].output[12] */ + TRIG6_IN_TR_GROUP11_OUTPUT13 = 0x00000616u, /* tr_group[11].output[13] */ + TRIG6_IN_TR_GROUP11_OUTPUT14 = 0x00000617u, /* tr_group[11].output[14] */ + TRIG6_IN_TR_GROUP11_OUTPUT15 = 0x00000618u, /* tr_group[11].output[15] */ + TRIG6_IN_TR_GROUP12_OUTPUT0 = 0x00000619u, /* tr_group[12].output[0] */ + TRIG6_IN_TR_GROUP12_OUTPUT1 = 0x0000061Au, /* tr_group[12].output[1] */ + TRIG6_IN_TR_GROUP12_OUTPUT2 = 0x0000061Bu, /* tr_group[12].output[2] */ + TRIG6_IN_TR_GROUP12_OUTPUT3 = 0x0000061Cu, /* tr_group[12].output[3] */ + TRIG6_IN_TR_GROUP12_OUTPUT4 = 0x0000061Du, /* tr_group[12].output[4] */ + TRIG6_IN_TR_GROUP12_OUTPUT5 = 0x0000061Eu, /* tr_group[12].output[5] */ + TRIG6_IN_TR_GROUP12_OUTPUT6 = 0x0000061Fu, /* tr_group[12].output[6] */ + TRIG6_IN_TR_GROUP12_OUTPUT7 = 0x00000620u, /* tr_group[12].output[7] */ + TRIG6_IN_TR_GROUP13_OUTPUT16 = 0x00000621u, /* tr_group[13].output[16] */ + TRIG6_IN_TR_GROUP13_OUTPUT17 = 0x00000622u, /* tr_group[13].output[17] */ + TRIG6_IN_TR_GROUP14_OUTPUT8 = 0x00000623u, /* tr_group[14].output[8] */ + TRIG6_IN_TR_GROUP14_OUTPUT9 = 0x00000624u, /* tr_group[14].output[9] */ + TRIG6_IN_TR_GROUP14_OUTPUT10 = 0x00000625u, /* tr_group[14].output[10] */ + TRIG6_IN_TR_GROUP14_OUTPUT11 = 0x00000626u, /* tr_group[14].output[11] */ + TRIG6_IN_TR_GROUP14_OUTPUT12 = 0x00000627u, /* tr_group[14].output[12] */ + TRIG6_IN_TR_GROUP14_OUTPUT13 = 0x00000628u, /* tr_group[14].output[13] */ + TRIG6_IN_TR_GROUP14_OUTPUT14 = 0x00000629u, /* tr_group[14].output[14] */ + TRIG6_IN_TR_GROUP14_OUTPUT15 = 0x0000062Au /* tr_group[14].output[15] */ +} en_trig_input_grp6_t; + +/* Trigger Input Group 7 - UDB general purpose trigger multiplexer */ +typedef enum +{ + TRIG7_IN_CPUSS_ZERO = 0x00000700u, /* cpuss.zero */ + TRIG7_IN_TR_GROUP10_OUTPUT0 = 0x00000701u, /* tr_group[10].output[0] */ + TRIG7_IN_TR_GROUP10_OUTPUT1 = 0x00000702u, /* tr_group[10].output[1] */ + TRIG7_IN_TR_GROUP10_OUTPUT2 = 0x00000703u, /* tr_group[10].output[2] */ + TRIG7_IN_TR_GROUP10_OUTPUT3 = 0x00000704u, /* tr_group[10].output[3] */ + TRIG7_IN_TR_GROUP10_OUTPUT4 = 0x00000705u, /* tr_group[10].output[4] */ + TRIG7_IN_TR_GROUP10_OUTPUT5 = 0x00000706u, /* tr_group[10].output[5] */ + TRIG7_IN_TR_GROUP10_OUTPUT6 = 0x00000707u, /* tr_group[10].output[6] */ + TRIG7_IN_TR_GROUP10_OUTPUT7 = 0x00000708u, /* tr_group[10].output[7] */ + TRIG7_IN_TR_GROUP11_OUTPUT0 = 0x00000709u, /* tr_group[11].output[0] */ + TRIG7_IN_TR_GROUP11_OUTPUT1 = 0x0000070Au, /* tr_group[11].output[1] */ + TRIG7_IN_TR_GROUP11_OUTPUT2 = 0x0000070Bu, /* tr_group[11].output[2] */ + TRIG7_IN_TR_GROUP11_OUTPUT3 = 0x0000070Cu, /* tr_group[11].output[3] */ + TRIG7_IN_TR_GROUP11_OUTPUT4 = 0x0000070Du, /* tr_group[11].output[4] */ + TRIG7_IN_TR_GROUP11_OUTPUT5 = 0x0000070Eu, /* tr_group[11].output[5] */ + TRIG7_IN_TR_GROUP11_OUTPUT6 = 0x0000070Fu, /* tr_group[11].output[6] */ + TRIG7_IN_TR_GROUP11_OUTPUT7 = 0x00000710u, /* tr_group[11].output[7] */ + TRIG7_IN_TR_GROUP11_OUTPUT8 = 0x00000711u, /* tr_group[11].output[8] */ + TRIG7_IN_TR_GROUP11_OUTPUT9 = 0x00000712u, /* tr_group[11].output[9] */ + TRIG7_IN_TR_GROUP11_OUTPUT10 = 0x00000713u, /* tr_group[11].output[10] */ + TRIG7_IN_TR_GROUP11_OUTPUT11 = 0x00000714u, /* tr_group[11].output[11] */ + TRIG7_IN_TR_GROUP11_OUTPUT12 = 0x00000715u, /* tr_group[11].output[12] */ + TRIG7_IN_TR_GROUP11_OUTPUT13 = 0x00000716u, /* tr_group[11].output[13] */ + TRIG7_IN_TR_GROUP11_OUTPUT14 = 0x00000717u, /* tr_group[11].output[14] */ + TRIG7_IN_TR_GROUP11_OUTPUT15 = 0x00000718u, /* tr_group[11].output[15] */ + TRIG7_IN_TR_GROUP12_OUTPUT0 = 0x00000719u, /* tr_group[12].output[0] */ + TRIG7_IN_TR_GROUP12_OUTPUT1 = 0x0000071Au, /* tr_group[12].output[1] */ + TRIG7_IN_TR_GROUP12_OUTPUT2 = 0x0000071Bu, /* tr_group[12].output[2] */ + TRIG7_IN_TR_GROUP12_OUTPUT3 = 0x0000071Cu, /* tr_group[12].output[3] */ + TRIG7_IN_TR_GROUP12_OUTPUT4 = 0x0000071Du, /* tr_group[12].output[4] */ + TRIG7_IN_TR_GROUP12_OUTPUT5 = 0x0000071Eu, /* tr_group[12].output[5] */ + TRIG7_IN_TR_GROUP12_OUTPUT6 = 0x0000071Fu, /* tr_group[12].output[6] */ + TRIG7_IN_TR_GROUP12_OUTPUT7 = 0x00000720u, /* tr_group[12].output[7] */ + TRIG7_IN_TR_GROUP13_OUTPUT16 = 0x00000721u, /* tr_group[13].output[16] */ + TRIG7_IN_TR_GROUP13_OUTPUT17 = 0x00000722u, /* tr_group[13].output[17] */ + TRIG7_IN_TR_GROUP14_OUTPUT8 = 0x00000723u, /* tr_group[14].output[8] */ + TRIG7_IN_TR_GROUP14_OUTPUT9 = 0x00000724u, /* tr_group[14].output[9] */ + TRIG7_IN_TR_GROUP14_OUTPUT10 = 0x00000725u, /* tr_group[14].output[10] */ + TRIG7_IN_TR_GROUP14_OUTPUT11 = 0x00000726u, /* tr_group[14].output[11] */ + TRIG7_IN_TR_GROUP14_OUTPUT12 = 0x00000727u, /* tr_group[14].output[12] */ + TRIG7_IN_TR_GROUP14_OUTPUT13 = 0x00000728u, /* tr_group[14].output[13] */ + TRIG7_IN_TR_GROUP14_OUTPUT14 = 0x00000729u, /* tr_group[14].output[14] */ + TRIG7_IN_TR_GROUP14_OUTPUT15 = 0x0000072Au /* tr_group[14].output[15] */ +} en_trig_input_grp7_t; + +/* Trigger Input Group 8 - Trigger multiplexer to pins */ +typedef enum +{ + TRIG8_IN_CPUSS_ZERO = 0x00000800u, /* cpuss.zero */ + TRIG8_IN_TR_GROUP10_OUTPUT0 = 0x00000801u, /* tr_group[10].output[0] */ + TRIG8_IN_TR_GROUP10_OUTPUT1 = 0x00000802u, /* tr_group[10].output[1] */ + TRIG8_IN_TR_GROUP10_OUTPUT2 = 0x00000803u, /* tr_group[10].output[2] */ + TRIG8_IN_TR_GROUP10_OUTPUT3 = 0x00000804u, /* tr_group[10].output[3] */ + TRIG8_IN_TR_GROUP10_OUTPUT4 = 0x00000805u, /* tr_group[10].output[4] */ + TRIG8_IN_TR_GROUP10_OUTPUT5 = 0x00000806u, /* tr_group[10].output[5] */ + TRIG8_IN_TR_GROUP10_OUTPUT6 = 0x00000807u, /* tr_group[10].output[6] */ + TRIG8_IN_TR_GROUP10_OUTPUT7 = 0x00000808u, /* tr_group[10].output[7] */ + TRIG8_IN_TR_GROUP11_OUTPUT0 = 0x00000809u, /* tr_group[11].output[0] */ + TRIG8_IN_TR_GROUP11_OUTPUT1 = 0x0000080Au, /* tr_group[11].output[1] */ + TRIG8_IN_TR_GROUP11_OUTPUT2 = 0x0000080Bu, /* tr_group[11].output[2] */ + TRIG8_IN_TR_GROUP11_OUTPUT3 = 0x0000080Cu, /* tr_group[11].output[3] */ + TRIG8_IN_TR_GROUP11_OUTPUT4 = 0x0000080Du, /* tr_group[11].output[4] */ + TRIG8_IN_TR_GROUP11_OUTPUT5 = 0x0000080Eu, /* tr_group[11].output[5] */ + TRIG8_IN_TR_GROUP11_OUTPUT6 = 0x0000080Fu, /* tr_group[11].output[6] */ + TRIG8_IN_TR_GROUP11_OUTPUT7 = 0x00000810u, /* tr_group[11].output[7] */ + TRIG8_IN_TR_GROUP11_OUTPUT8 = 0x00000811u, /* tr_group[11].output[8] */ + TRIG8_IN_TR_GROUP11_OUTPUT9 = 0x00000812u, /* tr_group[11].output[9] */ + TRIG8_IN_TR_GROUP11_OUTPUT10 = 0x00000813u, /* tr_group[11].output[10] */ + TRIG8_IN_TR_GROUP11_OUTPUT11 = 0x00000814u, /* tr_group[11].output[11] */ + TRIG8_IN_TR_GROUP11_OUTPUT12 = 0x00000815u, /* tr_group[11].output[12] */ + TRIG8_IN_TR_GROUP11_OUTPUT13 = 0x00000816u, /* tr_group[11].output[13] */ + TRIG8_IN_TR_GROUP11_OUTPUT14 = 0x00000817u, /* tr_group[11].output[14] */ + TRIG8_IN_TR_GROUP11_OUTPUT15 = 0x00000818u, /* tr_group[11].output[15] */ + TRIG8_IN_TR_GROUP12_OUTPUT0 = 0x00000819u, /* tr_group[12].output[0] */ + TRIG8_IN_TR_GROUP12_OUTPUT1 = 0x0000081Au, /* tr_group[12].output[1] */ + TRIG8_IN_TR_GROUP12_OUTPUT2 = 0x0000081Bu, /* tr_group[12].output[2] */ + TRIG8_IN_TR_GROUP12_OUTPUT3 = 0x0000081Cu, /* tr_group[12].output[3] */ + TRIG8_IN_TR_GROUP12_OUTPUT4 = 0x0000081Du, /* tr_group[12].output[4] */ + TRIG8_IN_TR_GROUP12_OUTPUT5 = 0x0000081Eu, /* tr_group[12].output[5] */ + TRIG8_IN_TR_GROUP12_OUTPUT6 = 0x0000081Fu, /* tr_group[12].output[6] */ + TRIG8_IN_TR_GROUP12_OUTPUT7 = 0x00000820u, /* tr_group[12].output[7] */ + TRIG8_IN_TR_GROUP13_OUTPUT16 = 0x00000821u, /* tr_group[13].output[16] */ + TRIG8_IN_TR_GROUP13_OUTPUT17 = 0x00000822u, /* tr_group[13].output[17] */ + TRIG8_IN_TR_GROUP14_OUTPUT8 = 0x00000823u, /* tr_group[14].output[8] */ + TRIG8_IN_TR_GROUP14_OUTPUT9 = 0x00000824u, /* tr_group[14].output[9] */ + TRIG8_IN_TR_GROUP14_OUTPUT10 = 0x00000825u, /* tr_group[14].output[10] */ + TRIG8_IN_TR_GROUP14_OUTPUT11 = 0x00000826u, /* tr_group[14].output[11] */ + TRIG8_IN_TR_GROUP14_OUTPUT12 = 0x00000827u, /* tr_group[14].output[12] */ + TRIG8_IN_TR_GROUP14_OUTPUT13 = 0x00000828u, /* tr_group[14].output[13] */ + TRIG8_IN_TR_GROUP14_OUTPUT14 = 0x00000829u, /* tr_group[14].output[14] */ + TRIG8_IN_TR_GROUP14_OUTPUT15 = 0x0000082Au /* tr_group[14].output[15] */ +} en_trig_input_grp8_t; + +/* Trigger Input Group 9 - Feedback mux to USB DMA interface */ +typedef enum +{ + TRIG9_IN_CPUSS_ZERO = 0x00000900u, /* cpuss.zero */ + TRIG9_IN_CPUSS_DW0_TR_OUT0 = 0x00000901u, /* cpuss.dw0_tr_out[0] */ + TRIG9_IN_CPUSS_DW0_TR_OUT1 = 0x00000902u, /* cpuss.dw0_tr_out[1] */ + TRIG9_IN_CPUSS_DW0_TR_OUT2 = 0x00000903u, /* cpuss.dw0_tr_out[2] */ + TRIG9_IN_CPUSS_DW0_TR_OUT3 = 0x00000904u, /* cpuss.dw0_tr_out[3] */ + TRIG9_IN_CPUSS_DW0_TR_OUT4 = 0x00000905u, /* cpuss.dw0_tr_out[4] */ + TRIG9_IN_CPUSS_DW0_TR_OUT5 = 0x00000906u, /* cpuss.dw0_tr_out[5] */ + TRIG9_IN_CPUSS_DW0_TR_OUT6 = 0x00000907u, /* cpuss.dw0_tr_out[6] */ + TRIG9_IN_CPUSS_DW0_TR_OUT7 = 0x00000908u, /* cpuss.dw0_tr_out[7] */ + TRIG9_IN_CPUSS_DW0_TR_OUT8 = 0x00000909u, /* cpuss.dw0_tr_out[8] */ + TRIG9_IN_CPUSS_DW0_TR_OUT9 = 0x0000090Au, /* cpuss.dw0_tr_out[9] */ + TRIG9_IN_CPUSS_DW0_TR_OUT10 = 0x0000090Bu, /* cpuss.dw0_tr_out[10] */ + TRIG9_IN_CPUSS_DW0_TR_OUT11 = 0x0000090Cu, /* cpuss.dw0_tr_out[11] */ + TRIG9_IN_CPUSS_DW0_TR_OUT12 = 0x0000090Du, /* cpuss.dw0_tr_out[12] */ + TRIG9_IN_CPUSS_DW0_TR_OUT13 = 0x0000090Eu, /* cpuss.dw0_tr_out[13] */ + TRIG9_IN_CPUSS_DW0_TR_OUT14 = 0x0000090Fu, /* cpuss.dw0_tr_out[14] */ + TRIG9_IN_CPUSS_DW0_TR_OUT15 = 0x00000910u, /* cpuss.dw0_tr_out[15] */ + TRIG9_IN_CPUSS_DW1_TR_OUT0 = 0x00000911u, /* cpuss.dw1_tr_out[0] */ + TRIG9_IN_CPUSS_DW1_TR_OUT1 = 0x00000912u, /* cpuss.dw1_tr_out[1] */ + TRIG9_IN_CPUSS_DW1_TR_OUT2 = 0x00000913u, /* cpuss.dw1_tr_out[2] */ + TRIG9_IN_CPUSS_DW1_TR_OUT3 = 0x00000914u, /* cpuss.dw1_tr_out[3] */ + TRIG9_IN_CPUSS_DW1_TR_OUT4 = 0x00000915u, /* cpuss.dw1_tr_out[4] */ + TRIG9_IN_CPUSS_DW1_TR_OUT5 = 0x00000916u, /* cpuss.dw1_tr_out[5] */ + TRIG9_IN_CPUSS_DW1_TR_OUT6 = 0x00000917u, /* cpuss.dw1_tr_out[6] */ + TRIG9_IN_CPUSS_DW1_TR_OUT7 = 0x00000918u, /* cpuss.dw1_tr_out[7] */ + TRIG9_IN_CPUSS_DW1_TR_OUT8 = 0x00000919u, /* cpuss.dw1_tr_out[8] */ + TRIG9_IN_CPUSS_DW1_TR_OUT9 = 0x0000091Au, /* cpuss.dw1_tr_out[9] */ + TRIG9_IN_CPUSS_DW1_TR_OUT10 = 0x0000091Bu, /* cpuss.dw1_tr_out[10] */ + TRIG9_IN_CPUSS_DW1_TR_OUT11 = 0x0000091Cu, /* cpuss.dw1_tr_out[11] */ + TRIG9_IN_CPUSS_DW1_TR_OUT12 = 0x0000091Du, /* cpuss.dw1_tr_out[12] */ + TRIG9_IN_CPUSS_DW1_TR_OUT13 = 0x0000091Eu, /* cpuss.dw1_tr_out[13] */ + TRIG9_IN_CPUSS_DW1_TR_OUT14 = 0x0000091Fu, /* cpuss.dw1_tr_out[14] */ + TRIG9_IN_CPUSS_DW1_TR_OUT15 = 0x00000920u /* cpuss.dw1_tr_out[15] */ +} en_trig_input_grp9_t; + +/* Trigger Input Group 10 - Reduces 32 datawire output triggers to 8 signals, used by all except USB */ +typedef enum +{ + TRIG10_IN_CPUSS_ZERO = 0x00000A00u, /* cpuss.zero */ + TRIG10_IN_CPUSS_DW0_TR_OUT0 = 0x00000A01u, /* cpuss.dw0_tr_out[0] */ + TRIG10_IN_CPUSS_DW0_TR_OUT1 = 0x00000A02u, /* cpuss.dw0_tr_out[1] */ + TRIG10_IN_CPUSS_DW0_TR_OUT2 = 0x00000A03u, /* cpuss.dw0_tr_out[2] */ + TRIG10_IN_CPUSS_DW0_TR_OUT3 = 0x00000A04u, /* cpuss.dw0_tr_out[3] */ + TRIG10_IN_CPUSS_DW0_TR_OUT4 = 0x00000A05u, /* cpuss.dw0_tr_out[4] */ + TRIG10_IN_CPUSS_DW0_TR_OUT5 = 0x00000A06u, /* cpuss.dw0_tr_out[5] */ + TRIG10_IN_CPUSS_DW0_TR_OUT6 = 0x00000A07u, /* cpuss.dw0_tr_out[6] */ + TRIG10_IN_CPUSS_DW0_TR_OUT7 = 0x00000A08u, /* cpuss.dw0_tr_out[7] */ + TRIG10_IN_CPUSS_DW0_TR_OUT8 = 0x00000A09u, /* cpuss.dw0_tr_out[8] */ + TRIG10_IN_CPUSS_DW0_TR_OUT9 = 0x00000A0Au, /* cpuss.dw0_tr_out[9] */ + TRIG10_IN_CPUSS_DW0_TR_OUT10 = 0x00000A0Bu, /* cpuss.dw0_tr_out[10] */ + TRIG10_IN_CPUSS_DW0_TR_OUT11 = 0x00000A0Cu, /* cpuss.dw0_tr_out[11] */ + TRIG10_IN_CPUSS_DW0_TR_OUT12 = 0x00000A0Du, /* cpuss.dw0_tr_out[12] */ + TRIG10_IN_CPUSS_DW0_TR_OUT13 = 0x00000A0Eu, /* cpuss.dw0_tr_out[13] */ + TRIG10_IN_CPUSS_DW0_TR_OUT14 = 0x00000A0Fu, /* cpuss.dw0_tr_out[14] */ + TRIG10_IN_CPUSS_DW0_TR_OUT15 = 0x00000A10u, /* cpuss.dw0_tr_out[15] */ + TRIG10_IN_CPUSS_DW1_TR_OUT0 = 0x00000A11u, /* cpuss.dw1_tr_out[0] */ + TRIG10_IN_CPUSS_DW1_TR_OUT1 = 0x00000A12u, /* cpuss.dw1_tr_out[1] */ + TRIG10_IN_CPUSS_DW1_TR_OUT2 = 0x00000A13u, /* cpuss.dw1_tr_out[2] */ + TRIG10_IN_CPUSS_DW1_TR_OUT3 = 0x00000A14u, /* cpuss.dw1_tr_out[3] */ + TRIG10_IN_CPUSS_DW1_TR_OUT4 = 0x00000A15u, /* cpuss.dw1_tr_out[4] */ + TRIG10_IN_CPUSS_DW1_TR_OUT5 = 0x00000A16u, /* cpuss.dw1_tr_out[5] */ + TRIG10_IN_CPUSS_DW1_TR_OUT6 = 0x00000A17u, /* cpuss.dw1_tr_out[6] */ + TRIG10_IN_CPUSS_DW1_TR_OUT7 = 0x00000A18u, /* cpuss.dw1_tr_out[7] */ + TRIG10_IN_CPUSS_DW1_TR_OUT8 = 0x00000A19u, /* cpuss.dw1_tr_out[8] */ + TRIG10_IN_CPUSS_DW1_TR_OUT9 = 0x00000A1Au, /* cpuss.dw1_tr_out[9] */ + TRIG10_IN_CPUSS_DW1_TR_OUT10 = 0x00000A1Bu, /* cpuss.dw1_tr_out[10] */ + TRIG10_IN_CPUSS_DW1_TR_OUT11 = 0x00000A1Cu, /* cpuss.dw1_tr_out[11] */ + TRIG10_IN_CPUSS_DW1_TR_OUT12 = 0x00000A1Du, /* cpuss.dw1_tr_out[12] */ + TRIG10_IN_CPUSS_DW1_TR_OUT13 = 0x00000A1Eu, /* cpuss.dw1_tr_out[13] */ + TRIG10_IN_CPUSS_DW1_TR_OUT14 = 0x00000A1Fu, /* cpuss.dw1_tr_out[14] */ + TRIG10_IN_CPUSS_DW1_TR_OUT15 = 0x00000A20u /* cpuss.dw1_tr_out[15] */ +} en_trig_input_grp10_t; + +/* Trigger Input Group 11 - Reduces 96 tcpwm output triggers to 16 signals, used by all sinks */ +typedef enum +{ + TRIG11_IN_CPUSS_ZERO = 0x00000B00u, /* cpuss.zero */ + TRIG11_IN_TCPWM0_TR_OVERFLOW0 = 0x00000B01u, /* tcpwm[0].tr_overflow[0] */ + TRIG11_IN_TCPWM0_TR_OVERFLOW1 = 0x00000B02u, /* tcpwm[0].tr_overflow[1] */ + TRIG11_IN_TCPWM0_TR_OVERFLOW2 = 0x00000B03u, /* tcpwm[0].tr_overflow[2] */ + TRIG11_IN_TCPWM0_TR_OVERFLOW3 = 0x00000B04u, /* tcpwm[0].tr_overflow[3] */ + TRIG11_IN_TCPWM0_TR_OVERFLOW4 = 0x00000B05u, /* tcpwm[0].tr_overflow[4] */ + TRIG11_IN_TCPWM0_TR_OVERFLOW5 = 0x00000B06u, /* tcpwm[0].tr_overflow[5] */ + TRIG11_IN_TCPWM0_TR_OVERFLOW6 = 0x00000B07u, /* tcpwm[0].tr_overflow[6] */ + TRIG11_IN_TCPWM0_TR_OVERFLOW7 = 0x00000B08u, /* tcpwm[0].tr_overflow[7] */ + TRIG11_IN_TCPWM0_TR_COMPARE_MATCH0 = 0x00000B09u, /* tcpwm[0].tr_compare_match[0] */ + TRIG11_IN_TCPWM0_TR_COMPARE_MATCH1 = 0x00000B0Au, /* tcpwm[0].tr_compare_match[1] */ + TRIG11_IN_TCPWM0_TR_COMPARE_MATCH2 = 0x00000B0Bu, /* tcpwm[0].tr_compare_match[2] */ + TRIG11_IN_TCPWM0_TR_COMPARE_MATCH3 = 0x00000B0Cu, /* tcpwm[0].tr_compare_match[3] */ + TRIG11_IN_TCPWM0_TR_COMPARE_MATCH4 = 0x00000B0Du, /* tcpwm[0].tr_compare_match[4] */ + TRIG11_IN_TCPWM0_TR_COMPARE_MATCH5 = 0x00000B0Eu, /* tcpwm[0].tr_compare_match[5] */ + TRIG11_IN_TCPWM0_TR_COMPARE_MATCH6 = 0x00000B0Fu, /* tcpwm[0].tr_compare_match[6] */ + TRIG11_IN_TCPWM0_TR_COMPARE_MATCH7 = 0x00000B10u, /* tcpwm[0].tr_compare_match[7] */ + TRIG11_IN_TCPWM0_TR_UNDERFLOW0 = 0x00000B11u, /* tcpwm[0].tr_underflow[0] */ + TRIG11_IN_TCPWM0_TR_UNDERFLOW1 = 0x00000B12u, /* tcpwm[0].tr_underflow[1] */ + TRIG11_IN_TCPWM0_TR_UNDERFLOW2 = 0x00000B13u, /* tcpwm[0].tr_underflow[2] */ + TRIG11_IN_TCPWM0_TR_UNDERFLOW3 = 0x00000B14u, /* tcpwm[0].tr_underflow[3] */ + TRIG11_IN_TCPWM0_TR_UNDERFLOW4 = 0x00000B15u, /* tcpwm[0].tr_underflow[4] */ + TRIG11_IN_TCPWM0_TR_UNDERFLOW5 = 0x00000B16u, /* tcpwm[0].tr_underflow[5] */ + TRIG11_IN_TCPWM0_TR_UNDERFLOW6 = 0x00000B17u, /* tcpwm[0].tr_underflow[6] */ + TRIG11_IN_TCPWM0_TR_UNDERFLOW7 = 0x00000B18u, /* tcpwm[0].tr_underflow[7] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW0 = 0x00000B19u, /* tcpwm[1].tr_overflow[0] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW1 = 0x00000B1Au, /* tcpwm[1].tr_overflow[1] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW2 = 0x00000B1Bu, /* tcpwm[1].tr_overflow[2] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW3 = 0x00000B1Cu, /* tcpwm[1].tr_overflow[3] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW4 = 0x00000B1Du, /* tcpwm[1].tr_overflow[4] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW5 = 0x00000B1Eu, /* tcpwm[1].tr_overflow[5] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW6 = 0x00000B1Fu, /* tcpwm[1].tr_overflow[6] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW7 = 0x00000B20u, /* tcpwm[1].tr_overflow[7] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW8 = 0x00000B21u, /* tcpwm[1].tr_overflow[8] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW9 = 0x00000B22u, /* tcpwm[1].tr_overflow[9] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW10 = 0x00000B23u, /* tcpwm[1].tr_overflow[10] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW11 = 0x00000B24u, /* tcpwm[1].tr_overflow[11] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW12 = 0x00000B25u, /* tcpwm[1].tr_overflow[12] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW13 = 0x00000B26u, /* tcpwm[1].tr_overflow[13] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW14 = 0x00000B27u, /* tcpwm[1].tr_overflow[14] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW15 = 0x00000B28u, /* tcpwm[1].tr_overflow[15] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW16 = 0x00000B29u, /* tcpwm[1].tr_overflow[16] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW17 = 0x00000B2Au, /* tcpwm[1].tr_overflow[17] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW18 = 0x00000B2Bu, /* tcpwm[1].tr_overflow[18] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW19 = 0x00000B2Cu, /* tcpwm[1].tr_overflow[19] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW20 = 0x00000B2Du, /* tcpwm[1].tr_overflow[20] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW21 = 0x00000B2Eu, /* tcpwm[1].tr_overflow[21] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW22 = 0x00000B2Fu, /* tcpwm[1].tr_overflow[22] */ + TRIG11_IN_TCPWM1_TR_OVERFLOW23 = 0x00000B30u, /* tcpwm[1].tr_overflow[23] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH0 = 0x00000B31u, /* tcpwm[1].tr_compare_match[0] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH1 = 0x00000B32u, /* tcpwm[1].tr_compare_match[1] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH2 = 0x00000B33u, /* tcpwm[1].tr_compare_match[2] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH3 = 0x00000B34u, /* tcpwm[1].tr_compare_match[3] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH4 = 0x00000B35u, /* tcpwm[1].tr_compare_match[4] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH5 = 0x00000B36u, /* tcpwm[1].tr_compare_match[5] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH6 = 0x00000B37u, /* tcpwm[1].tr_compare_match[6] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH7 = 0x00000B38u, /* tcpwm[1].tr_compare_match[7] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH8 = 0x00000B39u, /* tcpwm[1].tr_compare_match[8] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH9 = 0x00000B3Au, /* tcpwm[1].tr_compare_match[9] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH10 = 0x00000B3Bu, /* tcpwm[1].tr_compare_match[10] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH11 = 0x00000B3Cu, /* tcpwm[1].tr_compare_match[11] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH12 = 0x00000B3Du, /* tcpwm[1].tr_compare_match[12] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH13 = 0x00000B3Eu, /* tcpwm[1].tr_compare_match[13] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH14 = 0x00000B3Fu, /* tcpwm[1].tr_compare_match[14] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH15 = 0x00000B40u, /* tcpwm[1].tr_compare_match[15] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH16 = 0x00000B41u, /* tcpwm[1].tr_compare_match[16] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH17 = 0x00000B42u, /* tcpwm[1].tr_compare_match[17] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH18 = 0x00000B43u, /* tcpwm[1].tr_compare_match[18] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH19 = 0x00000B44u, /* tcpwm[1].tr_compare_match[19] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH20 = 0x00000B45u, /* tcpwm[1].tr_compare_match[20] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH21 = 0x00000B46u, /* tcpwm[1].tr_compare_match[21] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH22 = 0x00000B47u, /* tcpwm[1].tr_compare_match[22] */ + TRIG11_IN_TCPWM1_TR_COMPARE_MATCH23 = 0x00000B48u, /* tcpwm[1].tr_compare_match[23] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW0 = 0x00000B49u, /* tcpwm[1].tr_underflow[0] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW1 = 0x00000B4Au, /* tcpwm[1].tr_underflow[1] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW2 = 0x00000B4Bu, /* tcpwm[1].tr_underflow[2] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW3 = 0x00000B4Cu, /* tcpwm[1].tr_underflow[3] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW4 = 0x00000B4Du, /* tcpwm[1].tr_underflow[4] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW5 = 0x00000B4Eu, /* tcpwm[1].tr_underflow[5] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW6 = 0x00000B4Fu, /* tcpwm[1].tr_underflow[6] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW7 = 0x00000B50u, /* tcpwm[1].tr_underflow[7] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW8 = 0x00000B51u, /* tcpwm[1].tr_underflow[8] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW9 = 0x00000B52u, /* tcpwm[1].tr_underflow[9] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW10 = 0x00000B53u, /* tcpwm[1].tr_underflow[10] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW11 = 0x00000B54u, /* tcpwm[1].tr_underflow[11] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW12 = 0x00000B55u, /* tcpwm[1].tr_underflow[12] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW13 = 0x00000B56u, /* tcpwm[1].tr_underflow[13] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW14 = 0x00000B57u, /* tcpwm[1].tr_underflow[14] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW15 = 0x00000B58u, /* tcpwm[1].tr_underflow[15] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW16 = 0x00000B59u, /* tcpwm[1].tr_underflow[16] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW17 = 0x00000B5Au, /* tcpwm[1].tr_underflow[17] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW18 = 0x00000B5Bu, /* tcpwm[1].tr_underflow[18] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW19 = 0x00000B5Cu, /* tcpwm[1].tr_underflow[19] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW20 = 0x00000B5Du, /* tcpwm[1].tr_underflow[20] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW21 = 0x00000B5Eu, /* tcpwm[1].tr_underflow[21] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW22 = 0x00000B5Fu, /* tcpwm[1].tr_underflow[22] */ + TRIG11_IN_TCPWM1_TR_UNDERFLOW23 = 0x00000B60u /* tcpwm[1].tr_underflow[23] */ +} en_trig_input_grp11_t; + +/* Trigger Input Group 12 - Reduces 28 pin input signals to 10 triggers used by all sinks */ +typedef enum +{ + TRIG12_IN_CPUSS_ZERO = 0x00000C00u, /* cpuss.zero */ + TRIG12_IN_PERI_TR_IO_INPUT0 = 0x00000C01u, /* peri.tr_io_input[0] */ + TRIG12_IN_PERI_TR_IO_INPUT1 = 0x00000C02u, /* peri.tr_io_input[1] */ + TRIG12_IN_PERI_TR_IO_INPUT2 = 0x00000C03u, /* peri.tr_io_input[2] */ + TRIG12_IN_PERI_TR_IO_INPUT3 = 0x00000C04u, /* peri.tr_io_input[3] */ + TRIG12_IN_PERI_TR_IO_INPUT4 = 0x00000C05u, /* peri.tr_io_input[4] */ + TRIG12_IN_PERI_TR_IO_INPUT5 = 0x00000C06u, /* peri.tr_io_input[5] */ + TRIG12_IN_PERI_TR_IO_INPUT6 = 0x00000C07u, /* peri.tr_io_input[6] */ + TRIG12_IN_PERI_TR_IO_INPUT7 = 0x00000C08u, /* peri.tr_io_input[7] */ + TRIG12_IN_PERI_TR_IO_INPUT8 = 0x00000C09u, /* peri.tr_io_input[8] */ + TRIG12_IN_PERI_TR_IO_INPUT9 = 0x00000C0Au, /* peri.tr_io_input[9] */ + TRIG12_IN_PERI_TR_IO_INPUT10 = 0x00000C0Bu, /* peri.tr_io_input[10] */ + TRIG12_IN_PERI_TR_IO_INPUT11 = 0x00000C0Cu, /* peri.tr_io_input[11] */ + TRIG12_IN_PERI_TR_IO_INPUT12 = 0x00000C0Du, /* peri.tr_io_input[12] */ + TRIG12_IN_PERI_TR_IO_INPUT13 = 0x00000C0Eu, /* peri.tr_io_input[13] */ + TRIG12_IN_PERI_TR_IO_INPUT14 = 0x00000C0Fu, /* peri.tr_io_input[14] */ + TRIG12_IN_PERI_TR_IO_INPUT15 = 0x00000C10u, /* peri.tr_io_input[15] */ + TRIG12_IN_PERI_TR_IO_INPUT16 = 0x00000C11u, /* peri.tr_io_input[16] */ + TRIG12_IN_PERI_TR_IO_INPUT17 = 0x00000C12u, /* peri.tr_io_input[17] */ + TRIG12_IN_PERI_TR_IO_INPUT18 = 0x00000C13u, /* peri.tr_io_input[18] */ + TRIG12_IN_PERI_TR_IO_INPUT19 = 0x00000C14u, /* peri.tr_io_input[19] */ + TRIG12_IN_PERI_TR_IO_INPUT20 = 0x00000C15u, /* peri.tr_io_input[20] */ + TRIG12_IN_PERI_TR_IO_INPUT21 = 0x00000C16u, /* peri.tr_io_input[21] */ + TRIG12_IN_PERI_TR_IO_INPUT22 = 0x00000C17u, /* peri.tr_io_input[22] */ + TRIG12_IN_PERI_TR_IO_INPUT23 = 0x00000C18u, /* peri.tr_io_input[23] */ + TRIG12_IN_PERI_TR_IO_INPUT24 = 0x00000C19u, /* peri.tr_io_input[24] */ + TRIG12_IN_PERI_TR_IO_INPUT25 = 0x00000C1Au, /* peri.tr_io_input[25] */ + TRIG12_IN_PERI_TR_IO_INPUT26 = 0x00000C1Bu, /* peri.tr_io_input[26] */ + TRIG12_IN_PERI_TR_IO_INPUT27 = 0x00000C1Cu /* peri.tr_io_input[27] */ +} en_trig_input_grp12_t; + +/* Trigger Input Group 13 - Reduces DMA requests to 16+2 outputs used by all sinks */ +typedef enum +{ + TRIG13_IN_CPUSS_ZERO = 0x00000D00u, /* cpuss.zero */ + TRIG13_IN_SCB0_TR_TX_REQ = 0x00000D01u, /* scb[0].tr_tx_req */ + TRIG13_IN_SCB0_TR_RX_REQ = 0x00000D02u, /* scb[0].tr_rx_req */ + TRIG13_IN_SCB1_TR_TX_REQ = 0x00000D03u, /* scb[1].tr_tx_req */ + TRIG13_IN_SCB1_TR_RX_REQ = 0x00000D04u, /* scb[1].tr_rx_req */ + TRIG13_IN_SCB2_TR_TX_REQ = 0x00000D05u, /* scb[2].tr_tx_req */ + TRIG13_IN_SCB2_TR_RX_REQ = 0x00000D06u, /* scb[2].tr_rx_req */ + TRIG13_IN_SCB3_TR_TX_REQ = 0x00000D07u, /* scb[3].tr_tx_req */ + TRIG13_IN_SCB3_TR_RX_REQ = 0x00000D08u, /* scb[3].tr_rx_req */ + TRIG13_IN_SCB4_TR_TX_REQ = 0x00000D09u, /* scb[4].tr_tx_req */ + TRIG13_IN_SCB4_TR_RX_REQ = 0x00000D0Au, /* scb[4].tr_rx_req */ + TRIG13_IN_SCB5_TR_TX_REQ = 0x00000D0Bu, /* scb[5].tr_tx_req */ + TRIG13_IN_SCB5_TR_RX_REQ = 0x00000D0Cu, /* scb[5].tr_rx_req */ + TRIG13_IN_SCB6_TR_TX_REQ = 0x00000D0Du, /* scb[6].tr_tx_req */ + TRIG13_IN_SCB6_TR_RX_REQ = 0x00000D0Eu, /* scb[6].tr_rx_req */ + TRIG13_IN_SCB7_TR_TX_REQ = 0x00000D0Fu, /* scb[7].tr_tx_req */ + TRIG13_IN_SCB7_TR_RX_REQ = 0x00000D10u, /* scb[7].tr_rx_req */ + TRIG13_IN_SCB8_TR_TX_REQ = 0x00000D11u, /* scb[8].tr_tx_req */ + TRIG13_IN_SCB8_TR_RX_REQ = 0x00000D12u, /* scb[8].tr_rx_req */ + TRIG13_IN_AUDIOSS_TR_PDM_RX_REQ = 0x00000D13u, /* audioss.tr_pdm_rx_req */ + TRIG13_IN_AUDIOSS_TR_I2S_TX_REQ = 0x00000D14u, /* audioss.tr_i2s_tx_req */ + TRIG13_IN_AUDIOSS_TR_I2S_RX_REQ = 0x00000D15u, /* audioss.tr_i2s_rx_req */ + TRIG13_IN_SMIF_TR_TX_REQ = 0x00000D16u, /* smif.tr_tx_req */ + TRIG13_IN_SMIF_TR_RX_REQ = 0x00000D17u, /* smif.tr_rx_req */ + TRIG13_IN_USB_DMA_REQ0 = 0x00000D18u, /* usb.dma_req[0] */ + TRIG13_IN_USB_DMA_REQ1 = 0x00000D19u, /* usb.dma_req[1] */ + TRIG13_IN_USB_DMA_REQ2 = 0x00000D1Au, /* usb.dma_req[2] */ + TRIG13_IN_USB_DMA_REQ3 = 0x00000D1Bu, /* usb.dma_req[3] */ + TRIG13_IN_USB_DMA_REQ4 = 0x00000D1Cu, /* usb.dma_req[4] */ + TRIG13_IN_USB_DMA_REQ5 = 0x00000D1Du, /* usb.dma_req[5] */ + TRIG13_IN_USB_DMA_REQ6 = 0x00000D1Eu, /* usb.dma_req[6] */ + TRIG13_IN_USB_DMA_REQ7 = 0x00000D1Fu, /* usb.dma_req[7] */ + TRIG13_IN_CSD_TR_ADC_DONE = 0x00000D20u, /* csd.tr_adc_done */ + TRIG13_IN_CSD_DSI_SENSE_OUT = 0x00000D21u /* csd.dsi_sense_out */ +} en_trig_input_grp13_t; + +/* Trigger Input Group 14 - Reduces general purpose trigger inputs to 8+8 outputs used by all sinks */ +typedef enum +{ + TRIG14_IN_CPUSS_ZERO = 0x00000E00u, /* cpuss.zero */ + TRIG14_IN_UDB_TR_UDB0 = 0x00000E01u, /* udb.tr_udb[0] */ + TRIG14_IN_UDB_TR_UDB1 = 0x00000E02u, /* udb.tr_udb[1] */ + TRIG14_IN_UDB_TR_UDB2 = 0x00000E03u, /* udb.tr_udb[2] */ + TRIG14_IN_UDB_TR_UDB3 = 0x00000E04u, /* udb.tr_udb[3] */ + TRIG14_IN_UDB_TR_UDB4 = 0x00000E05u, /* udb.tr_udb[4] */ + TRIG14_IN_UDB_TR_UDB5 = 0x00000E06u, /* udb.tr_udb[5] */ + TRIG14_IN_UDB_TR_UDB6 = 0x00000E07u, /* udb.tr_udb[6] */ + TRIG14_IN_UDB_TR_UDB7 = 0x00000E08u, /* udb.tr_udb[7] */ + TRIG14_IN_UDB_TR_UDB8 = 0x00000E09u, /* udb.tr_udb[8] */ + TRIG14_IN_UDB_TR_UDB9 = 0x00000E0Au, /* udb.tr_udb[9] */ + TRIG14_IN_UDB_TR_UDB10 = 0x00000E0Bu, /* udb.tr_udb[10] */ + TRIG14_IN_UDB_TR_UDB11 = 0x00000E0Cu, /* udb.tr_udb[11] */ + TRIG14_IN_UDB_TR_UDB12 = 0x00000E0Du, /* udb.tr_udb[12] */ + TRIG14_IN_UDB_TR_UDB13 = 0x00000E0Eu, /* udb.tr_udb[13] */ + TRIG14_IN_UDB_TR_UDB14 = 0x00000E0Fu, /* udb.tr_udb[14] */ + TRIG14_IN_UDB_TR_UDB15 = 0x00000E10u, /* udb.tr_udb[15] */ + TRIG14_IN_UDB_DSI_OUT_TR0 = 0x00000E11u, /* udb.dsi_out_tr[0] */ + TRIG14_IN_UDB_DSI_OUT_TR1 = 0x00000E12u, /* udb.dsi_out_tr[1] */ + TRIG14_IN_CPUSS_CTI_TR_OUT0 = 0x00000E13u, /* cpuss.cti_tr_out[0] */ + TRIG14_IN_CPUSS_CTI_TR_OUT1 = 0x00000E14u, /* cpuss.cti_tr_out[1] */ + TRIG14_IN_PASS_TR_SAR_OUT = 0x00000E15u, /* pass.tr_sar_out */ + TRIG14_IN_PASS_TR_CTDAC_EMPTY = 0x00000E16u, /* pass.tr_ctdac_empty */ + TRIG14_IN_PASS_DSI_CTB_CMP0 = 0x00000E17u, /* pass.dsi_ctb_cmp0 */ + TRIG14_IN_PASS_DSI_CTB_CMP1 = 0x00000E18u, /* pass.dsi_ctb_cmp1 */ + TRIG14_IN_LPCOMP_DSI_COMP0 = 0x00000E19u, /* lpcomp.dsi_comp0 */ + TRIG14_IN_LPCOMP_DSI_COMP1 = 0x00000E1Au, /* lpcomp.dsi_comp1 */ + TRIG14_IN_SCB0_TR_I2C_SCL_FILTERED = 0x00000E1Bu, /* scb[0].tr_i2c_scl_filtered */ + TRIG14_IN_SCB1_TR_I2C_SCL_FILTERED = 0x00000E1Cu, /* scb[1].tr_i2c_scl_filtered */ + TRIG14_IN_SCB2_TR_I2C_SCL_FILTERED = 0x00000E1Du, /* scb[2].tr_i2c_scl_filtered */ + TRIG14_IN_SCB3_TR_I2C_SCL_FILTERED = 0x00000E1Eu, /* scb[3].tr_i2c_scl_filtered */ + TRIG14_IN_SCB4_TR_I2C_SCL_FILTERED = 0x00000E1Fu, /* scb[4].tr_i2c_scl_filtered */ + TRIG14_IN_SCB5_TR_I2C_SCL_FILTERED = 0x00000E20u, /* scb[5].tr_i2c_scl_filtered */ + TRIG14_IN_SCB6_TR_I2C_SCL_FILTERED = 0x00000E21u, /* scb[6].tr_i2c_scl_filtered */ + TRIG14_IN_SCB7_TR_I2C_SCL_FILTERED = 0x00000E22u, /* scb[7].tr_i2c_scl_filtered */ + TRIG14_IN_SCB8_TR_I2C_SCL_FILTERED = 0x00000E23u, /* scb[8].tr_i2c_scl_filtered */ + TRIG14_IN_CPUSS_TR_FAULT0 = 0x00000E24u, /* cpuss.tr_fault[0] */ + TRIG14_IN_CPUSS_TR_FAULT1 = 0x00000E25u /* cpuss.tr_fault[1] */ +} en_trig_input_grp14_t; + +/* Trigger Group Outputs */ +/* Trigger Output Group 0 - DMA Request Assignments */ +typedef enum +{ + TRIG0_OUT_CPUSS_DW0_TR_IN0 = 0x40000000u, /* cpuss.dw0_tr_in[0] */ + TRIG0_OUT_CPUSS_DW0_TR_IN1 = 0x40000001u, /* cpuss.dw0_tr_in[1] */ + TRIG0_OUT_CPUSS_DW0_TR_IN2 = 0x40000002u, /* cpuss.dw0_tr_in[2] */ + TRIG0_OUT_CPUSS_DW0_TR_IN3 = 0x40000003u, /* cpuss.dw0_tr_in[3] */ + TRIG0_OUT_CPUSS_DW0_TR_IN4 = 0x40000004u, /* cpuss.dw0_tr_in[4] */ + TRIG0_OUT_CPUSS_DW0_TR_IN5 = 0x40000005u, /* cpuss.dw0_tr_in[5] */ + TRIG0_OUT_CPUSS_DW0_TR_IN6 = 0x40000006u, /* cpuss.dw0_tr_in[6] */ + TRIG0_OUT_CPUSS_DW0_TR_IN7 = 0x40000007u, /* cpuss.dw0_tr_in[7] */ + TRIG0_OUT_CPUSS_DW0_TR_IN8 = 0x40000008u, /* cpuss.dw0_tr_in[8] */ + TRIG0_OUT_CPUSS_DW0_TR_IN9 = 0x40000009u, /* cpuss.dw0_tr_in[9] */ + TRIG0_OUT_CPUSS_DW0_TR_IN10 = 0x4000000Au, /* cpuss.dw0_tr_in[10] */ + TRIG0_OUT_CPUSS_DW0_TR_IN11 = 0x4000000Bu, /* cpuss.dw0_tr_in[11] */ + TRIG0_OUT_CPUSS_DW0_TR_IN12 = 0x4000000Cu, /* cpuss.dw0_tr_in[12] */ + TRIG0_OUT_CPUSS_DW0_TR_IN13 = 0x4000000Du, /* cpuss.dw0_tr_in[13] */ + TRIG0_OUT_CPUSS_DW0_TR_IN14 = 0x4000000Eu, /* cpuss.dw0_tr_in[14] */ + TRIG0_OUT_CPUSS_DW0_TR_IN15 = 0x4000000Fu /* cpuss.dw0_tr_in[15] */ +} en_trig_output_grp0_t; + +/* Trigger Output Group 1 - DMA Request Assignments */ +typedef enum +{ + TRIG1_OUT_CPUSS_DW1_TR_IN0 = 0x40000100u, /* cpuss.dw1_tr_in[0] */ + TRIG1_OUT_CPUSS_DW1_TR_IN1 = 0x40000101u, /* cpuss.dw1_tr_in[1] */ + TRIG1_OUT_CPUSS_DW1_TR_IN2 = 0x40000102u, /* cpuss.dw1_tr_in[2] */ + TRIG1_OUT_CPUSS_DW1_TR_IN3 = 0x40000103u, /* cpuss.dw1_tr_in[3] */ + TRIG1_OUT_CPUSS_DW1_TR_IN4 = 0x40000104u, /* cpuss.dw1_tr_in[4] */ + TRIG1_OUT_CPUSS_DW1_TR_IN5 = 0x40000105u, /* cpuss.dw1_tr_in[5] */ + TRIG1_OUT_CPUSS_DW1_TR_IN6 = 0x40000106u, /* cpuss.dw1_tr_in[6] */ + TRIG1_OUT_CPUSS_DW1_TR_IN7 = 0x40000107u, /* cpuss.dw1_tr_in[7] */ + TRIG1_OUT_CPUSS_DW1_TR_IN8 = 0x40000108u, /* cpuss.dw1_tr_in[8] */ + TRIG1_OUT_CPUSS_DW1_TR_IN9 = 0x40000109u, /* cpuss.dw1_tr_in[9] */ + TRIG1_OUT_CPUSS_DW1_TR_IN10 = 0x4000010Au, /* cpuss.dw1_tr_in[10] */ + TRIG1_OUT_CPUSS_DW1_TR_IN11 = 0x4000010Bu, /* cpuss.dw1_tr_in[11] */ + TRIG1_OUT_CPUSS_DW1_TR_IN12 = 0x4000010Cu, /* cpuss.dw1_tr_in[12] */ + TRIG1_OUT_CPUSS_DW1_TR_IN13 = 0x4000010Du, /* cpuss.dw1_tr_in[13] */ + TRIG1_OUT_CPUSS_DW1_TR_IN14 = 0x4000010Eu, /* cpuss.dw1_tr_in[14] */ + TRIG1_OUT_CPUSS_DW1_TR_IN15 = 0x4000010Fu /* cpuss.dw1_tr_in[15] */ +} en_trig_output_grp1_t; + +/* Trigger Output Group 2 - TCPWM trigger inputs */ +typedef enum +{ + TRIG2_OUT_TCPWM0_TR_IN0 = 0x40000200u, /* tcpwm[0].tr_in[0] */ + TRIG2_OUT_TCPWM0_TR_IN1 = 0x40000201u, /* tcpwm[0].tr_in[1] */ + TRIG2_OUT_TCPWM0_TR_IN2 = 0x40000202u, /* tcpwm[0].tr_in[2] */ + TRIG2_OUT_TCPWM0_TR_IN3 = 0x40000203u, /* tcpwm[0].tr_in[3] */ + TRIG2_OUT_TCPWM0_TR_IN4 = 0x40000204u, /* tcpwm[0].tr_in[4] */ + TRIG2_OUT_TCPWM0_TR_IN5 = 0x40000205u, /* tcpwm[0].tr_in[5] */ + TRIG2_OUT_TCPWM0_TR_IN6 = 0x40000206u, /* tcpwm[0].tr_in[6] */ + TRIG2_OUT_TCPWM0_TR_IN7 = 0x40000207u, /* tcpwm[0].tr_in[7] */ + TRIG2_OUT_TCPWM0_TR_IN8 = 0x40000208u, /* tcpwm[0].tr_in[8] */ + TRIG2_OUT_TCPWM0_TR_IN9 = 0x40000209u, /* tcpwm[0].tr_in[9] */ + TRIG2_OUT_TCPWM0_TR_IN10 = 0x4000020Au, /* tcpwm[0].tr_in[10] */ + TRIG2_OUT_TCPWM0_TR_IN11 = 0x4000020Bu, /* tcpwm[0].tr_in[11] */ + TRIG2_OUT_TCPWM0_TR_IN12 = 0x4000020Cu, /* tcpwm[0].tr_in[12] */ + TRIG2_OUT_TCPWM0_TR_IN13 = 0x4000020Du /* tcpwm[0].tr_in[13] */ +} en_trig_output_grp2_t; + +/* Trigger Output Group 3 - TCPWM trigger inputs */ +typedef enum +{ + TRIG3_OUT_TCPWM1_TR_IN0 = 0x40000300u, /* tcpwm[1].tr_in[0] */ + TRIG3_OUT_TCPWM1_TR_IN1 = 0x40000301u, /* tcpwm[1].tr_in[1] */ + TRIG3_OUT_TCPWM1_TR_IN2 = 0x40000302u, /* tcpwm[1].tr_in[2] */ + TRIG3_OUT_TCPWM1_TR_IN3 = 0x40000303u, /* tcpwm[1].tr_in[3] */ + TRIG3_OUT_TCPWM1_TR_IN4 = 0x40000304u, /* tcpwm[1].tr_in[4] */ + TRIG3_OUT_TCPWM1_TR_IN5 = 0x40000305u, /* tcpwm[1].tr_in[5] */ + TRIG3_OUT_TCPWM1_TR_IN6 = 0x40000306u, /* tcpwm[1].tr_in[6] */ + TRIG3_OUT_TCPWM1_TR_IN7 = 0x40000307u, /* tcpwm[1].tr_in[7] */ + TRIG3_OUT_TCPWM1_TR_IN8 = 0x40000308u, /* tcpwm[1].tr_in[8] */ + TRIG3_OUT_TCPWM1_TR_IN9 = 0x40000309u, /* tcpwm[1].tr_in[9] */ + TRIG3_OUT_TCPWM1_TR_IN10 = 0x4000030Au, /* tcpwm[1].tr_in[10] */ + TRIG3_OUT_TCPWM1_TR_IN11 = 0x4000030Bu, /* tcpwm[1].tr_in[11] */ + TRIG3_OUT_TCPWM1_TR_IN12 = 0x4000030Cu, /* tcpwm[1].tr_in[12] */ + TRIG3_OUT_TCPWM1_TR_IN13 = 0x4000030Du /* tcpwm[1].tr_in[13] */ +} en_trig_output_grp3_t; + +/* Trigger Output Group 4 - PROFILE trigger multiplexer */ +typedef enum +{ + TRIG4_OUT_PROFILE_TR_START = 0x40000400u, /* profile.tr_start */ + TRIG4_OUT_PROFILE_TR_STOP = 0x40000401u /* profile.tr_stop */ +} en_trig_output_grp4_t; + +/* Trigger Output Group 5 - CPUSS.CTI trigger multiplexer */ +typedef enum +{ + TRIG5_OUT_CPUSS_CTI_TR_IN0 = 0x40000500u, /* cpuss.cti_tr_in[0] */ + TRIG5_OUT_CPUSS_CTI_TR_IN1 = 0x40000501u /* cpuss.cti_tr_in[1] */ +} en_trig_output_grp5_t; + +/* Trigger Output Group 6 - PASS trigger multiplexer */ +typedef enum +{ + TRIG6_OUT_PASS_TR_SAR_IN = 0x40000600u /* pass.tr_sar_in */ +} en_trig_output_grp6_t; + +/* Trigger Output Group 7 - UDB general purpose trigger multiplexer */ +typedef enum +{ + TRIG7_OUT_UDB_TR_IN0 = 0x40000700u, /* udb.tr_in[0] */ + TRIG7_OUT_UDB_TR_IN1 = 0x40000701u /* udb.tr_in[1] */ +} en_trig_output_grp7_t; + +/* Trigger Output Group 8 - Trigger multiplexer to pins */ +typedef enum +{ + TRIG8_OUT_PERI_TR_IO_OUTPUT0 = 0x40000800u, /* peri.tr_io_output[0] */ + TRIG8_OUT_PERI_TR_IO_OUTPUT1 = 0x40000801u /* peri.tr_io_output[1] */ +} en_trig_output_grp8_t; + +/* Trigger Output Group 9 - Feedback mux to USB DMA interface */ +typedef enum +{ + TRIG9_OUT_USB_DMA_BURSTEND0 = 0x40000900u, /* usb.dma_burstend[0] */ + TRIG9_OUT_USB_DMA_BURSTEND1 = 0x40000901u, /* usb.dma_burstend[1] */ + TRIG9_OUT_USB_DMA_BURSTEND2 = 0x40000902u, /* usb.dma_burstend[2] */ + TRIG9_OUT_USB_DMA_BURSTEND3 = 0x40000903u, /* usb.dma_burstend[3] */ + TRIG9_OUT_USB_DMA_BURSTEND4 = 0x40000904u, /* usb.dma_burstend[4] */ + TRIG9_OUT_USB_DMA_BURSTEND5 = 0x40000905u, /* usb.dma_burstend[5] */ + TRIG9_OUT_USB_DMA_BURSTEND6 = 0x40000906u, /* usb.dma_burstend[6] */ + TRIG9_OUT_USB_DMA_BURSTEND7 = 0x40000907u /* usb.dma_burstend[7] */ +} en_trig_output_grp9_t; + +/* Trigger Output Group 10 - Reduces 32 datawire output triggers to 8 signals, used by all except USB */ +typedef enum +{ + TRIG10_OUT_UDB_TR_DW_ACK0 = 0x40000A00u, /* udb.tr_dw_ack[0] */ + TRIG10_OUT_TR_GROUP0_INPUT1 = 0x40000A00u, /* tr_group[0].input[1] */ + TRIG10_OUT_TR_GROUP1_INPUT1 = 0x40000A00u, /* tr_group[1].input[1] */ + TRIG10_OUT_TR_GROUP2_INPUT1 = 0x40000A00u, /* tr_group[2].input[1] */ + TRIG10_OUT_TR_GROUP3_INPUT1 = 0x40000A00u, /* tr_group[3].input[1] */ + TRIG10_OUT_TR_GROUP4_INPUT1 = 0x40000A00u, /* tr_group[4].input[1] */ + TRIG10_OUT_TR_GROUP5_INPUT1 = 0x40000A00u, /* tr_group[5].input[1] */ + TRIG10_OUT_TR_GROUP6_INPUT1 = 0x40000A00u, /* tr_group[6].input[1] */ + TRIG10_OUT_TR_GROUP7_INPUT1 = 0x40000A00u, /* tr_group[7].input[1] */ + TRIG10_OUT_TR_GROUP8_INPUT1 = 0x40000A00u, /* tr_group[8].input[1] */ + TRIG10_OUT_UDB_TR_DW_ACK1 = 0x40000A01u, /* udb.tr_dw_ack[1] */ + TRIG10_OUT_TR_GROUP0_INPUT2 = 0x40000A01u, /* tr_group[0].input[2] */ + TRIG10_OUT_TR_GROUP1_INPUT2 = 0x40000A01u, /* tr_group[1].input[2] */ + TRIG10_OUT_TR_GROUP2_INPUT2 = 0x40000A01u, /* tr_group[2].input[2] */ + TRIG10_OUT_TR_GROUP3_INPUT2 = 0x40000A01u, /* tr_group[3].input[2] */ + TRIG10_OUT_TR_GROUP4_INPUT2 = 0x40000A01u, /* tr_group[4].input[2] */ + TRIG10_OUT_TR_GROUP5_INPUT2 = 0x40000A01u, /* tr_group[5].input[2] */ + TRIG10_OUT_TR_GROUP6_INPUT2 = 0x40000A01u, /* tr_group[6].input[2] */ + TRIG10_OUT_TR_GROUP7_INPUT2 = 0x40000A01u, /* tr_group[7].input[2] */ + TRIG10_OUT_TR_GROUP8_INPUT2 = 0x40000A01u, /* tr_group[8].input[2] */ + TRIG10_OUT_UDB_TR_DW_ACK2 = 0x40000A02u, /* udb.tr_dw_ack[2] */ + TRIG10_OUT_TR_GROUP0_INPUT3 = 0x40000A02u, /* tr_group[0].input[3] */ + TRIG10_OUT_TR_GROUP1_INPUT3 = 0x40000A02u, /* tr_group[1].input[3] */ + TRIG10_OUT_TR_GROUP2_INPUT3 = 0x40000A02u, /* tr_group[2].input[3] */ + TRIG10_OUT_TR_GROUP3_INPUT3 = 0x40000A02u, /* tr_group[3].input[3] */ + TRIG10_OUT_TR_GROUP4_INPUT3 = 0x40000A02u, /* tr_group[4].input[3] */ + TRIG10_OUT_TR_GROUP5_INPUT3 = 0x40000A02u, /* tr_group[5].input[3] */ + TRIG10_OUT_TR_GROUP6_INPUT3 = 0x40000A02u, /* tr_group[6].input[3] */ + TRIG10_OUT_TR_GROUP7_INPUT3 = 0x40000A02u, /* tr_group[7].input[3] */ + TRIG10_OUT_TR_GROUP8_INPUT3 = 0x40000A02u, /* tr_group[8].input[3] */ + TRIG10_OUT_UDB_TR_DW_ACK3 = 0x40000A03u, /* udb.tr_dw_ack[3] */ + TRIG10_OUT_TR_GROUP0_INPUT4 = 0x40000A03u, /* tr_group[0].input[4] */ + TRIG10_OUT_TR_GROUP1_INPUT4 = 0x40000A03u, /* tr_group[1].input[4] */ + TRIG10_OUT_TR_GROUP2_INPUT4 = 0x40000A03u, /* tr_group[2].input[4] */ + TRIG10_OUT_TR_GROUP3_INPUT4 = 0x40000A03u, /* tr_group[3].input[4] */ + TRIG10_OUT_TR_GROUP4_INPUT4 = 0x40000A03u, /* tr_group[4].input[4] */ + TRIG10_OUT_TR_GROUP5_INPUT4 = 0x40000A03u, /* tr_group[5].input[4] */ + TRIG10_OUT_TR_GROUP6_INPUT4 = 0x40000A03u, /* tr_group[6].input[4] */ + TRIG10_OUT_TR_GROUP7_INPUT4 = 0x40000A03u, /* tr_group[7].input[4] */ + TRIG10_OUT_TR_GROUP8_INPUT4 = 0x40000A03u, /* tr_group[8].input[4] */ + TRIG10_OUT_UDB_TR_DW_ACK4 = 0x40000A04u, /* udb.tr_dw_ack[4] */ + TRIG10_OUT_TR_GROUP0_INPUT5 = 0x40000A04u, /* tr_group[0].input[5] */ + TRIG10_OUT_TR_GROUP1_INPUT5 = 0x40000A04u, /* tr_group[1].input[5] */ + TRIG10_OUT_TR_GROUP2_INPUT5 = 0x40000A04u, /* tr_group[2].input[5] */ + TRIG10_OUT_TR_GROUP3_INPUT5 = 0x40000A04u, /* tr_group[3].input[5] */ + TRIG10_OUT_TR_GROUP4_INPUT5 = 0x40000A04u, /* tr_group[4].input[5] */ + TRIG10_OUT_TR_GROUP5_INPUT5 = 0x40000A04u, /* tr_group[5].input[5] */ + TRIG10_OUT_TR_GROUP6_INPUT5 = 0x40000A04u, /* tr_group[6].input[5] */ + TRIG10_OUT_TR_GROUP7_INPUT5 = 0x40000A04u, /* tr_group[7].input[5] */ + TRIG10_OUT_TR_GROUP8_INPUT5 = 0x40000A04u, /* tr_group[8].input[5] */ + TRIG10_OUT_UDB_TR_DW_ACK5 = 0x40000A05u, /* udb.tr_dw_ack[5] */ + TRIG10_OUT_TR_GROUP0_INPUT6 = 0x40000A05u, /* tr_group[0].input[6] */ + TRIG10_OUT_TR_GROUP1_INPUT6 = 0x40000A05u, /* tr_group[1].input[6] */ + TRIG10_OUT_TR_GROUP2_INPUT6 = 0x40000A05u, /* tr_group[2].input[6] */ + TRIG10_OUT_TR_GROUP3_INPUT6 = 0x40000A05u, /* tr_group[3].input[6] */ + TRIG10_OUT_TR_GROUP4_INPUT6 = 0x40000A05u, /* tr_group[4].input[6] */ + TRIG10_OUT_TR_GROUP5_INPUT6 = 0x40000A05u, /* tr_group[5].input[6] */ + TRIG10_OUT_TR_GROUP6_INPUT6 = 0x40000A05u, /* tr_group[6].input[6] */ + TRIG10_OUT_TR_GROUP7_INPUT6 = 0x40000A05u, /* tr_group[7].input[6] */ + TRIG10_OUT_TR_GROUP8_INPUT6 = 0x40000A05u, /* tr_group[8].input[6] */ + TRIG10_OUT_UDB_TR_DW_ACK6 = 0x40000A06u, /* udb.tr_dw_ack[6] */ + TRIG10_OUT_TR_GROUP0_INPUT7 = 0x40000A06u, /* tr_group[0].input[7] */ + TRIG10_OUT_TR_GROUP1_INPUT7 = 0x40000A06u, /* tr_group[1].input[7] */ + TRIG10_OUT_TR_GROUP2_INPUT7 = 0x40000A06u, /* tr_group[2].input[7] */ + TRIG10_OUT_TR_GROUP3_INPUT7 = 0x40000A06u, /* tr_group[3].input[7] */ + TRIG10_OUT_TR_GROUP4_INPUT7 = 0x40000A06u, /* tr_group[4].input[7] */ + TRIG10_OUT_TR_GROUP5_INPUT7 = 0x40000A06u, /* tr_group[5].input[7] */ + TRIG10_OUT_TR_GROUP6_INPUT7 = 0x40000A06u, /* tr_group[6].input[7] */ + TRIG10_OUT_TR_GROUP7_INPUT7 = 0x40000A06u, /* tr_group[7].input[7] */ + TRIG10_OUT_TR_GROUP8_INPUT7 = 0x40000A06u, /* tr_group[8].input[7] */ + TRIG10_OUT_UDB_TR_DW_ACK7 = 0x40000A07u, /* udb.tr_dw_ack[7] */ + TRIG10_OUT_TR_GROUP0_INPUT8 = 0x40000A07u, /* tr_group[0].input[8] */ + TRIG10_OUT_TR_GROUP1_INPUT8 = 0x40000A07u, /* tr_group[1].input[8] */ + TRIG10_OUT_TR_GROUP2_INPUT8 = 0x40000A07u, /* tr_group[2].input[8] */ + TRIG10_OUT_TR_GROUP3_INPUT8 = 0x40000A07u, /* tr_group[3].input[8] */ + TRIG10_OUT_TR_GROUP4_INPUT8 = 0x40000A07u, /* tr_group[4].input[8] */ + TRIG10_OUT_TR_GROUP5_INPUT8 = 0x40000A07u, /* tr_group[5].input[8] */ + TRIG10_OUT_TR_GROUP6_INPUT8 = 0x40000A07u, /* tr_group[6].input[8] */ + TRIG10_OUT_TR_GROUP7_INPUT8 = 0x40000A07u, /* tr_group[7].input[8] */ + TRIG10_OUT_TR_GROUP8_INPUT8 = 0x40000A07u /* tr_group[8].input[8] */ +} en_trig_output_grp10_t; + +/* Trigger Output Group 11 - Reduces 96 tcpwm output triggers to 16 signals, used by all sinks */ +typedef enum +{ + TRIG11_OUT_TR_GROUP0_INPUT9 = 0x40000B00u, /* tr_group[0].input[9] */ + TRIG11_OUT_TR_GROUP1_INPUT9 = 0x40000B00u, /* tr_group[1].input[9] */ + TRIG11_OUT_TR_GROUP2_INPUT9 = 0x40000B00u, /* tr_group[2].input[9] */ + TRIG11_OUT_TR_GROUP3_INPUT9 = 0x40000B00u, /* tr_group[3].input[9] */ + TRIG11_OUT_TR_GROUP4_INPUT9 = 0x40000B00u, /* tr_group[4].input[9] */ + TRIG11_OUT_TR_GROUP5_INPUT9 = 0x40000B00u, /* tr_group[5].input[9] */ + TRIG11_OUT_TR_GROUP6_INPUT9 = 0x40000B00u, /* tr_group[6].input[9] */ + TRIG11_OUT_TR_GROUP7_INPUT9 = 0x40000B00u, /* tr_group[7].input[9] */ + TRIG11_OUT_TR_GROUP8_INPUT9 = 0x40000B00u, /* tr_group[8].input[9] */ + TRIG11_OUT_TR_GROUP0_INPUT10 = 0x40000B01u, /* tr_group[0].input[10] */ + TRIG11_OUT_TR_GROUP1_INPUT10 = 0x40000B01u, /* tr_group[1].input[10] */ + TRIG11_OUT_TR_GROUP2_INPUT10 = 0x40000B01u, /* tr_group[2].input[10] */ + TRIG11_OUT_TR_GROUP3_INPUT10 = 0x40000B01u, /* tr_group[3].input[10] */ + TRIG11_OUT_TR_GROUP4_INPUT10 = 0x40000B01u, /* tr_group[4].input[10] */ + TRIG11_OUT_TR_GROUP5_INPUT10 = 0x40000B01u, /* tr_group[5].input[10] */ + TRIG11_OUT_TR_GROUP6_INPUT10 = 0x40000B01u, /* tr_group[6].input[10] */ + TRIG11_OUT_TR_GROUP7_INPUT10 = 0x40000B01u, /* tr_group[7].input[10] */ + TRIG11_OUT_TR_GROUP8_INPUT10 = 0x40000B01u, /* tr_group[8].input[10] */ + TRIG11_OUT_TR_GROUP0_INPUT11 = 0x40000B02u, /* tr_group[0].input[11] */ + TRIG11_OUT_TR_GROUP1_INPUT11 = 0x40000B02u, /* tr_group[1].input[11] */ + TRIG11_OUT_TR_GROUP2_INPUT11 = 0x40000B02u, /* tr_group[2].input[11] */ + TRIG11_OUT_TR_GROUP3_INPUT11 = 0x40000B02u, /* tr_group[3].input[11] */ + TRIG11_OUT_TR_GROUP4_INPUT11 = 0x40000B02u, /* tr_group[4].input[11] */ + TRIG11_OUT_TR_GROUP5_INPUT11 = 0x40000B02u, /* tr_group[5].input[11] */ + TRIG11_OUT_TR_GROUP6_INPUT11 = 0x40000B02u, /* tr_group[6].input[11] */ + TRIG11_OUT_TR_GROUP7_INPUT11 = 0x40000B02u, /* tr_group[7].input[11] */ + TRIG11_OUT_TR_GROUP8_INPUT11 = 0x40000B02u, /* tr_group[8].input[11] */ + TRIG11_OUT_TR_GROUP0_INPUT12 = 0x40000B03u, /* tr_group[0].input[12] */ + TRIG11_OUT_TR_GROUP1_INPUT12 = 0x40000B03u, /* tr_group[1].input[12] */ + TRIG11_OUT_TR_GROUP2_INPUT12 = 0x40000B03u, /* tr_group[2].input[12] */ + TRIG11_OUT_TR_GROUP3_INPUT12 = 0x40000B03u, /* tr_group[3].input[12] */ + TRIG11_OUT_TR_GROUP4_INPUT12 = 0x40000B03u, /* tr_group[4].input[12] */ + TRIG11_OUT_TR_GROUP5_INPUT12 = 0x40000B03u, /* tr_group[5].input[12] */ + TRIG11_OUT_TR_GROUP6_INPUT12 = 0x40000B03u, /* tr_group[6].input[12] */ + TRIG11_OUT_TR_GROUP7_INPUT12 = 0x40000B03u, /* tr_group[7].input[12] */ + TRIG11_OUT_TR_GROUP8_INPUT12 = 0x40000B03u, /* tr_group[8].input[12] */ + TRIG11_OUT_TR_GROUP0_INPUT13 = 0x40000B04u, /* tr_group[0].input[13] */ + TRIG11_OUT_TR_GROUP1_INPUT13 = 0x40000B04u, /* tr_group[1].input[13] */ + TRIG11_OUT_TR_GROUP2_INPUT13 = 0x40000B04u, /* tr_group[2].input[13] */ + TRIG11_OUT_TR_GROUP3_INPUT13 = 0x40000B04u, /* tr_group[3].input[13] */ + TRIG11_OUT_TR_GROUP4_INPUT13 = 0x40000B04u, /* tr_group[4].input[13] */ + TRIG11_OUT_TR_GROUP5_INPUT13 = 0x40000B04u, /* tr_group[5].input[13] */ + TRIG11_OUT_TR_GROUP6_INPUT13 = 0x40000B04u, /* tr_group[6].input[13] */ + TRIG11_OUT_TR_GROUP7_INPUT13 = 0x40000B04u, /* tr_group[7].input[13] */ + TRIG11_OUT_TR_GROUP8_INPUT13 = 0x40000B04u, /* tr_group[8].input[13] */ + TRIG11_OUT_TR_GROUP0_INPUT14 = 0x40000B05u, /* tr_group[0].input[14] */ + TRIG11_OUT_TR_GROUP1_INPUT14 = 0x40000B05u, /* tr_group[1].input[14] */ + TRIG11_OUT_TR_GROUP2_INPUT14 = 0x40000B05u, /* tr_group[2].input[14] */ + TRIG11_OUT_TR_GROUP3_INPUT14 = 0x40000B05u, /* tr_group[3].input[14] */ + TRIG11_OUT_TR_GROUP4_INPUT14 = 0x40000B05u, /* tr_group[4].input[14] */ + TRIG11_OUT_TR_GROUP5_INPUT14 = 0x40000B05u, /* tr_group[5].input[14] */ + TRIG11_OUT_TR_GROUP6_INPUT14 = 0x40000B05u, /* tr_group[6].input[14] */ + TRIG11_OUT_TR_GROUP7_INPUT14 = 0x40000B05u, /* tr_group[7].input[14] */ + TRIG11_OUT_TR_GROUP8_INPUT14 = 0x40000B05u, /* tr_group[8].input[14] */ + TRIG11_OUT_TR_GROUP0_INPUT15 = 0x40000B06u, /* tr_group[0].input[15] */ + TRIG11_OUT_TR_GROUP1_INPUT15 = 0x40000B06u, /* tr_group[1].input[15] */ + TRIG11_OUT_TR_GROUP2_INPUT15 = 0x40000B06u, /* tr_group[2].input[15] */ + TRIG11_OUT_TR_GROUP3_INPUT15 = 0x40000B06u, /* tr_group[3].input[15] */ + TRIG11_OUT_TR_GROUP4_INPUT15 = 0x40000B06u, /* tr_group[4].input[15] */ + TRIG11_OUT_TR_GROUP5_INPUT15 = 0x40000B06u, /* tr_group[5].input[15] */ + TRIG11_OUT_TR_GROUP6_INPUT15 = 0x40000B06u, /* tr_group[6].input[15] */ + TRIG11_OUT_TR_GROUP7_INPUT15 = 0x40000B06u, /* tr_group[7].input[15] */ + TRIG11_OUT_TR_GROUP8_INPUT15 = 0x40000B06u, /* tr_group[8].input[15] */ + TRIG11_OUT_TR_GROUP0_INPUT16 = 0x40000B07u, /* tr_group[0].input[16] */ + TRIG11_OUT_TR_GROUP1_INPUT16 = 0x40000B07u, /* tr_group[1].input[16] */ + TRIG11_OUT_TR_GROUP2_INPUT16 = 0x40000B07u, /* tr_group[2].input[16] */ + TRIG11_OUT_TR_GROUP3_INPUT16 = 0x40000B07u, /* tr_group[3].input[16] */ + TRIG11_OUT_TR_GROUP4_INPUT16 = 0x40000B07u, /* tr_group[4].input[16] */ + TRIG11_OUT_TR_GROUP5_INPUT16 = 0x40000B07u, /* tr_group[5].input[16] */ + TRIG11_OUT_TR_GROUP6_INPUT16 = 0x40000B07u, /* tr_group[6].input[16] */ + TRIG11_OUT_TR_GROUP7_INPUT16 = 0x40000B07u, /* tr_group[7].input[16] */ + TRIG11_OUT_TR_GROUP8_INPUT16 = 0x40000B07u, /* tr_group[8].input[16] */ + TRIG11_OUT_TR_GROUP0_INPUT17 = 0x40000B08u, /* tr_group[0].input[17] */ + TRIG11_OUT_TR_GROUP1_INPUT17 = 0x40000B08u, /* tr_group[1].input[17] */ + TRIG11_OUT_TR_GROUP2_INPUT17 = 0x40000B08u, /* tr_group[2].input[17] */ + TRIG11_OUT_TR_GROUP3_INPUT17 = 0x40000B08u, /* tr_group[3].input[17] */ + TRIG11_OUT_TR_GROUP4_INPUT17 = 0x40000B08u, /* tr_group[4].input[17] */ + TRIG11_OUT_TR_GROUP5_INPUT17 = 0x40000B08u, /* tr_group[5].input[17] */ + TRIG11_OUT_TR_GROUP6_INPUT17 = 0x40000B08u, /* tr_group[6].input[17] */ + TRIG11_OUT_TR_GROUP7_INPUT17 = 0x40000B08u, /* tr_group[7].input[17] */ + TRIG11_OUT_TR_GROUP8_INPUT17 = 0x40000B08u, /* tr_group[8].input[17] */ + TRIG11_OUT_TR_GROUP0_INPUT18 = 0x40000B09u, /* tr_group[0].input[18] */ + TRIG11_OUT_TR_GROUP1_INPUT18 = 0x40000B09u, /* tr_group[1].input[18] */ + TRIG11_OUT_TR_GROUP2_INPUT18 = 0x40000B09u, /* tr_group[2].input[18] */ + TRIG11_OUT_TR_GROUP3_INPUT18 = 0x40000B09u, /* tr_group[3].input[18] */ + TRIG11_OUT_TR_GROUP4_INPUT18 = 0x40000B09u, /* tr_group[4].input[18] */ + TRIG11_OUT_TR_GROUP5_INPUT18 = 0x40000B09u, /* tr_group[5].input[18] */ + TRIG11_OUT_TR_GROUP6_INPUT18 = 0x40000B09u, /* tr_group[6].input[18] */ + TRIG11_OUT_TR_GROUP7_INPUT18 = 0x40000B09u, /* tr_group[7].input[18] */ + TRIG11_OUT_TR_GROUP8_INPUT18 = 0x40000B09u, /* tr_group[8].input[18] */ + TRIG11_OUT_TR_GROUP0_INPUT19 = 0x40000B0Au, /* tr_group[0].input[19] */ + TRIG11_OUT_TR_GROUP1_INPUT19 = 0x40000B0Au, /* tr_group[1].input[19] */ + TRIG11_OUT_TR_GROUP2_INPUT19 = 0x40000B0Au, /* tr_group[2].input[19] */ + TRIG11_OUT_TR_GROUP3_INPUT19 = 0x40000B0Au, /* tr_group[3].input[19] */ + TRIG11_OUT_TR_GROUP4_INPUT19 = 0x40000B0Au, /* tr_group[4].input[19] */ + TRIG11_OUT_TR_GROUP5_INPUT19 = 0x40000B0Au, /* tr_group[5].input[19] */ + TRIG11_OUT_TR_GROUP6_INPUT19 = 0x40000B0Au, /* tr_group[6].input[19] */ + TRIG11_OUT_TR_GROUP7_INPUT19 = 0x40000B0Au, /* tr_group[7].input[19] */ + TRIG11_OUT_TR_GROUP8_INPUT19 = 0x40000B0Au, /* tr_group[8].input[19] */ + TRIG11_OUT_TR_GROUP0_INPUT20 = 0x40000B0Bu, /* tr_group[0].input[20] */ + TRIG11_OUT_TR_GROUP1_INPUT20 = 0x40000B0Bu, /* tr_group[1].input[20] */ + TRIG11_OUT_TR_GROUP2_INPUT20 = 0x40000B0Bu, /* tr_group[2].input[20] */ + TRIG11_OUT_TR_GROUP3_INPUT20 = 0x40000B0Bu, /* tr_group[3].input[20] */ + TRIG11_OUT_TR_GROUP4_INPUT20 = 0x40000B0Bu, /* tr_group[4].input[20] */ + TRIG11_OUT_TR_GROUP5_INPUT20 = 0x40000B0Bu, /* tr_group[5].input[20] */ + TRIG11_OUT_TR_GROUP6_INPUT20 = 0x40000B0Bu, /* tr_group[6].input[20] */ + TRIG11_OUT_TR_GROUP7_INPUT20 = 0x40000B0Bu, /* tr_group[7].input[20] */ + TRIG11_OUT_TR_GROUP8_INPUT20 = 0x40000B0Bu, /* tr_group[8].input[20] */ + TRIG11_OUT_TR_GROUP0_INPUT21 = 0x40000B0Cu, /* tr_group[0].input[21] */ + TRIG11_OUT_TR_GROUP1_INPUT21 = 0x40000B0Cu, /* tr_group[1].input[21] */ + TRIG11_OUT_TR_GROUP2_INPUT21 = 0x40000B0Cu, /* tr_group[2].input[21] */ + TRIG11_OUT_TR_GROUP3_INPUT21 = 0x40000B0Cu, /* tr_group[3].input[21] */ + TRIG11_OUT_TR_GROUP4_INPUT21 = 0x40000B0Cu, /* tr_group[4].input[21] */ + TRIG11_OUT_TR_GROUP5_INPUT21 = 0x40000B0Cu, /* tr_group[5].input[21] */ + TRIG11_OUT_TR_GROUP6_INPUT21 = 0x40000B0Cu, /* tr_group[6].input[21] */ + TRIG11_OUT_TR_GROUP7_INPUT21 = 0x40000B0Cu, /* tr_group[7].input[21] */ + TRIG11_OUT_TR_GROUP8_INPUT21 = 0x40000B0Cu, /* tr_group[8].input[21] */ + TRIG11_OUT_TR_GROUP0_INPUT22 = 0x40000B0Du, /* tr_group[0].input[22] */ + TRIG11_OUT_TR_GROUP1_INPUT22 = 0x40000B0Du, /* tr_group[1].input[22] */ + TRIG11_OUT_TR_GROUP2_INPUT22 = 0x40000B0Du, /* tr_group[2].input[22] */ + TRIG11_OUT_TR_GROUP3_INPUT22 = 0x40000B0Du, /* tr_group[3].input[22] */ + TRIG11_OUT_TR_GROUP4_INPUT22 = 0x40000B0Du, /* tr_group[4].input[22] */ + TRIG11_OUT_TR_GROUP5_INPUT22 = 0x40000B0Du, /* tr_group[5].input[22] */ + TRIG11_OUT_TR_GROUP6_INPUT22 = 0x40000B0Du, /* tr_group[6].input[22] */ + TRIG11_OUT_TR_GROUP7_INPUT22 = 0x40000B0Du, /* tr_group[7].input[22] */ + TRIG11_OUT_TR_GROUP8_INPUT22 = 0x40000B0Du, /* tr_group[8].input[22] */ + TRIG11_OUT_TR_GROUP0_INPUT23 = 0x40000B0Eu, /* tr_group[0].input[23] */ + TRIG11_OUT_TR_GROUP1_INPUT23 = 0x40000B0Eu, /* tr_group[1].input[23] */ + TRIG11_OUT_TR_GROUP2_INPUT23 = 0x40000B0Eu, /* tr_group[2].input[23] */ + TRIG11_OUT_TR_GROUP3_INPUT23 = 0x40000B0Eu, /* tr_group[3].input[23] */ + TRIG11_OUT_TR_GROUP4_INPUT23 = 0x40000B0Eu, /* tr_group[4].input[23] */ + TRIG11_OUT_TR_GROUP5_INPUT23 = 0x40000B0Eu, /* tr_group[5].input[23] */ + TRIG11_OUT_TR_GROUP6_INPUT23 = 0x40000B0Eu, /* tr_group[6].input[23] */ + TRIG11_OUT_TR_GROUP7_INPUT23 = 0x40000B0Eu, /* tr_group[7].input[23] */ + TRIG11_OUT_TR_GROUP8_INPUT23 = 0x40000B0Eu, /* tr_group[8].input[23] */ + TRIG11_OUT_TR_GROUP0_INPUT24 = 0x40000B0Fu, /* tr_group[0].input[24] */ + TRIG11_OUT_TR_GROUP1_INPUT24 = 0x40000B0Fu, /* tr_group[1].input[24] */ + TRIG11_OUT_TR_GROUP2_INPUT24 = 0x40000B0Fu, /* tr_group[2].input[24] */ + TRIG11_OUT_TR_GROUP3_INPUT24 = 0x40000B0Fu, /* tr_group[3].input[24] */ + TRIG11_OUT_TR_GROUP4_INPUT24 = 0x40000B0Fu, /* tr_group[4].input[24] */ + TRIG11_OUT_TR_GROUP5_INPUT24 = 0x40000B0Fu, /* tr_group[5].input[24] */ + TRIG11_OUT_TR_GROUP6_INPUT24 = 0x40000B0Fu, /* tr_group[6].input[24] */ + TRIG11_OUT_TR_GROUP7_INPUT24 = 0x40000B0Fu, /* tr_group[7].input[24] */ + TRIG11_OUT_TR_GROUP8_INPUT24 = 0x40000B0Fu /* tr_group[8].input[24] */ +} en_trig_output_grp11_t; + +/* Trigger Output Group 12 - Reduces 28 pin input signals to 10 triggers used by all sinks */ +typedef enum +{ + TRIG12_OUT_TR_GROUP2_INPUT25 = 0x40000C00u, /* tr_group[2].input[25] */ + TRIG12_OUT_TR_GROUP3_INPUT25 = 0x40000C00u, /* tr_group[3].input[25] */ + TRIG12_OUT_TR_GROUP4_INPUT25 = 0x40000C00u, /* tr_group[4].input[25] */ + TRIG12_OUT_TR_GROUP5_INPUT25 = 0x40000C00u, /* tr_group[5].input[25] */ + TRIG12_OUT_TR_GROUP6_INPUT25 = 0x40000C00u, /* tr_group[6].input[25] */ + TRIG12_OUT_TR_GROUP7_INPUT25 = 0x40000C00u, /* tr_group[7].input[25] */ + TRIG12_OUT_TR_GROUP8_INPUT25 = 0x40000C00u, /* tr_group[8].input[25] */ + TRIG12_OUT_TR_GROUP2_INPUT26 = 0x40000C01u, /* tr_group[2].input[26] */ + TRIG12_OUT_TR_GROUP3_INPUT26 = 0x40000C01u, /* tr_group[3].input[26] */ + TRIG12_OUT_TR_GROUP4_INPUT26 = 0x40000C01u, /* tr_group[4].input[26] */ + TRIG12_OUT_TR_GROUP5_INPUT26 = 0x40000C01u, /* tr_group[5].input[26] */ + TRIG12_OUT_TR_GROUP6_INPUT26 = 0x40000C01u, /* tr_group[6].input[26] */ + TRIG12_OUT_TR_GROUP7_INPUT26 = 0x40000C01u, /* tr_group[7].input[26] */ + TRIG12_OUT_TR_GROUP8_INPUT26 = 0x40000C01u, /* tr_group[8].input[26] */ + TRIG12_OUT_TR_GROUP2_INPUT27 = 0x40000C02u, /* tr_group[2].input[27] */ + TRIG12_OUT_TR_GROUP3_INPUT27 = 0x40000C02u, /* tr_group[3].input[27] */ + TRIG12_OUT_TR_GROUP4_INPUT27 = 0x40000C02u, /* tr_group[4].input[27] */ + TRIG12_OUT_TR_GROUP5_INPUT27 = 0x40000C02u, /* tr_group[5].input[27] */ + TRIG12_OUT_TR_GROUP6_INPUT27 = 0x40000C02u, /* tr_group[6].input[27] */ + TRIG12_OUT_TR_GROUP7_INPUT27 = 0x40000C02u, /* tr_group[7].input[27] */ + TRIG12_OUT_TR_GROUP8_INPUT27 = 0x40000C02u, /* tr_group[8].input[27] */ + TRIG12_OUT_TR_GROUP2_INPUT28 = 0x40000C03u, /* tr_group[2].input[28] */ + TRIG12_OUT_TR_GROUP3_INPUT28 = 0x40000C03u, /* tr_group[3].input[28] */ + TRIG12_OUT_TR_GROUP4_INPUT28 = 0x40000C03u, /* tr_group[4].input[28] */ + TRIG12_OUT_TR_GROUP5_INPUT28 = 0x40000C03u, /* tr_group[5].input[28] */ + TRIG12_OUT_TR_GROUP6_INPUT28 = 0x40000C03u, /* tr_group[6].input[28] */ + TRIG12_OUT_TR_GROUP7_INPUT28 = 0x40000C03u, /* tr_group[7].input[28] */ + TRIG12_OUT_TR_GROUP8_INPUT28 = 0x40000C03u, /* tr_group[8].input[28] */ + TRIG12_OUT_TR_GROUP2_INPUT29 = 0x40000C04u, /* tr_group[2].input[29] */ + TRIG12_OUT_TR_GROUP3_INPUT29 = 0x40000C04u, /* tr_group[3].input[29] */ + TRIG12_OUT_TR_GROUP4_INPUT29 = 0x40000C04u, /* tr_group[4].input[29] */ + TRIG12_OUT_TR_GROUP5_INPUT29 = 0x40000C04u, /* tr_group[5].input[29] */ + TRIG12_OUT_TR_GROUP6_INPUT29 = 0x40000C04u, /* tr_group[6].input[29] */ + TRIG12_OUT_TR_GROUP7_INPUT29 = 0x40000C04u, /* tr_group[7].input[29] */ + TRIG12_OUT_TR_GROUP8_INPUT29 = 0x40000C04u, /* tr_group[8].input[29] */ + TRIG12_OUT_TR_GROUP2_INPUT30 = 0x40000C05u, /* tr_group[2].input[30] */ + TRIG12_OUT_TR_GROUP3_INPUT30 = 0x40000C05u, /* tr_group[3].input[30] */ + TRIG12_OUT_TR_GROUP4_INPUT30 = 0x40000C05u, /* tr_group[4].input[30] */ + TRIG12_OUT_TR_GROUP5_INPUT30 = 0x40000C05u, /* tr_group[5].input[30] */ + TRIG12_OUT_TR_GROUP6_INPUT30 = 0x40000C05u, /* tr_group[6].input[30] */ + TRIG12_OUT_TR_GROUP7_INPUT30 = 0x40000C05u, /* tr_group[7].input[30] */ + TRIG12_OUT_TR_GROUP8_INPUT30 = 0x40000C05u, /* tr_group[8].input[30] */ + TRIG12_OUT_TR_GROUP2_INPUT31 = 0x40000C06u, /* tr_group[2].input[31] */ + TRIG12_OUT_TR_GROUP3_INPUT31 = 0x40000C06u, /* tr_group[3].input[31] */ + TRIG12_OUT_TR_GROUP4_INPUT31 = 0x40000C06u, /* tr_group[4].input[31] */ + TRIG12_OUT_TR_GROUP5_INPUT31 = 0x40000C06u, /* tr_group[5].input[31] */ + TRIG12_OUT_TR_GROUP6_INPUT31 = 0x40000C06u, /* tr_group[6].input[31] */ + TRIG12_OUT_TR_GROUP7_INPUT31 = 0x40000C06u, /* tr_group[7].input[31] */ + TRIG12_OUT_TR_GROUP8_INPUT31 = 0x40000C06u, /* tr_group[8].input[31] */ + TRIG12_OUT_TR_GROUP2_INPUT32 = 0x40000C07u, /* tr_group[2].input[32] */ + TRIG12_OUT_TR_GROUP3_INPUT32 = 0x40000C07u, /* tr_group[3].input[32] */ + TRIG12_OUT_TR_GROUP4_INPUT32 = 0x40000C07u, /* tr_group[4].input[32] */ + TRIG12_OUT_TR_GROUP5_INPUT32 = 0x40000C07u, /* tr_group[5].input[32] */ + TRIG12_OUT_TR_GROUP6_INPUT32 = 0x40000C07u, /* tr_group[6].input[32] */ + TRIG12_OUT_TR_GROUP7_INPUT32 = 0x40000C07u, /* tr_group[7].input[32] */ + TRIG12_OUT_TR_GROUP8_INPUT32 = 0x40000C07u, /* tr_group[8].input[32] */ + TRIG12_OUT_TR_GROUP0_INPUT25 = 0x40000C08u, /* tr_group[0].input[25] */ + TRIG12_OUT_TR_GROUP1_INPUT25 = 0x40000C08u, /* tr_group[1].input[25] */ + TRIG12_OUT_TR_GROUP0_INPUT26 = 0x40000C09u, /* tr_group[0].input[26] */ + TRIG12_OUT_TR_GROUP1_INPUT26 = 0x40000C09u /* tr_group[1].input[26] */ +} en_trig_output_grp12_t; + +/* Trigger Output Group 13 - Reduces DMA requests to 16+2 outputs used by all sinks */ +typedef enum +{ + TRIG13_OUT_TR_GROUP0_INPUT27 = 0x40000D00u, /* tr_group[0].input[27] */ + TRIG13_OUT_TR_GROUP1_INPUT27 = 0x40000D00u, /* tr_group[1].input[27] */ + TRIG13_OUT_TR_GROUP0_INPUT28 = 0x40000D01u, /* tr_group[0].input[28] */ + TRIG13_OUT_TR_GROUP1_INPUT28 = 0x40000D01u, /* tr_group[1].input[28] */ + TRIG13_OUT_TR_GROUP0_INPUT29 = 0x40000D02u, /* tr_group[0].input[29] */ + TRIG13_OUT_TR_GROUP1_INPUT29 = 0x40000D02u, /* tr_group[1].input[29] */ + TRIG13_OUT_TR_GROUP0_INPUT30 = 0x40000D03u, /* tr_group[0].input[30] */ + TRIG13_OUT_TR_GROUP1_INPUT30 = 0x40000D03u, /* tr_group[1].input[30] */ + TRIG13_OUT_TR_GROUP0_INPUT31 = 0x40000D04u, /* tr_group[0].input[31] */ + TRIG13_OUT_TR_GROUP1_INPUT31 = 0x40000D04u, /* tr_group[1].input[31] */ + TRIG13_OUT_TR_GROUP0_INPUT32 = 0x40000D05u, /* tr_group[0].input[32] */ + TRIG13_OUT_TR_GROUP1_INPUT32 = 0x40000D05u, /* tr_group[1].input[32] */ + TRIG13_OUT_TR_GROUP0_INPUT33 = 0x40000D06u, /* tr_group[0].input[33] */ + TRIG13_OUT_TR_GROUP1_INPUT33 = 0x40000D06u, /* tr_group[1].input[33] */ + TRIG13_OUT_TR_GROUP0_INPUT34 = 0x40000D07u, /* tr_group[0].input[34] */ + TRIG13_OUT_TR_GROUP1_INPUT34 = 0x40000D07u, /* tr_group[1].input[34] */ + TRIG13_OUT_TR_GROUP0_INPUT35 = 0x40000D08u, /* tr_group[0].input[35] */ + TRIG13_OUT_TR_GROUP1_INPUT35 = 0x40000D08u, /* tr_group[1].input[35] */ + TRIG13_OUT_TR_GROUP0_INPUT36 = 0x40000D09u, /* tr_group[0].input[36] */ + TRIG13_OUT_TR_GROUP1_INPUT36 = 0x40000D09u, /* tr_group[1].input[36] */ + TRIG13_OUT_TR_GROUP0_INPUT37 = 0x40000D0Au, /* tr_group[0].input[37] */ + TRIG13_OUT_TR_GROUP1_INPUT37 = 0x40000D0Au, /* tr_group[1].input[37] */ + TRIG13_OUT_TR_GROUP0_INPUT38 = 0x40000D0Bu, /* tr_group[0].input[38] */ + TRIG13_OUT_TR_GROUP1_INPUT38 = 0x40000D0Bu, /* tr_group[1].input[38] */ + TRIG13_OUT_TR_GROUP0_INPUT39 = 0x40000D0Cu, /* tr_group[0].input[39] */ + TRIG13_OUT_TR_GROUP1_INPUT39 = 0x40000D0Cu, /* tr_group[1].input[39] */ + TRIG13_OUT_TR_GROUP0_INPUT40 = 0x40000D0Du, /* tr_group[0].input[40] */ + TRIG13_OUT_TR_GROUP1_INPUT40 = 0x40000D0Du, /* tr_group[1].input[40] */ + TRIG13_OUT_TR_GROUP0_INPUT41 = 0x40000D0Eu, /* tr_group[0].input[41] */ + TRIG13_OUT_TR_GROUP1_INPUT41 = 0x40000D0Eu, /* tr_group[1].input[41] */ + TRIG13_OUT_TR_GROUP0_INPUT42 = 0x40000D0Fu, /* tr_group[0].input[42] */ + TRIG13_OUT_TR_GROUP1_INPUT42 = 0x40000D0Fu, /* tr_group[1].input[42] */ + TRIG13_OUT_TR_GROUP2_INPUT33 = 0x40000D10u, /* tr_group[2].input[33] */ + TRIG13_OUT_TR_GROUP3_INPUT33 = 0x40000D10u, /* tr_group[3].input[33] */ + TRIG13_OUT_TR_GROUP4_INPUT33 = 0x40000D10u, /* tr_group[4].input[33] */ + TRIG13_OUT_TR_GROUP5_INPUT33 = 0x40000D10u, /* tr_group[5].input[33] */ + TRIG13_OUT_TR_GROUP6_INPUT33 = 0x40000D10u, /* tr_group[6].input[33] */ + TRIG13_OUT_TR_GROUP7_INPUT33 = 0x40000D10u, /* tr_group[7].input[33] */ + TRIG13_OUT_TR_GROUP8_INPUT33 = 0x40000D10u, /* tr_group[8].input[33] */ + TRIG13_OUT_TR_GROUP2_INPUT34 = 0x40000D11u, /* tr_group[2].input[34] */ + TRIG13_OUT_TR_GROUP3_INPUT34 = 0x40000D11u, /* tr_group[3].input[34] */ + TRIG13_OUT_TR_GROUP4_INPUT34 = 0x40000D11u, /* tr_group[4].input[34] */ + TRIG13_OUT_TR_GROUP5_INPUT34 = 0x40000D11u, /* tr_group[5].input[34] */ + TRIG13_OUT_TR_GROUP6_INPUT34 = 0x40000D11u, /* tr_group[6].input[34] */ + TRIG13_OUT_TR_GROUP7_INPUT34 = 0x40000D11u, /* tr_group[7].input[34] */ + TRIG13_OUT_TR_GROUP8_INPUT34 = 0x40000D11u /* tr_group[8].input[34] */ +} en_trig_output_grp13_t; + +/* Trigger Output Group 14 - Reduces general purpose trigger inputs to 8+8 outputs used by all sinks */ +typedef enum +{ + TRIG14_OUT_TR_GROUP0_INPUT43 = 0x40000E00u, /* tr_group[0].input[43] */ + TRIG14_OUT_TR_GROUP1_INPUT43 = 0x40000E00u, /* tr_group[1].input[43] */ + TRIG14_OUT_TR_GROUP0_INPUT44 = 0x40000E01u, /* tr_group[0].input[44] */ + TRIG14_OUT_TR_GROUP1_INPUT44 = 0x40000E01u, /* tr_group[1].input[44] */ + TRIG14_OUT_TR_GROUP0_INPUT45 = 0x40000E02u, /* tr_group[0].input[45] */ + TRIG14_OUT_TR_GROUP1_INPUT45 = 0x40000E02u, /* tr_group[1].input[45] */ + TRIG14_OUT_TR_GROUP0_INPUT46 = 0x40000E03u, /* tr_group[0].input[46] */ + TRIG14_OUT_TR_GROUP1_INPUT46 = 0x40000E03u, /* tr_group[1].input[46] */ + TRIG14_OUT_TR_GROUP0_INPUT47 = 0x40000E04u, /* tr_group[0].input[47] */ + TRIG14_OUT_TR_GROUP1_INPUT47 = 0x40000E04u, /* tr_group[1].input[47] */ + TRIG14_OUT_TR_GROUP0_INPUT48 = 0x40000E05u, /* tr_group[0].input[48] */ + TRIG14_OUT_TR_GROUP1_INPUT48 = 0x40000E05u, /* tr_group[1].input[48] */ + TRIG14_OUT_TR_GROUP0_INPUT49 = 0x40000E06u, /* tr_group[0].input[49] */ + TRIG14_OUT_TR_GROUP1_INPUT49 = 0x40000E06u, /* tr_group[1].input[49] */ + TRIG14_OUT_TR_GROUP0_INPUT50 = 0x40000E07u, /* tr_group[0].input[50] */ + TRIG14_OUT_TR_GROUP1_INPUT50 = 0x40000E07u, /* tr_group[1].input[50] */ + TRIG14_OUT_TR_GROUP2_INPUT35 = 0x40000E08u, /* tr_group[2].input[35] */ + TRIG14_OUT_TR_GROUP3_INPUT35 = 0x40000E08u, /* tr_group[3].input[35] */ + TRIG14_OUT_TR_GROUP4_INPUT35 = 0x40000E08u, /* tr_group[4].input[35] */ + TRIG14_OUT_TR_GROUP5_INPUT35 = 0x40000E08u, /* tr_group[5].input[35] */ + TRIG14_OUT_TR_GROUP6_INPUT35 = 0x40000E08u, /* tr_group[6].input[35] */ + TRIG14_OUT_TR_GROUP7_INPUT35 = 0x40000E08u, /* tr_group[7].input[35] */ + TRIG14_OUT_TR_GROUP8_INPUT35 = 0x40000E08u, /* tr_group[8].input[35] */ + TRIG14_OUT_TR_GROUP2_INPUT36 = 0x40000E09u, /* tr_group[2].input[36] */ + TRIG14_OUT_TR_GROUP3_INPUT36 = 0x40000E09u, /* tr_group[3].input[36] */ + TRIG14_OUT_TR_GROUP4_INPUT36 = 0x40000E09u, /* tr_group[4].input[36] */ + TRIG14_OUT_TR_GROUP5_INPUT36 = 0x40000E09u, /* tr_group[5].input[36] */ + TRIG14_OUT_TR_GROUP6_INPUT36 = 0x40000E09u, /* tr_group[6].input[36] */ + TRIG14_OUT_TR_GROUP7_INPUT36 = 0x40000E09u, /* tr_group[7].input[36] */ + TRIG14_OUT_TR_GROUP8_INPUT36 = 0x40000E09u, /* tr_group[8].input[36] */ + TRIG14_OUT_TR_GROUP2_INPUT37 = 0x40000E0Au, /* tr_group[2].input[37] */ + TRIG14_OUT_TR_GROUP3_INPUT37 = 0x40000E0Au, /* tr_group[3].input[37] */ + TRIG14_OUT_TR_GROUP4_INPUT37 = 0x40000E0Au, /* tr_group[4].input[37] */ + TRIG14_OUT_TR_GROUP5_INPUT37 = 0x40000E0Au, /* tr_group[5].input[37] */ + TRIG14_OUT_TR_GROUP6_INPUT37 = 0x40000E0Au, /* tr_group[6].input[37] */ + TRIG14_OUT_TR_GROUP7_INPUT37 = 0x40000E0Au, /* tr_group[7].input[37] */ + TRIG14_OUT_TR_GROUP8_INPUT37 = 0x40000E0Au, /* tr_group[8].input[37] */ + TRIG14_OUT_TR_GROUP2_INPUT38 = 0x40000E0Bu, /* tr_group[2].input[38] */ + TRIG14_OUT_TR_GROUP3_INPUT38 = 0x40000E0Bu, /* tr_group[3].input[38] */ + TRIG14_OUT_TR_GROUP4_INPUT38 = 0x40000E0Bu, /* tr_group[4].input[38] */ + TRIG14_OUT_TR_GROUP5_INPUT38 = 0x40000E0Bu, /* tr_group[5].input[38] */ + TRIG14_OUT_TR_GROUP6_INPUT38 = 0x40000E0Bu, /* tr_group[6].input[38] */ + TRIG14_OUT_TR_GROUP7_INPUT38 = 0x40000E0Bu, /* tr_group[7].input[38] */ + TRIG14_OUT_TR_GROUP8_INPUT38 = 0x40000E0Bu, /* tr_group[8].input[38] */ + TRIG14_OUT_TR_GROUP2_INPUT39 = 0x40000E0Cu, /* tr_group[2].input[39] */ + TRIG14_OUT_TR_GROUP3_INPUT39 = 0x40000E0Cu, /* tr_group[3].input[39] */ + TRIG14_OUT_TR_GROUP4_INPUT39 = 0x40000E0Cu, /* tr_group[4].input[39] */ + TRIG14_OUT_TR_GROUP5_INPUT39 = 0x40000E0Cu, /* tr_group[5].input[39] */ + TRIG14_OUT_TR_GROUP6_INPUT39 = 0x40000E0Cu, /* tr_group[6].input[39] */ + TRIG14_OUT_TR_GROUP7_INPUT39 = 0x40000E0Cu, /* tr_group[7].input[39] */ + TRIG14_OUT_TR_GROUP8_INPUT39 = 0x40000E0Cu, /* tr_group[8].input[39] */ + TRIG14_OUT_TR_GROUP2_INPUT40 = 0x40000E0Du, /* tr_group[2].input[40] */ + TRIG14_OUT_TR_GROUP3_INPUT40 = 0x40000E0Du, /* tr_group[3].input[40] */ + TRIG14_OUT_TR_GROUP4_INPUT40 = 0x40000E0Du, /* tr_group[4].input[40] */ + TRIG14_OUT_TR_GROUP5_INPUT40 = 0x40000E0Du, /* tr_group[5].input[40] */ + TRIG14_OUT_TR_GROUP6_INPUT40 = 0x40000E0Du, /* tr_group[6].input[40] */ + TRIG14_OUT_TR_GROUP7_INPUT40 = 0x40000E0Du, /* tr_group[7].input[40] */ + TRIG14_OUT_TR_GROUP8_INPUT40 = 0x40000E0Du, /* tr_group[8].input[40] */ + TRIG14_OUT_TR_GROUP2_INPUT41 = 0x40000E0Eu, /* tr_group[2].input[41] */ + TRIG14_OUT_TR_GROUP3_INPUT41 = 0x40000E0Eu, /* tr_group[3].input[41] */ + TRIG14_OUT_TR_GROUP4_INPUT41 = 0x40000E0Eu, /* tr_group[4].input[41] */ + TRIG14_OUT_TR_GROUP5_INPUT41 = 0x40000E0Eu, /* tr_group[5].input[41] */ + TRIG14_OUT_TR_GROUP6_INPUT41 = 0x40000E0Eu, /* tr_group[6].input[41] */ + TRIG14_OUT_TR_GROUP7_INPUT41 = 0x40000E0Eu, /* tr_group[7].input[41] */ + TRIG14_OUT_TR_GROUP8_INPUT41 = 0x40000E0Eu, /* tr_group[8].input[41] */ + TRIG14_OUT_TR_GROUP2_INPUT42 = 0x40000E0Fu, /* tr_group[2].input[42] */ + TRIG14_OUT_TR_GROUP3_INPUT42 = 0x40000E0Fu, /* tr_group[3].input[42] */ + TRIG14_OUT_TR_GROUP4_INPUT42 = 0x40000E0Fu, /* tr_group[4].input[42] */ + TRIG14_OUT_TR_GROUP5_INPUT42 = 0x40000E0Fu, /* tr_group[5].input[42] */ + TRIG14_OUT_TR_GROUP6_INPUT42 = 0x40000E0Fu, /* tr_group[6].input[42] */ + TRIG14_OUT_TR_GROUP7_INPUT42 = 0x40000E0Fu, /* tr_group[7].input[42] */ + TRIG14_OUT_TR_GROUP8_INPUT42 = 0x40000E0Fu /* tr_group[8].input[42] */ +} en_trig_output_grp14_t; + +/* Level or edge detection setting for a trigger mux */ +typedef enum +{ + /* The trigger is a simple level output */ + TRIGGER_TYPE_LEVEL = 0u, + /* The trigger is synchronized to the consumer blocks clock + and a two cycle pulse is generated on this clock */ + TRIGGER_TYPE_EDGE = 1u +} en_trig_type_t; + +/* Trigger Type Defines */ +/* TCPWM Trigger Types */ +#define TRIGGER_TYPE_TCPWM_LINE TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_TCPWM_LINE_COMPL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_TCPWM_TR_IN__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_TCPWM_TR_IN__EDGE TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_TCPWM_TR_OVERFLOW TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_TCPWM_TR_COMPARE_MATCH TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_TCPWM_TR_UNDERFLOW TRIGGER_TYPE_EDGE +/* CSD Trigger Types */ +#define TRIGGER_TYPE_CSD_DSI_SAMPLE_OUT TRIGGER_TYPE_EDGE +/* SCB Trigger Types */ +#define TRIGGER_TYPE_SCB_TR_TX_REQ TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_SCB_TR_RX_REQ TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_SCB_TR_I2C_SCL_FILTERED TRIGGER_TYPE_LEVEL +/* PERI Trigger Types */ +#define TRIGGER_TYPE_PERI_TR_IO_INPUT__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_PERI_TR_IO_INPUT__EDGE TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_PERI_TR_IO_OUTPUT__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_PERI_TR_IO_OUTPUT__EDGE TRIGGER_TYPE_EDGE +/* CPUSS Trigger Types */ +#define TRIGGER_TYPE_CPUSS_DW0_TR_IN__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_CPUSS_DW0_TR_IN__EDGE TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_CPUSS_DW1_TR_IN__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_CPUSS_DW1_TR_IN__EDGE TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_CPUSS_CTI_TR_IN TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_CPUSS_DW0_TR_OUT TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_CPUSS_DW1_TR_OUT TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_CPUSS_CTI_TR_OUT TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_CPUSS_TR_FAULT TRIGGER_TYPE_EDGE +/* AUDIOSS Trigger Types */ +#define TRIGGER_TYPE_AUDIOSS_TR_PDM_RX_REQ TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_AUDIOSS_TR_I2S_TX_REQ TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_AUDIOSS_TR_I2S_RX_REQ TRIGGER_TYPE_LEVEL +/* LPCOMP Trigger Types */ +#define TRIGGER_TYPE_LPCOMP_DSI_COMP0 TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_LPCOMP_DSI_COMP1 TRIGGER_TYPE_LEVEL +/* PASS Trigger Types */ +#define TRIGGER_TYPE_PASS_DSI_CTB_CMP0__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_PASS_DSI_CTB_CMP0__EDGE TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_PASS_DSI_CTB_CMP1__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_PASS_DSI_CTB_CMP1__EDGE TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_PASS_TR_SAR_IN__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_PASS_TR_SAR_IN__EDGE TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_PASS_TR_SAR_OUT TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_PASS_TR_CTDAC_EMPTY TRIGGER_TYPE_EDGE +/* SMIF Trigger Types */ +#define TRIGGER_TYPE_SMIF_TR_TX_REQ TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_SMIF_TR_RX_REQ TRIGGER_TYPE_LEVEL +/* USB Trigger Types */ +#define TRIGGER_TYPE_USB_DMA_BURSTEND TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_USB_DMA_REQ TRIGGER_TYPE_EDGE +/* UDB Trigger Types */ +#define TRIGGER_TYPE_UDB_TR_IN__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_UDB_TR_IN__EDGE TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_UDB_TR_DW_ACK__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_UDB_TR_DW_ACK__EDGE TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_UDB_TR_UDB__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_UDB_TR_UDB__EDGE TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_UDB_DSI_OUT_TR__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_UDB_DSI_OUT_TR__EDGE TRIGGER_TYPE_EDGE +/* PROFILE Trigger Types */ +#define TRIGGER_TYPE_PROFILE_TR_START TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_PROFILE_TR_STOP TRIGGER_TYPE_EDGE +/* TR_GROUP Trigger Types */ +#define TRIGGER_TYPE_TR_GROUP_OUTPUT__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_TR_GROUP_OUTPUT__EDGE TRIGGER_TYPE_EDGE +#define TRIGGER_TYPE_TR_GROUP_INPUT__LEVEL TRIGGER_TYPE_LEVEL +#define TRIGGER_TYPE_TR_GROUP_INPUT__EDGE TRIGGER_TYPE_EDGE + +/* Monitor Signal Defines */ +typedef enum +{ + PROFILE_ONE = 0, /* profile.one */ + CPUSS_MONITOR_CM0 = 1, /* cpuss.monitor_cm0 */ + CPUSS_MONITOR_CM4 = 2, /* cpuss.monitor_cm4 */ + CPUSS_MONITOR_FLASH = 3, /* cpuss.monitor_flash */ + CPUSS_MONITOR_DW0_AHB = 4, /* cpuss.monitor_dw0_ahb */ + CPUSS_MONITOR_DW1_AHB = 5, /* cpuss.monitor_dw1_ahb */ + CPUSS_MONITOR_CRYPTO = 6, /* cpuss.monitor_crypto */ + USB_MONITOR_AHB = 7, /* usb.monitor_ahb */ + SCB0_MONITOR_AHB = 8, /* scb[0].monitor_ahb */ + SCB1_MONITOR_AHB = 9, /* scb[1].monitor_ahb */ + SCB2_MONITOR_AHB = 10, /* scb[2].monitor_ahb */ + SCB3_MONITOR_AHB = 11, /* scb[3].monitor_ahb */ + SCB4_MONITOR_AHB = 12, /* scb[4].monitor_ahb */ + SCB5_MONITOR_AHB = 13, /* scb[5].monitor_ahb */ + SCB6_MONITOR_AHB = 14, /* scb[6].monitor_ahb */ + SCB7_MONITOR_AHB = 15, /* scb[7].monitor_ahb */ + SCB8_MONITOR_AHB = 16, /* scb[8].monitor_ahb */ + UDB_MONITOR_UDB0 = 17, /* udb.monitor_udb[0] */ + UDB_MONITOR_UDB1 = 18, /* udb.monitor_udb[1] */ + UDB_MONITOR_UDB2 = 19, /* udb.monitor_udb[2] */ + UDB_MONITOR_UDB3 = 20, /* udb.monitor_udb[3] */ + SMIF_MONITOR_SMIF_SPI_SELECT0 = 21, /* smif.monitor_smif_spi_select[0] */ + SMIF_MONITOR_SMIF_SPI_SELECT1 = 22, /* smif.monitor_smif_spi_select[1] */ + SMIF_MONITOR_SMIF_SPI_SELECT2 = 23, /* smif.monitor_smif_spi_select[2] */ + SMIF_MONITOR_SMIF_SPI_SELECT3 = 24, /* smif.monitor_smif_spi_select[3] */ + SMIF_MONITOR_SMIF_SPI_SELECT_ANY = 25, /* smif.monitor_smif_spi_select_any */ + BLESS_EXT_LNA_RX_CTL_OUT = 26, /* bless.ext_lna_rx_ctl_out */ + BLESS_EXT_PA_TX_CTL_OUT = 27 /* bless.ext_pa_tx_ctl_out */ +} en_ep_mon_sel_t; + +/* Total count of Energy Profiler monitor signal connections */ +#define EP_MONITOR_COUNT 28u + +/* Bus masters */ +typedef enum +{ + CPUSS_MS_ID_CM0 = 0, + CPUSS_MS_ID_CRYPTO = 1, + CPUSS_MS_ID_DW0 = 2, + CPUSS_MS_ID_DW1 = 3, + CPUSS_MS_ID_CM4 = 14, + CPUSS_MS_ID_TC = 15 +} en_prot_master_t; + +/* Parameter Defines */ +/* Number of regulator modules instantiated within SRSS */ +#define SRSS_NUM_ACTREG_PWRMOD 2u +/* Number of shorting switches between vccd and vccact */ +#define SRSS_NUM_ACTIVE_SWITCH 3u +/* ULP linear regulator system is present */ +#define SRSS_ULPLINREG_PRESENT 1u +/* HT linear regulator system is present */ +#define SRSS_HTLINREG_PRESENT 0u +/* SIMO buck core regulator is present. Only compatible with ULP linear regulator + system (ULPLINREG_PRESENT==1). */ +#define SRSS_SIMOBUCK_PRESENT 1u +/* Precision ILO (PILO) is present */ +#define SRSS_PILO_PRESENT 1u +/* External Crystal Oscillator is present (high frequency) */ +#define SRSS_ECO_PRESENT 1u +/* System Buck-Boost is present */ +#define SRSS_SYSBB_PRESENT 0u +/* Number of clock paths. Must be > 0 */ +#define SRSS_NUM_CLKPATH 5u +/* Number of PLLs present. Must be <= NUM_CLKPATH */ +#define SRSS_NUM_PLL 1u +/* Number of HFCLK roots present. Must be > 0 */ +#define SRSS_NUM_HFROOT 5u +/* Number of PWR_HIB_DATA registers */ +#define SRSS_NUM_HIBDATA 1u +/* Backup domain is present */ +#define SRSS_BACKUP_PRESENT 1u +/* Mask of HFCLK root clock supervisors (CSV). For each clock root i, bit[i] of + mask indicates presence of a CSV. */ +#define SRSS_MASK_HFCSV 0u +/* Clock supervisor is present on WCO. Must be 0 if BACKUP_PRESENT==0. */ +#define SRSS_WCOCSV_PRESENT 0u +/* Number of software watchdog timers. */ +#define SRSS_NUM_MCWDT 2u +/* Number of DSI inputs into clock muxes. This is used for logic optimization. */ +#define SRSS_NUM_DSI 2u +/* Alternate high-frequency clock is present. This is used for logic optimization. */ +#define SRSS_ALTHF_PRESENT 1u +/* Alternate low-frequency clock is present. This is used for logic optimization. */ +#define SRSS_ALTLF_PRESENT 0u +/* Use the hardened clkactfllmux block */ +#define SRSS_USE_HARD_CLKACTFLLMUX 1u +/* Number of clock paths, including direct paths in hardened clkactfllmux block + (Must be >= NUM_CLKPATH) */ +#define SRSS_HARD_CLKPATH 6u +/* Number of clock paths with muxes in hardened clkactfllmux block (Must be >= + NUM_PLL+1) */ +#define SRSS_HARD_CLKPATHMUX 6u +/* Number of HFCLKS present in hardened clkactfllmux block (Must be >= NUM_HFROOT) */ +#define SRSS_HARD_HFROOT 6u +/* ECO mux is present in hardened clkactfllmux block (Must be >= ECO_PRESENT) */ +#define SRSS_HARD_ECOMUX_PRESENT 1u +/* ALTHF mux is present in hardened clkactfllmux block (Must be >= ALTHF_PRESENT) */ +#define SRSS_HARD_ALTHFMUX_PRESENT 1u +/* Low-current buck regulator present. Can be derived from S40S_SISOBUCKLC_PRESENT + or SIMOBUCK_PRESENT. */ +#define SRSS_BUCKCTL_PRESENT 1u +/* Low-current SISO buck core regulator is present. Only compatible with ULP + linear regulator system (ULPLINREG_PRESENT==1). */ +#define SRSS_S40S_SISOBUCKLC_PRESENT 0u +/* Backup memory is present (only used when BACKUP_PRESENT==1) */ +#define SRSS_BACKUP_BMEM_PRESENT 0u +/* Number of Backup registers to include (each is 32b). Only used when + BACKUP_PRESENT==1. */ +#define SRSS_BACKUP_NUM_BREG 16u +/* Number of AMUX splitter cells */ +#define IOSS_HSIOM_AMUX_SPLIT_NR 9u +/* Number of HSIOM ports in device (same as GPIO.GPIO_PRT_NR) */ +#define IOSS_HSIOM_HSIOM_PORT_NR 15u +/* Number of GPIO ports in range 0..31 */ +#define IOSS_GPIO_GPIO_PORT_NR_0_31 15u +/* Number of GPIO ports in range 32..63 */ +#define IOSS_GPIO_GPIO_PORT_NR_32_63 0u +/* Number of GPIO ports in range 64..95 */ +#define IOSS_GPIO_GPIO_PORT_NR_64_95 0u +/* Number of GPIO ports in range 96..127 */ +#define IOSS_GPIO_GPIO_PORT_NR_96_127 0u +/* Number of ports in device */ +#define IOSS_GPIO_GPIO_PORT_NR 15u +/* Mask of SMARTIO instances presence */ +#define IOSS_SMARTIO_SMARTIO_MASK 768u +/* The number of protection contexts ([2, 16]). */ +#define PERI_PC_NR 8u +/* Master interface presence mask (4 bits) */ +#define PERI_MS_PRESENT 15u +/* Master interface PPU combinatorial (1) or registerd (0) */ +#define PERI_MS_PPU_COMBINATORIAL 1u +/* The number of programmable PPU structures for PERI (all peripherals) */ +#define PERI_MS_PPU_PROG_STRUCT_NR 16u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_CLOCK_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL0_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL1_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL2_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT0_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_CLOCK_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL0_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL1_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL2_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT1_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_CLOCK_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL0_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL1_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL2_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL3_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL4_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL5_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL6_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL7_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL8_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL9_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL12_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL13_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT2_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL0_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL1_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL2_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL3_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL4_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL5_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL6_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL8_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL9_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL10_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL11_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL12_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT3_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL0_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL1_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL2_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT4_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL0_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL1_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL2_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT5_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL0_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL1_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL2_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL3_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL4_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL5_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL6_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL7_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL8_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL9_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT6_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL0_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL1_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL2_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT7_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL0_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL1_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL2_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT8_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL0_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL1_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL2_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT9_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL0_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL1_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL2_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT10_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL0_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL1_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL2_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT11_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL0_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL1_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL2_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT12_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL0_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL1_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL2_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT13_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL0_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL1_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL2_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT14_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Presence of a timeout functionality (1: Yes, 0:No) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_CLOCK_PRESENT 1u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL0_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL1_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL2_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL3_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL4_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL5_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL6_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL7_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL8_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL9_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL10_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL11_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL12_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL13_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL14_PRESENT 0u +/* Slave present (0:No, 1:Yes) */ +#define PERI_GROUP_PRESENT15_PERI_GROUP_STRUCT_SL15_PRESENT 0u +/* Number of programmable clocks (outputs) */ +#define PERI_CLOCK_NR 59u +/* Number of 8.0 dividers */ +#define PERI_DIV_8_NR 8u +/* Number of 16.0 dividers */ +#define PERI_DIV_16_NR 16u +/* Number of 16.5 (fractional) dividers */ +#define PERI_DIV_16_5_NR 4u +/* Number of 24.5 (fractional) dividers */ +#define PERI_DIV_24_5_NR 1u +/* Divider number width: max(1,roundup(log2(max(DIV_*_NR))) */ +#define PERI_DIV_ADDR_WIDTH 4u +/* Trigger module present (0=No, 1=Yes) */ +#define PERI_TR 1u +/* Number of trigger groups */ +#define PERI_TR_GROUP_NR 15u +/* The number of protection contexts minus 1 ([1, 15]). */ +#define PERI_PPU_FIXED_STRUCT_PC_NR_MINUS1 7u +/* The number of protection contexts minus 1 ([1, 15]). */ +#define PERI_PPU_PROG_STRUCT_PC_NR_MINUS1 7u +/* UDB present or not ('0': no, '1': yes) */ +#define CPUSS_UDB_PRESENT 1u +/* System RAM 0 size in kilobytes */ +#define CPUSS_SRAM0_SIZE 288u +/* Number of macros used to implement System RAM 0. Example: 8 if 256 KB System + SRAM0 is implemented with 8 32KB macros. */ +#define CPUSS_RAMC0_MACRO_NR 9u +/* System RAM 1 present or not (0=No, 1=Yes) */ +#define CPUSS_RAMC1_PRESENT 0u +/* System RAM 1 size in kilobytes */ +#define CPUSS_SRAM1_SIZE 32u +/* Number of macros used to implement System RAM 1. Example: 8 if 256 KB System + RAM 1 is implemented with 8 32KB macros. */ +#define CPUSS_RAMC1_MACRO_NR 1u +/* System RAM 2 present or not (0=No, 1=Yes) */ +#define CPUSS_RAMC2_PRESENT 0u +/* System RAM 2 size in kilobytes */ +#define CPUSS_SRAM2_SIZE 256u +/* Number of macros used to implement System RAM 2. Example: 8 if 256 KB System + RAM 2 is implemented with 8 32KB macros. */ +#define CPUSS_RAMC2_MACRO_NR 16u +/* System ROM size in KB */ +#define CPUSS_ROM_SIZE 128u +/* Flash main region size in KB */ +#define CPUSS_FLASH_SIZE 1024u +/* Flash work region size in KB (EEPROM emulation, data) */ +#define CPUSS_WFLASH_SIZE 32u +/* Flash supervisory region size in KB */ +#define CPUSS_SFLASH_SIZE 32u +/* Flash data output size (in Bytes) */ +#define CPUSS_FLASHC_WORD_SIZE 16u +/* Flash row address width */ +#define CPUSS_FLASHC_ROW_ADDR_WIDTH 12u +/* Flash column address width */ +#define CPUSS_FLASHC_COL_ADDR_WIDTH 5u +/* Number of external slaves directly connected to slow AHB-Lite infrastructure. + Maximum nubmer of slave supported is 4. Width of this parameter is 4-bits. + 1-bit mask for each slave indicating present or not. Example: 4'b0011 - slave + 0 and slave 1 are present. Note: The SLOW_SLx_ADDR and SLOW_SLx_MASK + parameters (for the slaves present) should be derived from the Memory Map. */ +#define CPUSS_SLOW_SL_PRESENT 1u +/* Number of external slaves directly connected to fast AHB-Lite infrastructure. + Maximum nubmer of slave supported is 4. Width of this parameter is 4-bits. + 1-bit mask for each slave indicating present or not. Example: 4'b0011 - slave + 0 and slave 1 are present. Note: The FAST_SLx_ADDR and FAST_SLx_MASK + parameters (for the slaves present) should be derived from the Memory Map. */ +#define CPUSS_FAST_SL_PRESENT 1u +/* Number of external masters driving the slow AHB-Lite infrastructure. Maximum + number of masters supported is 2. Width of this parameter is 2-bits. 1-bit + mask for each master indicating present or not. Example: 2'b01 - master 0 is + present. */ +#define CPUSS_SLOW_MS_PRESENT 0u +/* Number of total interrupt request inputs to CPUSS */ +#define CPUSS_IRQ_NR 147u +/* Number of DeepSleep wakeup interrupt inputs to CPUSS */ +#define CPUSS_DPSLP_IRQ_NR 41u +/* Number of DeepSleep wakeup interrupt inputs to CM0+ (product configuration) */ +#define CPUSS_CM0_DPSLP_IRQ_NR 8u +/* Width of the CM4 interrupt priority bits. Legal range [3,8] Example: 3 = 8 + levels of priority 8 = 256 levels of priority */ +#define CPUSS_CM4_LVL_WIDTH 3u +/* CM4 Floating point unit present or not (0=No, 1=Yes) */ +#define CPUSS_CM4_FPU_PRESENT 1u +/* Debug level. Legal range [0,3] */ +#define CPUSS_DEBUG_LVL 3u +/* Trace level. Legal range [0,2] Note: CM4 HTM is not supported. Hence vaule 3 + for trace level is not supported in CPUSS. */ +#define CPUSS_TRACE_LVL 2u +/* Embedded Trace Buffer present or not (0=No, 1=Yes) */ +#define CPUSS_ETB_PRESENT 0u +/* CM0+ MTB SRAM buffer size in kilobytes. Legal vaules 4, 8 or 16 */ +#define CPUSS_MTB_SRAM_SIZE 4u +/* CM4 ETB SRAM buffer size in kilobytes. Legal vaules 4, 8 or 16 */ +#define CPUSS_ETB_SRAM_SIZE 16u +/* PTM interface present (0=No, 1=Yes) */ +#define CPUSS_PTM_PRESENT 1u +/* Width of the PTM interface in bits ([2,32]) */ +#define CPUSS_PTM_WIDTH 8u +/* Width of the TPIU interface in bits ([1,32]) */ +#define CPUSS_TPIU_WIDTH 4u +/* CoreSight Part Identification Number */ +#define CPUSS_JEPID 52u +/* CoreSight Part Identification Number */ +#define CPUSS_JEPCONTINUATION 0u +/* CoreSight Part Identification Number */ +#define CPUSS_FAMILYID 256u +/* Cryptography IP present or not (0=No, 1=Yes) */ +#define CPUSS_CRYPTO_PRESENT 1u +/* DataWire 0 present or not (0=No, 1=Yes) */ +#define CPUSS_DW0_PRESENT 1u +/* Number of DataWire 0 channels (8, 16 or 32) */ +#define CPUSS_DW0_CH_NR 16u +/* DataWire 1 present or not (0=No, 1=Yes) */ +#define CPUSS_DW1_PRESENT 1u +/* Number of DataWire 1 channels (8, 16 or 32) */ +#define CPUSS_DW1_CH_NR 16u +/* Number of Flash BIST_DATA registers */ +#define CPUSS_FLASHC_FLASHC_BIST_DATA_NR 4u +/* Page size in # of 32-bit words (1: 4 bytes, 2: 8 bytes, ... */ +#define CPUSS_FLASHC_PA_SIZE 128u +/* AES cipher support (0 = no support, 1 = support */ +#define CPUSS_CRYPTO_AES 1u +/* (Tripple) DES cipher support (0 = no support, 1 = support */ +#define CPUSS_CRYPTO_DES 1u +/* Pseudo random number generation support (0 = no support, 1 = support) */ +#define CPUSS_CRYPTO_PR 1u +/* SHA support included */ +#define CPUSS_CRYPTO_SHA 1u +/* SHA1 hash support (0 = no support, 1 = support) */ +#define CPUSS_CRYPTO_SHA1 1u +/* SHA256 hash support (0 = no support, 1 = support) */ +#define CPUSS_CRYPTO_SHA256 1u +/* SHA512 hash support (0 = no support, 1 = support) */ +#define CPUSS_CRYPTO_SHA512 1u +/* Cyclic Redundancy Check support (0 = no support, 1 = support) */ +#define CPUSS_CRYPTO_CRC 1u +/* Vector unit support (0 = no support, 1 = support) */ +#define CPUSS_CRYPTO_VU 1u +/* True random number generation support (0 = no support, 1 = support) */ +#define CPUSS_CRYPTO_TR 1u +/* String support (0 = no support, 1 = support) */ +#define CPUSS_CRYPTO_STR 1u +/* AHB-Lite master interface support (0 = no support, 1 = support) */ +#define CPUSS_CRYPTO_MASTER_IF 1u +/* Number of 32-bit words in the IP internal memory buffer (from the set [64, 128, + 256, 512, 1024, 2048, 4096], to allow for a 256 B, 512 B, 1 kB, 2 kB, 4 kB, 8 + kB and 16 kB memory buffer) */ +#define CPUSS_CRYPTO_BUFF_SIZE 1024u +/* Number of fault structures. Legal range [1, 4] */ +#define CPUSS_FAULT_FAULT_NR 2u +/* Number of IPC structures. Legal range [1, 16] */ +#define CPUSS_IPC_IPC_NR 16u +/* Number of IPC interrupt structures. Legal range [1, 16] */ +#define CPUSS_IPC_IPC_IRQ_NR 16u +/* Master 0 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS0_PC_NR_MINUS1 7u +/* Master 1 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS1_PC_NR_MINUS1 7u +/* Master 2 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS2_PC_NR_MINUS1 0u +/* Master 3 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS3_PC_NR_MINUS1 0u +/* Master 4 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS4_PC_NR_MINUS1 0u +/* Master 5 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS5_PC_NR_MINUS1 0u +/* Master 6 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS6_PC_NR_MINUS1 0u +/* Master 7 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS7_PC_NR_MINUS1 0u +/* Master 8 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS8_PC_NR_MINUS1 0u +/* Master 9 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS9_PC_NR_MINUS1 0u +/* Master 10 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS10_PC_NR_MINUS1 0u +/* Master 11 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS11_PC_NR_MINUS1 0u +/* Master 12 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS12_PC_NR_MINUS1 0u +/* Master 13 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS13_PC_NR_MINUS1 0u +/* Master 14 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS14_PC_NR_MINUS1 7u +/* Master 15 protect contexts minus one */ +#define CPUSS_PROT_SMPU_MS15_PC_NR_MINUS1 7u +/* Number of SMPU protection structures */ +#define CPUSS_PROT_SMPU_STRUCT_NR 16u +/* Number of protection contexts supported minus 1. Legal range [1,16] */ +#define CPUSS_SMPU_STRUCT_PC_NR_MINUS1 7u +/* Number of DataWire controllers present (max 2) */ +#define CPUSS_DW_NR 2u +/* Number of channels in each DataWire controller (must be the same for now) */ +#define CPUSS_DW_CH_NR 16u +/* Number of profiling counters. Legal range [1, 32] */ +#define PROFILE_PRFL_CNT_NR 8u +/* Number of monitor event signals. Legal range [1, 128] */ +#define PROFILE_PRFL_MONITOR_NR 128u +/* Number of instantiated eFUSE macros (256 bit macros). Legal range [1, 16] */ +#define EFUSE_EFUSE_NR 4u +/* SONOS Flash is used or not ('0': no, '1': yes) */ +#define SFLASH_FLASHC_IS_SONOS 1u +/* Number of UDB Interrupts */ +#define UDB_NUMINT 16u +/* Number of triggers */ +#define UDB_NUMTR 16u +/* Number of UDB array rows (must be multiple of 2) */ +#define UDB_NUMROW 2u +/* Number of UDB array columns */ +#define UDB_NUMCOL 6u +/* DSI on bottom (1) or on bottom and top (2) of UDB array */ +#define UDB_DSISIDES 2u +/* Number of UDBs = NUMROW * NUMCOL */ +#define UDB_NUMUDB 12u +/* Number of UDB pairs = NUMUDB / 2 */ +#define UDB_NUMUDBPAIR 6u +/* Number of DSIs = NUMCOL * DSISIDES */ +#define UDB_NUMDSI 12u +/* Number of quad clocks */ +#define UDB_NUMQCLK 3u +/* DeepSleep support ('0':no, '1': yes) */ +#define SCB0_DEEPSLEEP 0u +/* Externally clocked support? ('0': no, '1': yes) */ +#define SCB0_EC 0u +/* I2C master support? ('0': no, '1': yes) */ +#define SCB0_I2C_M 1u +/* I2C slave support? ('0': no, '1': yes) */ +#define SCB0_I2C_S 1u +/* I2C support? (I2C_M | I2C_S) */ +#define SCB0_I2C 1u +/* I2C glitch filters present? ('0': no, '1': yes) */ +#define SCB0_I2C_GLITCH 1u +/* I2C externally clocked support? ('0': no, '1': yes) */ +#define SCB0_I2C_EC 0u +/* I2C master and slave support? (I2C_M & I2C_S) */ +#define SCB0_I2C_M_S 1u +/* I2C slave with EC? (I2C_S & I2C_EC) */ +#define SCB0_I2C_S_EC 0u +/* SPI master support? ('0': no, '1': yes) */ +#define SCB0_SPI_M 1u +/* SPI slave support? ('0': no, '1': yes) */ +#define SCB0_SPI_S 1u +/* SPI support? (SPI_M | SPI_S) */ +#define SCB0_SPI 1u +/* SPI externally clocked support? ('0': no, '1': yes) */ +#define SCB0_SPI_EC 0u +/* SPI slave with EC? (SPI_S & SPI_EC) */ +#define SCB0_SPI_S_EC 0u +/* UART support? ('0': no, '1': yes) */ +#define SCB0_UART 1u +/* SPI or UART (SPI | UART) */ +#define SCB0_SPI_UART 1u +/* Number of EZ memory Bytes ([32, 256, 512]). This memory is used in EZ mode, + CMD_RESP mode and FIFO mode. Note that in EZ mode, if EZ_DATA_NR is 512, only + 256 B are used. This is because the EZ mode uses 8-bit addresses. */ +#define SCB0_EZ_DATA_NR 256u +/* Command/response mode support? ('0': no, '1': yes) */ +#define SCB0_CMD_RESP 0u +/* EZ mode support? ('0': no, '1': yes) */ +#define SCB0_EZ 0u +/* Command/response mode or EZ mode support? (CMD_RESP | EZ) */ +#define SCB0_EZ_CMD_RESP 0u +/* I2C slave with EZ mode (I2C_S & EZ) */ +#define SCB0_I2C_S_EZ 0u +/* SPI slave with EZ mode (SPI_S & EZ) */ +#define SCB0_SPI_S_EZ 0u +/* Support I2C FM+/1Mbps speed ('0': no, '1': yes) */ +#define SCB0_I2C_FAST_PLUS 1u +/* DeepSleep support ('0':no, '1': yes) */ +#define SCB1_DEEPSLEEP 0u +/* Externally clocked support? ('0': no, '1': yes) */ +#define SCB1_EC 0u +/* I2C master support? ('0': no, '1': yes) */ +#define SCB1_I2C_M 1u +/* I2C slave support? ('0': no, '1': yes) */ +#define SCB1_I2C_S 1u +/* I2C support? (I2C_M | I2C_S) */ +#define SCB1_I2C 1u +/* I2C glitch filters present? ('0': no, '1': yes) */ +#define SCB1_I2C_GLITCH 1u +/* I2C externally clocked support? ('0': no, '1': yes) */ +#define SCB1_I2C_EC 0u +/* I2C master and slave support? (I2C_M & I2C_S) */ +#define SCB1_I2C_M_S 1u +/* I2C slave with EC? (I2C_S & I2C_EC) */ +#define SCB1_I2C_S_EC 0u +/* SPI master support? ('0': no, '1': yes) */ +#define SCB1_SPI_M 1u +/* SPI slave support? ('0': no, '1': yes) */ +#define SCB1_SPI_S 1u +/* SPI support? (SPI_M | SPI_S) */ +#define SCB1_SPI 1u +/* SPI externally clocked support? ('0': no, '1': yes) */ +#define SCB1_SPI_EC 0u +/* SPI slave with EC? (SPI_S & SPI_EC) */ +#define SCB1_SPI_S_EC 0u +/* UART support? ('0': no, '1': yes) */ +#define SCB1_UART 1u +/* SPI or UART (SPI | UART) */ +#define SCB1_SPI_UART 1u +/* Number of EZ memory Bytes ([32, 256, 512]). This memory is used in EZ mode, + CMD_RESP mode and FIFO mode. Note that in EZ mode, if EZ_DATA_NR is 512, only + 256 B are used. This is because the EZ mode uses 8-bit addresses. */ +#define SCB1_EZ_DATA_NR 256u +/* Command/response mode support? ('0': no, '1': yes) */ +#define SCB1_CMD_RESP 0u +/* EZ mode support? ('0': no, '1': yes) */ +#define SCB1_EZ 0u +/* Command/response mode or EZ mode support? (CMD_RESP | EZ) */ +#define SCB1_EZ_CMD_RESP 0u +/* I2C slave with EZ mode (I2C_S & EZ) */ +#define SCB1_I2C_S_EZ 0u +/* SPI slave with EZ mode (SPI_S & EZ) */ +#define SCB1_SPI_S_EZ 0u +/* Support I2C FM+/1Mbps speed ('0': no, '1': yes) */ +#define SCB1_I2C_FAST_PLUS 1u +/* DeepSleep support ('0':no, '1': yes) */ +#define SCB2_DEEPSLEEP 0u +/* Externally clocked support? ('0': no, '1': yes) */ +#define SCB2_EC 0u +/* I2C master support? ('0': no, '1': yes) */ +#define SCB2_I2C_M 1u +/* I2C slave support? ('0': no, '1': yes) */ +#define SCB2_I2C_S 1u +/* I2C support? (I2C_M | I2C_S) */ +#define SCB2_I2C 1u +/* I2C glitch filters present? ('0': no, '1': yes) */ +#define SCB2_I2C_GLITCH 1u +/* I2C externally clocked support? ('0': no, '1': yes) */ +#define SCB2_I2C_EC 0u +/* I2C master and slave support? (I2C_M & I2C_S) */ +#define SCB2_I2C_M_S 1u +/* I2C slave with EC? (I2C_S & I2C_EC) */ +#define SCB2_I2C_S_EC 0u +/* SPI master support? ('0': no, '1': yes) */ +#define SCB2_SPI_M 1u +/* SPI slave support? ('0': no, '1': yes) */ +#define SCB2_SPI_S 1u +/* SPI support? (SPI_M | SPI_S) */ +#define SCB2_SPI 1u +/* SPI externally clocked support? ('0': no, '1': yes) */ +#define SCB2_SPI_EC 0u +/* SPI slave with EC? (SPI_S & SPI_EC) */ +#define SCB2_SPI_S_EC 0u +/* UART support? ('0': no, '1': yes) */ +#define SCB2_UART 1u +/* SPI or UART (SPI | UART) */ +#define SCB2_SPI_UART 1u +/* Number of EZ memory Bytes ([32, 256, 512]). This memory is used in EZ mode, + CMD_RESP mode and FIFO mode. Note that in EZ mode, if EZ_DATA_NR is 512, only + 256 B are used. This is because the EZ mode uses 8-bit addresses. */ +#define SCB2_EZ_DATA_NR 256u +/* Command/response mode support? ('0': no, '1': yes) */ +#define SCB2_CMD_RESP 0u +/* EZ mode support? ('0': no, '1': yes) */ +#define SCB2_EZ 0u +/* Command/response mode or EZ mode support? (CMD_RESP | EZ) */ +#define SCB2_EZ_CMD_RESP 0u +/* I2C slave with EZ mode (I2C_S & EZ) */ +#define SCB2_I2C_S_EZ 0u +/* SPI slave with EZ mode (SPI_S & EZ) */ +#define SCB2_SPI_S_EZ 0u +/* Support I2C FM+/1Mbps speed ('0': no, '1': yes) */ +#define SCB2_I2C_FAST_PLUS 1u +/* DeepSleep support ('0':no, '1': yes) */ +#define SCB3_DEEPSLEEP 0u +/* Externally clocked support? ('0': no, '1': yes) */ +#define SCB3_EC 0u +/* I2C master support? ('0': no, '1': yes) */ +#define SCB3_I2C_M 1u +/* I2C slave support? ('0': no, '1': yes) */ +#define SCB3_I2C_S 1u +/* I2C support? (I2C_M | I2C_S) */ +#define SCB3_I2C 1u +/* I2C glitch filters present? ('0': no, '1': yes) */ +#define SCB3_I2C_GLITCH 1u +/* I2C externally clocked support? ('0': no, '1': yes) */ +#define SCB3_I2C_EC 0u +/* I2C master and slave support? (I2C_M & I2C_S) */ +#define SCB3_I2C_M_S 1u +/* I2C slave with EC? (I2C_S & I2C_EC) */ +#define SCB3_I2C_S_EC 0u +/* SPI master support? ('0': no, '1': yes) */ +#define SCB3_SPI_M 1u +/* SPI slave support? ('0': no, '1': yes) */ +#define SCB3_SPI_S 1u +/* SPI support? (SPI_M | SPI_S) */ +#define SCB3_SPI 1u +/* SPI externally clocked support? ('0': no, '1': yes) */ +#define SCB3_SPI_EC 0u +/* SPI slave with EC? (SPI_S & SPI_EC) */ +#define SCB3_SPI_S_EC 0u +/* UART support? ('0': no, '1': yes) */ +#define SCB3_UART 1u +/* SPI or UART (SPI | UART) */ +#define SCB3_SPI_UART 1u +/* Number of EZ memory Bytes ([32, 256, 512]). This memory is used in EZ mode, + CMD_RESP mode and FIFO mode. Note that in EZ mode, if EZ_DATA_NR is 512, only + 256 B are used. This is because the EZ mode uses 8-bit addresses. */ +#define SCB3_EZ_DATA_NR 256u +/* Command/response mode support? ('0': no, '1': yes) */ +#define SCB3_CMD_RESP 0u +/* EZ mode support? ('0': no, '1': yes) */ +#define SCB3_EZ 0u +/* Command/response mode or EZ mode support? (CMD_RESP | EZ) */ +#define SCB3_EZ_CMD_RESP 0u +/* I2C slave with EZ mode (I2C_S & EZ) */ +#define SCB3_I2C_S_EZ 0u +/* SPI slave with EZ mode (SPI_S & EZ) */ +#define SCB3_SPI_S_EZ 0u +/* Support I2C FM+/1Mbps speed ('0': no, '1': yes) */ +#define SCB3_I2C_FAST_PLUS 1u +/* DeepSleep support ('0':no, '1': yes) */ +#define SCB4_DEEPSLEEP 0u +/* Externally clocked support? ('0': no, '1': yes) */ +#define SCB4_EC 0u +/* I2C master support? ('0': no, '1': yes) */ +#define SCB4_I2C_M 1u +/* I2C slave support? ('0': no, '1': yes) */ +#define SCB4_I2C_S 1u +/* I2C support? (I2C_M | I2C_S) */ +#define SCB4_I2C 1u +/* I2C glitch filters present? ('0': no, '1': yes) */ +#define SCB4_I2C_GLITCH 1u +/* I2C externally clocked support? ('0': no, '1': yes) */ +#define SCB4_I2C_EC 0u +/* I2C master and slave support? (I2C_M & I2C_S) */ +#define SCB4_I2C_M_S 1u +/* I2C slave with EC? (I2C_S & I2C_EC) */ +#define SCB4_I2C_S_EC 0u +/* SPI master support? ('0': no, '1': yes) */ +#define SCB4_SPI_M 1u +/* SPI slave support? ('0': no, '1': yes) */ +#define SCB4_SPI_S 1u +/* SPI support? (SPI_M | SPI_S) */ +#define SCB4_SPI 1u +/* SPI externally clocked support? ('0': no, '1': yes) */ +#define SCB4_SPI_EC 0u +/* SPI slave with EC? (SPI_S & SPI_EC) */ +#define SCB4_SPI_S_EC 0u +/* UART support? ('0': no, '1': yes) */ +#define SCB4_UART 1u +/* SPI or UART (SPI | UART) */ +#define SCB4_SPI_UART 1u +/* Number of EZ memory Bytes ([32, 256, 512]). This memory is used in EZ mode, + CMD_RESP mode and FIFO mode. Note that in EZ mode, if EZ_DATA_NR is 512, only + 256 B are used. This is because the EZ mode uses 8-bit addresses. */ +#define SCB4_EZ_DATA_NR 256u +/* Command/response mode support? ('0': no, '1': yes) */ +#define SCB4_CMD_RESP 0u +/* EZ mode support? ('0': no, '1': yes) */ +#define SCB4_EZ 0u +/* Command/response mode or EZ mode support? (CMD_RESP | EZ) */ +#define SCB4_EZ_CMD_RESP 0u +/* I2C slave with EZ mode (I2C_S & EZ) */ +#define SCB4_I2C_S_EZ 0u +/* SPI slave with EZ mode (SPI_S & EZ) */ +#define SCB4_SPI_S_EZ 0u +/* Support I2C FM+/1Mbps speed ('0': no, '1': yes) */ +#define SCB4_I2C_FAST_PLUS 1u +/* DeepSleep support ('0':no, '1': yes) */ +#define SCB5_DEEPSLEEP 0u +/* Externally clocked support? ('0': no, '1': yes) */ +#define SCB5_EC 0u +/* I2C master support? ('0': no, '1': yes) */ +#define SCB5_I2C_M 1u +/* I2C slave support? ('0': no, '1': yes) */ +#define SCB5_I2C_S 1u +/* I2C support? (I2C_M | I2C_S) */ +#define SCB5_I2C 1u +/* I2C glitch filters present? ('0': no, '1': yes) */ +#define SCB5_I2C_GLITCH 1u +/* I2C externally clocked support? ('0': no, '1': yes) */ +#define SCB5_I2C_EC 0u +/* I2C master and slave support? (I2C_M & I2C_S) */ +#define SCB5_I2C_M_S 1u +/* I2C slave with EC? (I2C_S & I2C_EC) */ +#define SCB5_I2C_S_EC 0u +/* SPI master support? ('0': no, '1': yes) */ +#define SCB5_SPI_M 1u +/* SPI slave support? ('0': no, '1': yes) */ +#define SCB5_SPI_S 1u +/* SPI support? (SPI_M | SPI_S) */ +#define SCB5_SPI 1u +/* SPI externally clocked support? ('0': no, '1': yes) */ +#define SCB5_SPI_EC 0u +/* SPI slave with EC? (SPI_S & SPI_EC) */ +#define SCB5_SPI_S_EC 0u +/* UART support? ('0': no, '1': yes) */ +#define SCB5_UART 1u +/* SPI or UART (SPI | UART) */ +#define SCB5_SPI_UART 1u +/* Number of EZ memory Bytes ([32, 256, 512]). This memory is used in EZ mode, + CMD_RESP mode and FIFO mode. Note that in EZ mode, if EZ_DATA_NR is 512, only + 256 B are used. This is because the EZ mode uses 8-bit addresses. */ +#define SCB5_EZ_DATA_NR 256u +/* Command/response mode support? ('0': no, '1': yes) */ +#define SCB5_CMD_RESP 0u +/* EZ mode support? ('0': no, '1': yes) */ +#define SCB5_EZ 0u +/* Command/response mode or EZ mode support? (CMD_RESP | EZ) */ +#define SCB5_EZ_CMD_RESP 0u +/* I2C slave with EZ mode (I2C_S & EZ) */ +#define SCB5_I2C_S_EZ 0u +/* SPI slave with EZ mode (SPI_S & EZ) */ +#define SCB5_SPI_S_EZ 0u +/* Support I2C FM+/1Mbps speed ('0': no, '1': yes) */ +#define SCB5_I2C_FAST_PLUS 1u +/* DeepSleep support ('0':no, '1': yes) */ +#define SCB6_DEEPSLEEP 0u +/* Externally clocked support? ('0': no, '1': yes) */ +#define SCB6_EC 0u +/* I2C master support? ('0': no, '1': yes) */ +#define SCB6_I2C_M 1u +/* I2C slave support? ('0': no, '1': yes) */ +#define SCB6_I2C_S 1u +/* I2C support? (I2C_M | I2C_S) */ +#define SCB6_I2C 1u +/* I2C glitch filters present? ('0': no, '1': yes) */ +#define SCB6_I2C_GLITCH 1u +/* I2C externally clocked support? ('0': no, '1': yes) */ +#define SCB6_I2C_EC 0u +/* I2C master and slave support? (I2C_M & I2C_S) */ +#define SCB6_I2C_M_S 1u +/* I2C slave with EC? (I2C_S & I2C_EC) */ +#define SCB6_I2C_S_EC 0u +/* SPI master support? ('0': no, '1': yes) */ +#define SCB6_SPI_M 1u +/* SPI slave support? ('0': no, '1': yes) */ +#define SCB6_SPI_S 1u +/* SPI support? (SPI_M | SPI_S) */ +#define SCB6_SPI 1u +/* SPI externally clocked support? ('0': no, '1': yes) */ +#define SCB6_SPI_EC 0u +/* SPI slave with EC? (SPI_S & SPI_EC) */ +#define SCB6_SPI_S_EC 0u +/* UART support? ('0': no, '1': yes) */ +#define SCB6_UART 1u +/* SPI or UART (SPI | UART) */ +#define SCB6_SPI_UART 1u +/* Number of EZ memory Bytes ([32, 256, 512]). This memory is used in EZ mode, + CMD_RESP mode and FIFO mode. Note that in EZ mode, if EZ_DATA_NR is 512, only + 256 B are used. This is because the EZ mode uses 8-bit addresses. */ +#define SCB6_EZ_DATA_NR 256u +/* Command/response mode support? ('0': no, '1': yes) */ +#define SCB6_CMD_RESP 0u +/* EZ mode support? ('0': no, '1': yes) */ +#define SCB6_EZ 0u +/* Command/response mode or EZ mode support? (CMD_RESP | EZ) */ +#define SCB6_EZ_CMD_RESP 0u +/* I2C slave with EZ mode (I2C_S & EZ) */ +#define SCB6_I2C_S_EZ 0u +/* SPI slave with EZ mode (SPI_S & EZ) */ +#define SCB6_SPI_S_EZ 0u +/* Support I2C FM+/1Mbps speed ('0': no, '1': yes) */ +#define SCB6_I2C_FAST_PLUS 1u +/* DeepSleep support ('0':no, '1': yes) */ +#define SCB7_DEEPSLEEP 0u +/* Externally clocked support? ('0': no, '1': yes) */ +#define SCB7_EC 0u +/* I2C master support? ('0': no, '1': yes) */ +#define SCB7_I2C_M 1u +/* I2C slave support? ('0': no, '1': yes) */ +#define SCB7_I2C_S 1u +/* I2C support? (I2C_M | I2C_S) */ +#define SCB7_I2C 1u +/* I2C glitch filters present? ('0': no, '1': yes) */ +#define SCB7_I2C_GLITCH 1u +/* I2C externally clocked support? ('0': no, '1': yes) */ +#define SCB7_I2C_EC 0u +/* I2C master and slave support? (I2C_M & I2C_S) */ +#define SCB7_I2C_M_S 1u +/* I2C slave with EC? (I2C_S & I2C_EC) */ +#define SCB7_I2C_S_EC 0u +/* SPI master support? ('0': no, '1': yes) */ +#define SCB7_SPI_M 1u +/* SPI slave support? ('0': no, '1': yes) */ +#define SCB7_SPI_S 1u +/* SPI support? (SPI_M | SPI_S) */ +#define SCB7_SPI 1u +/* SPI externally clocked support? ('0': no, '1': yes) */ +#define SCB7_SPI_EC 0u +/* SPI slave with EC? (SPI_S & SPI_EC) */ +#define SCB7_SPI_S_EC 0u +/* UART support? ('0': no, '1': yes) */ +#define SCB7_UART 1u +/* SPI or UART (SPI | UART) */ +#define SCB7_SPI_UART 1u +/* Number of EZ memory Bytes ([32, 256, 512]). This memory is used in EZ mode, + CMD_RESP mode and FIFO mode. Note that in EZ mode, if EZ_DATA_NR is 512, only + 256 B are used. This is because the EZ mode uses 8-bit addresses. */ +#define SCB7_EZ_DATA_NR 256u +/* Command/response mode support? ('0': no, '1': yes) */ +#define SCB7_CMD_RESP 0u +/* EZ mode support? ('0': no, '1': yes) */ +#define SCB7_EZ 0u +/* Command/response mode or EZ mode support? (CMD_RESP | EZ) */ +#define SCB7_EZ_CMD_RESP 0u +/* I2C slave with EZ mode (I2C_S & EZ) */ +#define SCB7_I2C_S_EZ 0u +/* SPI slave with EZ mode (SPI_S & EZ) */ +#define SCB7_SPI_S_EZ 0u +/* Support I2C FM+/1Mbps speed ('0': no, '1': yes) */ +#define SCB7_I2C_FAST_PLUS 1u +/* DeepSleep support ('0':no, '1': yes) */ +#define SCB8_DEEPSLEEP 1u +/* Externally clocked support? ('0': no, '1': yes) */ +#define SCB8_EC 1u +/* I2C master support? ('0': no, '1': yes) */ +#define SCB8_I2C_M 0u +/* I2C slave support? ('0': no, '1': yes) */ +#define SCB8_I2C_S 1u +/* I2C support? (I2C_M | I2C_S) */ +#define SCB8_I2C 1u +/* I2C glitch filters present? ('0': no, '1': yes) */ +#define SCB8_I2C_GLITCH 1u +/* I2C externally clocked support? ('0': no, '1': yes) */ +#define SCB8_I2C_EC 1u +/* I2C master and slave support? (I2C_M & I2C_S) */ +#define SCB8_I2C_M_S 0u +/* I2C slave with EC? (I2C_S & I2C_EC) */ +#define SCB8_I2C_S_EC 1u +/* SPI master support? ('0': no, '1': yes) */ +#define SCB8_SPI_M 0u +/* SPI slave support? ('0': no, '1': yes) */ +#define SCB8_SPI_S 1u +/* SPI support? (SPI_M | SPI_S) */ +#define SCB8_SPI 1u +/* SPI externally clocked support? ('0': no, '1': yes) */ +#define SCB8_SPI_EC 1u +/* SPI slave with EC? (SPI_S & SPI_EC) */ +#define SCB8_SPI_S_EC 1u +/* UART support? ('0': no, '1': yes) */ +#define SCB8_UART 0u +/* SPI or UART (SPI | UART) */ +#define SCB8_SPI_UART 1u +/* Number of EZ memory Bytes ([32, 256, 512]). This memory is used in EZ mode, + CMD_RESP mode and FIFO mode. Note that in EZ mode, if EZ_DATA_NR is 512, only + 256 B are used. This is because the EZ mode uses 8-bit addresses. */ +#define SCB8_EZ_DATA_NR 256u +/* Command/response mode support? ('0': no, '1': yes) */ +#define SCB8_CMD_RESP 1u +/* EZ mode support? ('0': no, '1': yes) */ +#define SCB8_EZ 1u +/* Command/response mode or EZ mode support? (CMD_RESP | EZ) */ +#define SCB8_EZ_CMD_RESP 1u +/* I2C slave with EZ mode (I2C_S & EZ) */ +#define SCB8_I2C_S_EZ 1u +/* SPI slave with EZ mode (SPI_S & EZ) */ +#define SCB8_SPI_S_EZ 1u +/* Support I2C FM+/1Mbps speed ('0': no, '1': yes) */ +#define SCB8_I2C_FAST_PLUS 1u +/* Number of counters per IP (1..8) */ +#define TCPWM0_CNT_NR 8u +/* Counter width (in number of bits) */ +#define TCPWM0_CNT_CNT_WIDTH 32u +/* Number of counters per IP (1..8) */ +#define TCPWM1_CNT_NR 24u +/* Counter width (in number of bits) */ +#define TCPWM1_CNT_CNT_WIDTH 16u +/* Max number of LCD commons supported */ +#define LCD_COM_NR 8u +/* Max number of LCD pins (total) supported */ +#define LCD_PIN_NR 62u +/* Number of ports supoprting up to 4 COMs */ +#define LCD_NUMPORTS 8u +/* Number of ports supporting up to 8 COMs */ +#define LCD_NUMPORTS8 8u +/* Number of ports supporting up to 16 COMs */ +#define LCD_NUMPORTS16 0u +/* Number of IREF outputs from AREF */ +#define PASS_NR_IREFS 4u +/* Number of CTBs in the Subsystem */ +#define PASS_NR_CTBS 1u +/* Number of CTDACs in the Subsystem */ +#define PASS_NR_CTDACS 1u +/* CTB0 Exists */ +#define PASS_CTB0_EXISTS 1u +/* CTB1 Exists */ +#define PASS_CTB1_EXISTS 0u +/* CTB2 Exists */ +#define PASS_CTB2_EXISTS 0u +/* CTB3 Exists */ +#define PASS_CTB3_EXISTS 0u +/* CTDAC0 Exists */ +#define PASS_CTDAC0_EXISTS 1u +/* CTDAC1 Exists */ +#define PASS_CTDAC1_EXISTS 0u +/* CTDAC2 Exists */ +#define PASS_CTDAC2_EXISTS 0u +/* CTDAC3 Exists */ +#define PASS_CTDAC3_EXISTS 0u +/* Number of SAR channels */ +#define PASS_SAR_SAR_CHANNELS 16u +/* Averaging logic present in SAR */ +#define PASS_SAR_SAR_AVERAGE 1u +/* Range detect logic present in SAR */ +#define PASS_SAR_SAR_RANGEDET 1u +/* Support for UAB sampling */ +#define PASS_SAR_SAR_UAB 0u +#define PASS_CTBM_CTDAC_PRESENT 1u +/* Number of AHB-Lite "hmaster[]" bits ([1, 8]) */ +#define SMIF_MASTER_WIDTH 8u +/* Base address of the SMIF XIP memory region. This address must be a multiple of + the SMIF XIP memory capacity. This address must be a multiple of 64 KB. This + address must be in the [0x0000:0000, 0x1fff:ffff] memory region. The XIP + memory region should NOT overlap with other memory regions. */ +#define SMIF_SMIF_XIP_ADDR 402653184u +/* Capacity of the SMIF XIP memory region. The more significant bits of this + parameter must be '1' and the lesser significant bits of this paramter must + be '0'. E.g., 0xfff0:0000 specifies a 1 MB memory region. Legal values are + {0xffff:0000, 0xfffe:0000, 0xfffc:0000, 0xfff8:0000, 0xfff0:0000, + 0xffe0:0000, ..., 0xe000:0000}. */ +#define SMIF_SMIF_XIP_MASK 4160749568u +/* Cryptography (AES) support ('0' = no support, '1' = support) */ +#define SMIF_CRYPTO 1u +/* Number of external devices supported ([1,4]) */ +#define SMIF_DEVICE_NR 4u +/* External device write support. This is a 4-bit field. Each external device has + a dedicated bit. E.g., if bit 2 is '1', external device 2 has write support. */ +#define SMIF_DEVICE_WR_EN 15u +/* Set to 1 if IP will instantiate spares (0=None, 1=Max, 2=Min) */ +#define SMIF_SPARE_EN 1u +/* I2S capable? (0=No,1=Yes) */ +#define AUDIOSS_I2S 1u +/* PDM capable? (0=No,1=Yes) */ +#define AUDIOSS_PDM 1u + +/* MMIO Targets Defines */ +#define CY_MMIO_CRYPTO_GROUP_NR 1u +#define CY_MMIO_CRYPTO_SLAVE_NR 1u +#define CY_MMIO_CPUSS_GROUP_NR 2u +#define CY_MMIO_CPUSS_SLAVE_NR 1u +#define CY_MMIO_FAULT_GROUP_NR 2u +#define CY_MMIO_FAULT_SLAVE_NR 2u +#define CY_MMIO_IPC_GROUP_NR 2u +#define CY_MMIO_IPC_SLAVE_NR 3u +#define CY_MMIO_PROT_GROUP_NR 2u +#define CY_MMIO_PROT_SLAVE_NR 4u +#define CY_MMIO_FLASHC_GROUP_NR 2u +#define CY_MMIO_FLASHC_SLAVE_NR 5u +#define CY_MMIO_SRSS_GROUP_NR 2u +#define CY_MMIO_SRSS_SLAVE_NR 6u +#define CY_MMIO_BACKUP_GROUP_NR 2u +#define CY_MMIO_BACKUP_SLAVE_NR 7u +#define CY_MMIO_DW_GROUP_NR 2u +#define CY_MMIO_DW_SLAVE_NR 8u +#define CY_MMIO_EFUSE_GROUP_NR 2u +#define CY_MMIO_EFUSE_SLAVE_NR 12u +#define CY_MMIO_PROFILE_GROUP_NR 2u +#define CY_MMIO_PROFILE_SLAVE_NR 13u +#define CY_MMIO_HSIOM_GROUP_NR 3u +#define CY_MMIO_HSIOM_SLAVE_NR 1u +#define CY_MMIO_GPIO_GROUP_NR 3u +#define CY_MMIO_GPIO_SLAVE_NR 2u +#define CY_MMIO_SMARTIO_GROUP_NR 3u +#define CY_MMIO_SMARTIO_SLAVE_NR 3u +#define CY_MMIO_UDB_GROUP_NR 3u +#define CY_MMIO_UDB_SLAVE_NR 4u +#define CY_MMIO_LPCOMP_GROUP_NR 3u +#define CY_MMIO_LPCOMP_SLAVE_NR 5u +#define CY_MMIO_CSD0_GROUP_NR 3u +#define CY_MMIO_CSD0_SLAVE_NR 6u +#define CY_MMIO_TCPWM0_GROUP_NR 3u +#define CY_MMIO_TCPWM0_SLAVE_NR 8u +#define CY_MMIO_TCPWM1_GROUP_NR 3u +#define CY_MMIO_TCPWM1_SLAVE_NR 9u +#define CY_MMIO_LCD0_GROUP_NR 3u +#define CY_MMIO_LCD0_SLAVE_NR 10u +#define CY_MMIO_BLE_GROUP_NR 3u +#define CY_MMIO_BLE_SLAVE_NR 11u +#define CY_MMIO_USBFS0_GROUP_NR 3u +#define CY_MMIO_USBFS0_SLAVE_NR 12u +#define CY_MMIO_SMIF0_GROUP_NR 4u +#define CY_MMIO_SMIF0_SLAVE_NR 2u +#define CY_MMIO_SCB0_GROUP_NR 6u +#define CY_MMIO_SCB0_SLAVE_NR 1u +#define CY_MMIO_SCB1_GROUP_NR 6u +#define CY_MMIO_SCB1_SLAVE_NR 2u +#define CY_MMIO_SCB2_GROUP_NR 6u +#define CY_MMIO_SCB2_SLAVE_NR 3u +#define CY_MMIO_SCB3_GROUP_NR 6u +#define CY_MMIO_SCB3_SLAVE_NR 4u +#define CY_MMIO_SCB4_GROUP_NR 6u +#define CY_MMIO_SCB4_SLAVE_NR 5u +#define CY_MMIO_SCB5_GROUP_NR 6u +#define CY_MMIO_SCB5_SLAVE_NR 6u +#define CY_MMIO_SCB6_GROUP_NR 6u +#define CY_MMIO_SCB6_SLAVE_NR 7u +#define CY_MMIO_SCB7_GROUP_NR 6u +#define CY_MMIO_SCB7_SLAVE_NR 8u +#define CY_MMIO_SCB8_GROUP_NR 6u +#define CY_MMIO_SCB8_SLAVE_NR 9u +#define CY_MMIO_PASS_GROUP_NR 9u +#define CY_MMIO_PASS_SLAVE_NR 1u +#define CY_MMIO_I2S0_GROUP_NR 10u +#define CY_MMIO_I2S0_SLAVE_NR 1u +#define CY_MMIO_PDM0_GROUP_NR 10u +#define CY_MMIO_PDM0_SLAVE_NR 2u + +#endif /* _PSOC63_CONFIG_H_ */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/system_psoc63.h b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/system_psoc63.h new file mode 100644 index 0000000000..98b31f45ba --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/device/system_psoc63.h @@ -0,0 +1,556 @@ +/***************************************************************************//** +* \file system_psoc63.h +* \version 2.10 +* +* \brief Device system header file. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + + +#ifndef _SYSTEM_PSOC63_H_ +#define _SYSTEM_PSOC63_H_ + +/** +* \defgroup group_system_config System Configuration Files (Startup) +* \{ +* Provides device startup, system configuration, and linker script files. +* The system startup provides the followings features: +* - See \ref group_system_config_device_initialization for the: +* * \ref group_system_config_dual_core_device_initialization +* * \ref group_system_config_single_core_device_initialization +* - \ref group_system_config_device_memory_definition +* - \ref group_system_config_heap_stack_config +* - \ref group_system_config_merge_apps +* - Default interrupt handlers definition +* - \ref group_system_config_device_vector_table +* - \ref group_system_config_cm4_functions +* +* \section group_system_config_configuration Configuration Considerations +* +* \subsection group_system_config_device_memory_definition Device Memory Definition +* The flash and RAM allocation for each CPU is defined by the linker scripts. +* For dual-core devices, the physical flash and RAM memory is shared between the CPU cores. +* 2 KB of RAM (allocated at the end of RAM) are reserved for system use. +* For Single-Core devices the system reserves additional 80 bytes of RAM. +* Using the reserved memory area for other purposes will lead to unexpected behavior. +* +* \note The linker files provided with the PDL are generic and handle all common +* use cases. Your project may not use every section defined in the linker files. +* In that case you may see warnings during the build process. To eliminate build +* warnings in your project, you can simply comment out or remove the relevant +* code in the linker file. +* +* ARM GCC\n +* The flash and RAM sections for the CPU are defined in the linker files: +* 'xx_yy.ld', where 'xx' is the device group, and 'yy' is the target CPU; for example, +* 'cy8c6xx7_cm0plus.ld' and 'cy8c6xx7_cm4_dual.ld'. +* \note If the start of the Cortex-M4 application image is changed, the value +* of the of the \ref CY_CORTEX_M4_APPL_ADDR should also be changed. The +* \ref CY_CORTEX_M4_APPL_ADDR macro should be used as the parameter for the +* Cy_SysEnableCM4() function call. +* +* Change the flash and RAM sizes by editing the macros value in the +* linker files for both CPUs: +* - 'xx_cm0plus.ld', where 'xx' is the device group: +* \code +* flash (rx) : ORIGIN = 0x10000000, LENGTH = 0x00080000 +* ram (rwx) : ORIGIN = 0x08000000, LENGTH = 0x00024000 +* \endcode +* - 'xx_cm4_dual.ld', where 'xx' is the device group: +* \code +* flash (rx) : ORIGIN = 0x10080000, LENGTH = 0x00080000 +* ram (rwx) : ORIGIN = 0x08024000, LENGTH = 0x00023800 +* \endcode +* +* Change the value of the \ref CY_CORTEX_M4_APPL_ADDR macro to the rom ORIGIN's +* value in the 'xx_cm4_dual.ld' file, where 'xx' is the device group. Do this +* by either: +* - Passing the following commands to the compiler:\n +* \code -D CY_CORTEX_M4_APPL_ADDR=0x10080000 \endcode +* - Editing the \ref CY_CORTEX_M4_APPL_ADDR value in the 'system_xx.h', where 'xx' is device family:\n +* \code #define CY_CORTEX_M4_APPL_ADDR (0x10080000u) \endcode +* +* ARM MDK\n +* The flash and RAM sections for the CPU are defined in the linker files: +* 'xx_yy.scat', where 'xx' is the device group, and 'yy' is the target CPU; for example, +* 'cy8c6xx7_cm0plus.scat' and 'cy8c6xx7_cm4_dual.scat'. +* \note If the start of the Cortex-M4 application image is changed, the value +* of the of the \ref CY_CORTEX_M4_APPL_ADDR should also be changed. The +* \ref CY_CORTEX_M4_APPL_ADDR macro should be used as the parameter for the \ref +* Cy_SysEnableCM4() function call. +* +* \note The linker files provided with the PDL are generic and handle all common +* use cases. Your project may not use every section defined in the linker files. +* In that case you may see the warnings during the build process: +* L6314W (no section matches pattern) and/or L6329W +* (pattern only matches removed unused sections). In your project, you can +* suppress the warning by passing the "--diag_suppress=L6314W,L6329W" option to +* the linker. You can also comment out or remove the relevant code in the linker +* file. +* +* Change the flash and RAM sizes by editing the macros value in the +* linker files for both CPUs: +* - 'xx_cm0plus.scat', where 'xx' is the device group: +* \code +* #define FLASH_START 0x10000000 +* #define FLASH_SIZE 0x00080000 +* #define RAM_START 0x08000000 +* #define RAM_SIZE 0x00024000 +* \endcode +* - 'xx_cm4_dual.scat', where 'xx' is the device group: +* \code +* #define FLASH_START 0x10080000 +* #define FLASH_SIZE 0x00080000 +* #define RAM_START 0x08024000 +* #define RAM_SIZE 0x00023800 +* \endcode +* +* Change the value of the \ref CY_CORTEX_M4_APPL_ADDR macro to the FLASH_START +* value in the 'xx_cm4_dual.scat' file, +* where 'xx' is the device group. Do this by either: +* - Passing the following commands to the compiler:\n +* \code -D CY_CORTEX_M4_APPL_ADDR=0x10080000 \endcode +* - Editing the \ref CY_CORTEX_M4_APPL_ADDR value in the 'system_xx.h', where +* 'xx' is device family:\n +* \code #define CY_CORTEX_M4_APPL_ADDR (0x10080000u) \endcode +* +* IAR\n +* The flash and RAM sections for the CPU are defined in the linker files: +* 'xx_yy.icf', where 'xx' is the device group, and 'yy' is the target CPU; for example, +* 'cy8c6xx7_cm0plus.icf' and 'cy8c6xx7_cm4_dual.icf'. +* \note If the start of the Cortex-M4 application image is changed, the value +* of the of the \ref CY_CORTEX_M4_APPL_ADDR should also be changed. The +* \ref CY_CORTEX_M4_APPL_ADDR macro should be used as the parameter for the \ref +* Cy_SysEnableCM4() function call. +* +* Change the flash and RAM sizes by editing the macros value in the +* linker files for both CPUs: +* - 'xx_cm0plus.icf', where 'xx' is the device group: +* \code +* define symbol __ICFEDIT_region_IROM1_start__ = 0x10000000; +* define symbol __ICFEDIT_region_IROM1_end__ = 0x10080000; +* define symbol __ICFEDIT_region_IRAM1_start__ = 0x08000000; +* define symbol __ICFEDIT_region_IRAM1_end__ = 0x08024000; +* \endcode +* - 'xx_cm4_dual.icf', where 'xx' is the device group: +* \code +* define symbol __ICFEDIT_region_IROM1_start__ = 0x10080000; +* define symbol __ICFEDIT_region_IROM1_end__ = 0x10100000; +* define symbol __ICFEDIT_region_IRAM1_start__ = 0x08024000; +* define symbol __ICFEDIT_region_IRAM1_end__ = 0x08047800; +* \endcode +* +* Change the value of the \ref CY_CORTEX_M4_APPL_ADDR macro to the +* __ICFEDIT_region_IROM1_start__ value in the 'xx_cm4_dual.icf' file, where 'xx' +* is the device group. Do this by either: +* - Passing the following commands to the compiler:\n +* \code -D CY_CORTEX_M4_APPL_ADDR=0x10080000 \endcode +* - Editing the \ref CY_CORTEX_M4_APPL_ADDR value in the 'system_xx.h', where +* 'xx' is device family:\n +* \code #define CY_CORTEX_M4_APPL_ADDR (0x10080000u) \endcode +* +* \subsection group_system_config_device_initialization Device Initialization +* After a power-on-reset (POR), the boot process is handled by the boot code +* from the on-chip ROM that is always executed by the Cortex-M0+ core. The boot +* code passes the control to the Cortex-M0+ startup code located in flash. +* +* \subsubsection group_system_config_dual_core_device_initialization Dual-Core Devices +* The Cortex-M0+ startup code performs the device initialization by a call to +* SystemInit() and then calls the main() function. The Cortex-M4 core is disabled +* by default. Enable the core using the \ref Cy_SysEnableCM4() function. +* See \ref group_system_config_cm4_functions for more details. +* \note Startup code executes SystemInit() function for the both Cortex-M0+ and Cortex-M4 cores. +* The function has a separate implementation on each core. +* Both function implementations unlock and disable the WDT. +* Therefore enable the WDT after both cores have been initialized. +* +* \subsubsection group_system_config_single_core_device_initialization Single-Core Devices +* The Cortex-M0+ core is not user-accessible on these devices. In this case the +* Flash Boot handles setup of the CM0+ core and starts the Cortex-M4 core. +* +* \subsection group_system_config_heap_stack_config Heap and Stack Configuration +* There are two ways to adjust heap and stack configurations: +* -# Editing source code files +* -# Specifying via command line +* +* By default, the stack size is set to 0x00001000 and the heap size is set to 0x00000400. +* +* \subsubsection group_system_config_heap_stack_config_gcc ARM GCC +* - Editing source code files\n +* The heap and stack sizes are defined in the assembler startup files: +* 'startup_xx_yy.S', where 'xx' is the device family, and 'yy' is the target CPU; +* for example, startup_psoc63_cm0plus.s and startup_psoc63_cm4.s. +* Change the heap and stack sizes by modifying the following lines:\n +* \code .equ Stack_Size, 0x00001000 \endcode +* \code .equ Heap_Size, 0x00000400 \endcode +* +* - Specifying via command line\n +* Change the heap and stack sizes passing the following commands to the compiler:\n +* \code -D __STACK_SIZE=0x000000400 \endcode +* \code -D __HEAP_SIZE=0x000000100 \endcode +* +* \subsubsection group_system_config_heap_stack_config_mdk ARM MDK +* - Editing source code files\n +* The heap and stack sizes are defined in the assembler startup files: +* 'startup_xx_yy.s', where 'xx' is the device family, and 'yy' is the target +* CPU; for example, startup_psoc63_cm0plus.s and startup_psoc63_cm4.s. +* Change the heap and stack sizes by modifying the following lines:\n +* \code Stack_Size EQU 0x00001000 \endcode +* \code Heap_Size EQU 0x00000400 \endcode +* +* - Specifying via command line\n +* Change the heap and stack sizes passing the following commands to the assembler:\n +* \code "--predefine=___STACK_SIZE SETA 0x000000400" \endcode +* \code "--predefine=__HEAP_SIZE SETA 0x000000100" \endcode +* +* \subsubsection group_system_config_heap_stack_config_iar IAR +* - Editing source code files\n +* The heap and stack sizes are defined in the linker scatter files: 'xx_yy.icf', +* where 'xx' is the device family, and 'yy' is the target CPU; for example, +* cy8c6xx7_cm0plus.icf and cy8c6xx7_cm4_dual.icf. +* Change the heap and stack sizes by modifying the following lines:\n +* \code Stack_Size EQU 0x00001000 \endcode +* \code Heap_Size EQU 0x00000400 \endcode +* +* - Specifying via command line\n +* Change the heap and stack sizes passing the following commands to the +* linker (including quotation marks):\n +* \code --define_symbol __STACK_SIZE=0x000000400 \endcode +* \code --define_symbol __HEAP_SIZE=0x000000100 \endcode +* +* \subsection group_system_config_merge_apps Merging CM0+ and CM4 Executables +* The CM0+ project and linker script build the CM0+ application image. Similarly, +* the CM4 linker script builds the CM4 application image. Each specifies +* locations, sizes, and contents of sections in memory. See +* \ref group_system_config_device_memory_definition for the symbols and default +* values. +* +* The cymcuelftool is invoked by a post-build command. The precise project +* setting is IDE-specific. +* +* The cymcuelftool combines the two executables. The tool examines the +* executables to ensure that memory regions either do not overlap, or contain +* identical bytes (shared). If there are no problems, it creates a new ELF file +* with the merged image, without changing any of the addresses or data. +* +* \subsection group_system_config_device_vector_table Vectors Table Copy from Flash to RAM +* This process uses memory sections defined in the linker script. The startup +* code actually defines the contents of the vector table and performs the copy. +* \subsubsection group_system_config_device_vector_table_gcc ARM GCC +* The linker script file is 'xx_yy.ld', where 'xx' is the device family, and +* 'yy' is the target CPU; for example, cy8c6xx7_cm0plus.ld and cy8c6xx7_cm4_dual.ld. +* It defines sections and locations in memory.\n +* Copy interrupt vectors from flash to RAM: \n +* From: \code LONG (__Vectors) \endcode +* To: \code LONG (__ram_vectors_start__) \endcode +* Size: \code LONG (__Vectors_End - __Vectors) \endcode +* The vector table address (and the vector table itself) are defined in the +* assembler startup files: 'startup_xx_yy.S', where 'xx' is the device family, +* and 'yy' is the target CPU; for example, startup_psoc63_cm0plus.S and +* startup_psoc63_cm4.S. The code in these files copies the vector table from +* Flash to RAM. +* \subsubsection group_system_config_device_vector_table_mdk ARM MDK +* The linker script file is 'xx_yy.scat', where 'xx' is the device family, +* and 'yy' is the target CPU; for example, cy8c6xx7_cm0plus.scat and +* cy8c6xx7_cm4_dual.scat. The linker script specifies that the vector table +* (RESET_RAM) shall be first in the RAM section.\n +* RESET_RAM represents the vector table. It is defined in the assembler startup +* files: 'startup_xx_yy.s', where 'xx' is the device family, and 'yy' is the +* target CPU; for example, startup_psoc63_cm0plus.s and startup_psoc63_cm4.s. +* The code in these files copies the vector table from Flash to RAM. +* +* \subsubsection group_system_config_device_vector_table_iar IAR +* The linker script file is 'xx_yy.icf', where 'xx' is the device family, and +* 'yy' is the target CPU; for example, cy8c6xx7_cm0plus.icf and cy8c6xx7_cm4_dual.icf. +* This file defines the .intvec_ram section and its location. +* \code place at start of IRAM1_region { readwrite section .intvec_ram}; \endcode +* The vector table address (and the vector table itself) are defined in the +* assembler startup files: 'startup_xx_yy.s', where 'xx' is the device family, +* and 'yy' is the target CPU; for example, startup_psoc63_cm0plus.s and +* startup_psoc63_cm4.s. The code in these files copies the vector table +* from Flash to RAM. +* +* \section group_system_config_more_information More Information +* Refer to the PDL User Guide for the +* more details. +* +* \section group_system_config_MISRA MISRA Compliance +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
MISRA RuleRule Class (Required/Advisory)Rule DescriptionDescription of Deviation(s)
2.3RThe character sequence // shall not be used within a comment.The comments provide a useful WEB link to the documentation.
+* +* \section group_system_config_changelog Changelog +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
VersionChangesReason for Change
2.10Added constructor attribute to SystemInit() function declaration for ARM MDK compiler. \n +* Removed $Sub$$main symbol for ARM MDK compiler. +* uVision Debugger support.
Updated description of the Startup behavior for Single-Core Devices. \n +* Added note about WDT disabling by SystemInit() function. +* Documentation improvement.
2.0Added restoring of FLL registers to the default state in SystemInit() API for single core devices. +* Single core device support. +*
Added Normal Access Restrictions, Public Key, TOC part2 and TOC part2 copy to Supervisory flash linker memory regions. \n +* Renamed 'wflash' memory region to 'em_eeprom'. +* Linker scripts usability improvement.
Added Cy_IPC_SystemSemaInit(), Cy_IPC_SystemPipeInit(), Cy_Flash_Init() functions call to SystemInit() API.Reserved system resources for internal operations.
Added clearing and releasing of IPC structure #7 (reserved for the Deep-Sleep operations) to SystemInit() API.To avoid deadlocks in case of SW or WDT reset during Deep-Sleep entering.
1.0Initial version
+* +* +* \defgroup group_system_config_macro Macro +* \{ +* \defgroup group_system_config_system_macro System +* \defgroup group_system_config_cm4_status_macro Cortex-M4 Status +* \defgroup group_system_config_user_settings_macro User Settings +* \} +* \defgroup group_system_config_functions Functions +* \{ +* \defgroup group_system_config_system_functions System +* \defgroup group_system_config_cm4_functions Cortex-M4 Control +* \} +* \defgroup group_system_config_globals Global Variables +* +* \} +*/ + +/** +* \addtogroup group_system_config_system_functions +* \{ +* \details +* The following system functions implement CMSIS Core functions. +* Refer to the [CMSIS documentation] +* (http://www.keil.com/pack/doc/CMSIS/Core/html/group__system__init__gr.html "System and Clock Configuration") +* for more details. +* \} +*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +/******************************************************************************* +* Include files +*******************************************************************************/ +#include + + +/******************************************************************************* +* Global preprocessor symbols/macros ('define') +*******************************************************************************/ +#if ((defined(__GNUC__) && (__ARM_ARCH == 6) && (__ARM_ARCH_6M__ == 1)) || \ + (defined (__ICCARM__) && (__CORE__ == __ARM6M__)) || \ + (defined(__ARMCC_VERSION) && (__TARGET_ARCH_THUMB == 3))) + #define CY_SYSTEM_CPU_CM0P 1UL +#else + #define CY_SYSTEM_CPU_CM0P 0UL +#endif + +#if defined (CY_PSOC_CREATOR_USED) && (CY_PSOC_CREATOR_USED == 1U) + #include "cyfitter.h" +#endif /* (CY_PSOC_CREATOR_USED) && (CY_PSOC_CREATOR_USED == 1U) */ + + +/******************************************************************************* +* +* START OF USER SETTINGS HERE +* =========================== +* +* All lines with '<<<' can be set by user. +* +*******************************************************************************/ + +/** +* \addtogroup group_system_config_user_settings_macro +* \{ +*/ + + +#if defined (CYDEV_CLK_EXTCLK__HZ) + #define CY_CLK_EXT_FREQ_HZ (CYDEV_CLK_EXTCLK__HZ) +#else + /***************************************************************************//** + * External Clock Frequency (in Hz, [value]UL). If compiled within + * PSoC Creator and the clock is enabled in the DWR, the value from DWR used. + * Otherwise, edit the value below. + * (USER SETTING) + *******************************************************************************/ + #define CY_CLK_EXT_FREQ_HZ (24000000UL) /* <<< 24 MHz */ +#endif /* (CYDEV_CLK_EXTCLK__HZ) */ + + +#if defined (CYDEV_CLK_ECO__HZ) + #define CY_CLK_ECO_FREQ_HZ (CYDEV_CLK_ECO__HZ) +#else + /***************************************************************************//** + * \brief External crystal oscillator frequency (in Hz, [value]UL). If compiled + * within PSoC Creator and the clock is enabled in the DWR, the value from DWR + * used. + * (USER SETTING) + *******************************************************************************/ + #define CY_CLK_ECO_FREQ_HZ (24000000UL) /* <<< 24 MHz */ +#endif /* (CYDEV_CLK_ECO__HZ) */ + + +#if defined (CYDEV_CLK_ALTHF__HZ) + #define CY_CLK_ALTHF_FREQ_HZ (CYDEV_CLK_ALTHF__HZ) +#else + /***************************************************************************//** + * \brief Alternate high frequency (in Hz, [value]UL). If compiled within + * PSoC Creator and the clock is enabled in the DWR, the value from DWR used. + * Otherwise, edit the value below. + * (USER SETTING) + *******************************************************************************/ + #define CY_CLK_ALTHF_FREQ_HZ (32000000UL) /* <<< 32 MHz */ +#endif /* (CYDEV_CLK_ALTHF__HZ) */ + + +/***************************************************************************//** +* \brief Start address of the Cortex-M4 application ([address]UL) +* (USER SETTING) +*******************************************************************************/ +#define CY_CORTEX_M4_APPL_ADDR (0x10080000UL) /* <<< 512 KB reserved for the Cortex-M0+ application */ + + +/******************************************************************************* +* +* END OF USER SETTINGS HERE +* ========================= +* +*******************************************************************************/ + +/** \} group_system_config_user_settings_macro */ + + +/** +* \addtogroup group_system_config_system_macro +* \{ +*/ + +#if (CY_SYSTEM_CPU_CM0P == 1UL) || defined(CY_DOXYGEN) + /** The Cortex-M0+ startup driver identifier */ + #define CY_STARTUP_M0P_ID ((uint32_t)((uint32_t)((0x0Eu) & 0x3FFFu) << 18u)) +#endif /* (CY_SYSTEM_CPU_CM0P == 1UL) */ + +#if (CY_SYSTEM_CPU_CM0P != 1UL) || defined(CY_DOXYGEN) + /** The Cortex-M4 startup driver identifier */ + #define CY_STARTUP_M4_ID ((uint32_t)((uint32_t)((0x0Fu) & 0x3FFFu) << 18u)) +#endif /* (CY_SYSTEM_CPU_CM0P != 1UL) */ + +/** \} group_system_config_system_macro */ + + +/** +* \addtogroup group_system_config_system_functions +* \{ +*/ +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); +/** \} group_system_config_system_functions */ + + +/** +* \addtogroup group_system_config_cm4_functions +* \{ +*/ +extern uint32_t Cy_SysGetCM4Status(void); +extern void Cy_SysEnableCM4(uint32_t vectorTableOffset); +extern void Cy_SysDisableCM4(void); +extern void Cy_SysRetainCM4(void); +extern void Cy_SysResetCM4(void); +/** \} group_system_config_cm4_functions */ + + +/** \cond */ +extern void Default_Handler (void); +extern uint32_t Cy_SaveIRQ(void); +extern void Cy_RestoreIRQ(uint32_t saved); + +extern void Cy_SystemInit(void); +extern void Cy_SystemInitFpuEnable(void); + +extern uint32_t cy_delayFreqHz; +extern uint32_t cy_delayFreqKhz; +extern uint8_t cy_delayFreqMhz; +extern uint32_t cy_delay32kMs; +/** \endcond */ + + +#if (CY_SYSTEM_CPU_CM0P == 1UL) || defined(CY_DOXYGEN) +/** +* \addtogroup group_system_config_cm4_status_macro +* \{ +*/ +#define CY_SYS_CM4_STATUS_ENABLED (3u) /**< The Cortex-M4 core is enabled: power on, clock on, no isolate, no reset and no retain. */ +#define CY_SYS_CM4_STATUS_DISABLED (0u) /**< The Cortex-M4 core is disabled: power off, clock off, isolate, reset and no retain. */ +#define CY_SYS_CM4_STATUS_RETAINED (2u) /**< The Cortex-M4 core is retained. power off, clock off, isolate, no reset and retain. */ +#define CY_SYS_CM4_STATUS_RESET (1u) /**< The Cortex-M4 core is in the Reset mode: clock off, no isolated, no retain and reset. */ +/** \} group_system_config_cm4_status_macro */ + +#endif /* (CY_SYSTEM_CPU_CM0P == 1UL) */ + +/** \addtogroup group_system_config_globals +* \{ +*/ + +extern uint32_t SystemCoreClock; +extern uint32_t cy_BleEcoClockFreqHz; +extern uint32_t cy_Hfclk0FreqHz; +extern uint32_t cy_PeriClkFreqHz; + +/** \} group_system_config_globals */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYSTEM_PSOC63_H_ */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/ipc_rpc.h b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/ipc_rpc.h new file mode 100644 index 0000000000..581aca85ce --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/ipc_rpc.h @@ -0,0 +1,77 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#ifndef IPC_RPC_H +#define IPC_RPC_H + +#include + +#if defined(__MBED__) +#define IPCPIPE_ASSERT MBED_ASSERT +#include "mbed_assert.h" +#else +#include "project.h" +#define IPCPIPE_ASSERT CY_ASSERT +#endif + +#define IPCRPC_MAX_ARGUMENTS 8 + +/** IPC RPC message data structure + * Used to pass RPC call arguments to M0 core for execution + */ +typedef struct { + uint32_t client_id; ///< Client ID of the RPC client + uint32_t result; ///< Function execution result returned from callee to caller + uint32_t args_num; ///< Number of arguments to RPC function call + uint32_t args[IPCRPC_MAX_ARGUMENTS]; ///< Arguments of RPC function call +} IpcRpcMessage; + + +/** IPC RPC message buffer + * Used to hold and transfer RPC message + */ +typedef struct { + volatile uint8_t busy_flag; ///< Indicates whether the RPC call using this buffer is in progress + IpcRpcMessage message; ///< RPC message associated with a call +} IpcRpcBuffer; + + +/** Function handling the RPC call + * It packs its arguments into the RPC message buffer, initializes transfer + * and waits for completion. + * + * @param call_id unique identifier of the RPC API function to be executed + * @param args_num number of call arguments + * @param ... call arguments + * + * @return call result (as returned by executed function) + */ +uint32_t ipcrpc_call(uint32_t call_id, uint32_t args_num, ...); + +#if defined(__cplusplus) +extern "C" { +#endif +/** Initialization function for RPC mechanism. + * Generated automatically during wrapper generation; needs to be called from startup code. + */ +void ipcrpc_init(void); +#if defined(__cplusplus) +} +#endif + +#endif /* IPC_RPC_H */ +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/psoc6_static_srm.h b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/psoc6_static_srm.h new file mode 100644 index 0000000000..9a1f9870c0 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_CY8C63XX/psoc6_static_srm.h @@ -0,0 +1,74 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + + */ + +/* + * This file defines hardware resources statically allocated to M0 core + * when static resource managemnt is used. + * + * There are 4 classes of resources that must be declared here: + * - M0_ASSIGNED_PORTS macro defines which ports and pins are reserved + * for M0 core use. + * You define these as a colon separated list of ports and pins reserved + * using macro SRM_PORT(port_num, pins), one time for each reserved port. + * SRM_PORT macro arguments are port number, in the range 0 .. 14 and + * pins is a hex value with a bit set for each reserved pin on a port. + * + * - M0_ASSIGNED_DIVIDERS macro defines which clock dividers are reserved + * for M0 core use. + * You define these as a colon separated list of dividers reserved + * using macro SRM_DIVIDER(type, reservations), one time for each required + * devider type. + * SRM_DIVIDER arguments are divider type, one of cy_en_divider_types_t + * values and reservations is a hex mask value with a bit set for each + * reserved divider of a given type. + * + * - M0_ASSIGNED_SCBS macro defines which SCB blocks are reserved + * for M0 core use. + * You define these as a colon separated list of SCBs reserved using + * macro SRM_SCB(n), which argument is SCB number in a range 0 .. 7. + * + * - M0_ASSIGNED_TCPWM macro defines which TCPWM blocks are reserved + * for M0 core use. + * You define these as a colon separated list of TCPWMs reserved using + * macro SRM_TCPWM(n), which argument is TCPWM number in a range 0 .. 31. + * + * If a particular resource class is not used at all by M0 core you can + * skip defining relevant M0_ASSIGNED_* macro or define it as an empty one. + * + * Examples: + * #define M0_ASSIGNED_PORTS SRM_PORT(0, 0x30), SRM_PORT(5, 0x03) + * + * #define M0_ASSIGNED_DIVIDERS SRM_DIVIDER(CY_SYSCLK_DIV_8_BIT, 0x01) + * + * #define M0_ASSIGNED_SCBS SRM_SCB(2) + * + * #define M0_ASSIGNED_TCPWMS + * + */ + +// Reservations below apply to default M0 hex image. + +// P0_0 and p0_1 reserved for WCO, P6-6 and P6_7 reserved for SWD +#define M0_ASSIGNED_PORTS SRM_PORT(0, 0x03), SRM_PORT(6, 0xc0), SRM_PORT(11, 0x02) +// 8-bit divider 0 reserved for us ticker. +#define M0_ASSIGNED_DIVIDERS SRM_DIVIDER(CY_SYSCLK_DIV_8_BIT, 0x01), \ + SRM_DIVIDER(CY_SYSCLK_DIV_16_BIT, 0x01) +#define M0_ASSIGNED_SCBS +#define M0_ASSIGNED_TCPWMS + +/* End of File */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_FUTURE_SEQUANA/PinNames.h b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_FUTURE_SEQUANA/PinNames.h new file mode 100644 index 0000000000..10a8f6dd41 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_FUTURE_SEQUANA/PinNames.h @@ -0,0 +1,253 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#ifndef MBED_PINNAMES_H +#define MBED_PINNAMES_H + +#include "cmsis.h" +#include "PinNamesTypes.h" +#include "PortNames.h" + +#if PSOC6_ENABLE_M0_M4_DEBUG + +#define CY_STDIO_UART_RX P9_0 +#define CY_STDIO_UART_TX P9_1 +#define CY_STDIO_UART_CTS P9_2 +#define CY_STDIO_UART_RTS P9_3 +#else + +#define CY_STDIO_UART_RX P5_0 +#define CY_STDIO_UART_TX P5_1 +#define CY_STDIO_UART_CTS P5_2 +#define CY_STDIO_UART_RTS P5_3 + +#endif // PSOC6_ENABLE_M0_M4_DEBUG + +// PinName[15-0] = Port[15-8] + Pin[7-0] +typedef enum { + P0_0 = (Port0 << 8) + 0x00, + P0_1 = (Port0 << 8) + 0x01, + P0_2 = (Port0 << 8) + 0x02, + P0_3 = (Port0 << 8) + 0x03, + P0_4 = (Port0 << 8) + 0x04, + P0_5 = (Port0 << 8) + 0x05, + P0_6 = (Port0 << 8) + 0x06, + P0_7 = (Port0 << 8) + 0x07, + + P1_0 = (Port1 << 8) + 0x00, + P1_1 = (Port1 << 8) + 0x01, + P1_2 = (Port1 << 8) + 0x02, + P1_3 = (Port1 << 8) + 0x03, + P1_4 = (Port1 << 8) + 0x04, + P1_5 = (Port1 << 8) + 0x05, + P1_6 = (Port1 << 8) + 0x06, + P1_7 = (Port1 << 8) + 0x07, + + P2_0 = (Port2 << 8) + 0x00, + P2_1 = (Port2 << 8) + 0x01, + P2_2 = (Port2 << 8) + 0x02, + P2_3 = (Port2 << 8) + 0x03, + P2_4 = (Port2 << 8) + 0x04, + P2_5 = (Port2 << 8) + 0x05, + P2_6 = (Port2 << 8) + 0x06, + P2_7 = (Port2 << 8) + 0x07, + + P3_0 = (Port3 << 8) + 0x00, + P3_1 = (Port3 << 8) + 0x01, + P3_2 = (Port3 << 8) + 0x02, + P3_3 = (Port3 << 8) + 0x03, + P3_4 = (Port3 << 8) + 0x04, + P3_5 = (Port3 << 8) + 0x05, + P3_6 = (Port3 << 8) + 0x06, + P3_7 = (Port3 << 8) + 0x07, + + P4_0 = (Port4 << 8) + 0x00, + P4_1 = (Port4 << 8) + 0x01, + P4_2 = (Port4 << 8) + 0x02, + P4_3 = (Port4 << 8) + 0x03, + P4_4 = (Port4 << 8) + 0x04, + P4_5 = (Port4 << 8) + 0x05, + P4_6 = (Port4 << 8) + 0x06, + P4_7 = (Port4 << 8) + 0x07, + + P5_0 = (Port5 << 8) + 0x00, + P5_1 = (Port5 << 8) + 0x01, + P5_2 = (Port5 << 8) + 0x02, + P5_3 = (Port5 << 8) + 0x03, + P5_4 = (Port5 << 8) + 0x04, + P5_5 = (Port5 << 8) + 0x05, + P5_6 = (Port5 << 8) + 0x06, + P5_7 = (Port5 << 8) + 0x07, + + P6_0 = (Port6 << 8) + 0x00, + P6_1 = (Port6 << 8) + 0x01, + P6_2 = (Port6 << 8) + 0x02, + P6_3 = (Port6 << 8) + 0x03, + P6_4 = (Port6 << 8) + 0x04, + P6_5 = (Port6 << 8) + 0x05, + P6_6 = (Port6 << 8) + 0x06, + P6_7 = (Port6 << 8) + 0x07, + + P7_0 = (Port7 << 8) + 0x00, + P7_1 = (Port7 << 8) + 0x01, + P7_2 = (Port7 << 8) + 0x02, + P7_3 = (Port7 << 8) + 0x03, + P7_4 = (Port7 << 8) + 0x04, + P7_5 = (Port7 << 8) + 0x05, + P7_6 = (Port7 << 8) + 0x06, + P7_7 = (Port7 << 8) + 0x07, + + P8_0 = (Port8 << 8) + 0x00, + P8_1 = (Port8 << 8) + 0x01, + P8_2 = (Port8 << 8) + 0x02, + P8_3 = (Port8 << 8) + 0x03, + P8_4 = (Port8 << 8) + 0x04, + P8_5 = (Port8 << 8) + 0x05, + P8_6 = (Port8 << 8) + 0x06, + P8_7 = (Port8 << 8) + 0x07, + + P9_0 = (Port9 << 8) + 0x00, + P9_1 = (Port9 << 8) + 0x01, + P9_2 = (Port9 << 8) + 0x02, + P9_3 = (Port9 << 8) + 0x03, + P9_4 = (Port9 << 8) + 0x04, + P9_5 = (Port9 << 8) + 0x05, + P9_6 = (Port9 << 8) + 0x06, + P9_7 = (Port9 << 8) + 0x07, + + P10_0 = (Port10 << 8) + 0x00, + P10_1 = (Port10 << 8) + 0x01, + P10_2 = (Port10 << 8) + 0x02, + P10_3 = (Port10 << 8) + 0x03, + P10_4 = (Port10 << 8) + 0x04, + P10_5 = (Port10 << 8) + 0x05, + P10_6 = (Port10 << 8) + 0x06, + P10_7 = (Port10 << 8) + 0x07, + + P11_0 = (Port11 << 8) + 0x00, + P11_1 = (Port11 << 8) + 0x01, + P11_2 = (Port11 << 8) + 0x02, + P11_3 = (Port11 << 8) + 0x03, + P11_4 = (Port11 << 8) + 0x04, + P11_5 = (Port11 << 8) + 0x05, + P11_6 = (Port11 << 8) + 0x06, + P11_7 = (Port11 << 8) + 0x07, + + P12_0 = (Port12 << 8) + 0x00, + P12_1 = (Port12 << 8) + 0x01, + P12_2 = (Port12 << 8) + 0x02, + P12_3 = (Port12 << 8) + 0x03, + P12_4 = (Port12 << 8) + 0x04, + P12_5 = (Port12 << 8) + 0x05, + P12_6 = (Port12 << 8) + 0x06, + P12_7 = (Port12 << 8) + 0x07, + + P13_0 = (Port13 << 8) + 0x00, + P13_1 = (Port13 << 8) + 0x01, + P13_2 = (Port13 << 8) + 0x02, + P13_3 = (Port13 << 8) + 0x03, + P13_4 = (Port13 << 8) + 0x04, + P13_5 = (Port13 << 8) + 0x05, + P13_6 = (Port13 << 8) + 0x06, + P13_7 = (Port13 << 8) + 0x07, + + P14_0 = (Port14 << 8) + 0x00, + P14_1 = (Port14 << 8) + 0x01, + P14_2 = (Port14 << 8) + 0x02, + P14_3 = (Port14 << 8) + 0x03, + P14_4 = (Port14 << 8) + 0x04, + P14_5 = (Port14 << 8) + 0x05, + P14_6 = (Port14 << 8) + 0x06, + P14_7 = (Port14 << 8) + 0x07, + + // Arduino connector namings + A0 = P10_4, + A1 = P10_5, + A2 = P10_2, + A3 = P10_3, + A4 = P10_1, + A5 = P10_0, + + D0 = P6_4, + D1 = P6_5, + D2 = P10_6, + D3 = P12_6, + D4 = P12_7, + D5 = P6_2, + D6 = P6_3, + D7 = P7_2, + D8 = P7_1, + D9 = P7_7, + D10 = P9_4, + D11 = P9_0, + D12 = P9_1, + D13 = P9_2, + D14 = P10_1, + D15 = P10_0, + + // Generic signal names + + I2C_SCL = P10_0, + I2C_SDA = P10_1, + SPI_MOSI = P9_0, + SPI_MISO = P9_1, + SPI_CLK = P9_2, + SPI_CS = P9_3, + UART_RX = P6_4, + UART_TX = P6_5, + + SWITCH2 = P0_4, + LED1 = P6_2, + LED2 = P6_3, + LED3 = P7_2, + LED4 = P6_2, + LED_RED = LED1, + + USER_BUTTON = SWITCH2, + BUTTON1 = USER_BUTTON, + + // Standardized interfaces names + STDIO_UART_TX = CY_STDIO_UART_TX, + STDIO_UART_RX = CY_STDIO_UART_RX, + STDIO_UART_CTS = CY_STDIO_UART_CTS, + STDIO_UART_RTS = CY_STDIO_UART_RTS, + USBTX = CY_STDIO_UART_TX, + USBRX = CY_STDIO_UART_RX, + + // Not connected + NC = (int)0xFFFFFFFF +} PinName; + +// PinName[15-0] = Port[15-8] + Pin[4-0] +static inline unsigned CY_PIN(PinName pin) +{ + return pin & 0x07; +} + +static inline unsigned CY_PORT(PinName pin) +{ + return (pin >> 8) & 0xFF; +} + +// Because MBED pin mapping API does not allow to map multiple instances of the PWM +// to be mapped to the same pin, we create special pin names to force 32-bit PWM unit +// usage instead of standard 16-bit PWM. + +#define PWM32(pin) CY_PIN_FORCE_PWM_32(pin) + + +#endif diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_FUTURE_SEQUANA/TARGET_FUTURE_SEQUANA_M0/board_config.c b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_FUTURE_SEQUANA/TARGET_FUTURE_SEQUANA_M0/board_config.c new file mode 100644 index 0000000000..6570356cfb --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_FUTURE_SEQUANA/TARGET_FUTURE_SEQUANA_M0/board_config.c @@ -0,0 +1,330 @@ + +/******************************************************************************* +* File Name: board_config.c (formerly cyfitter_cfg.c) +* +* PSoC Creator 4.2 +* +* Description: +* This file contains device initialization code. +* Except for the user defined sections in CyClockStartupError(), this file should not be modified. +* This file is automatically generated by PSoC Creator. +* +******************************************************************************** +* Copyright 2007-2018, Cypress Semiconductor Corporation. All rights reserved. +* Copyright 2017-2018, Future Electronics +* SPDX-License-Identifier: Apache-2.0 +********************************************************************************/ + +#include +#include "device.h" +#include "gpio/cy_gpio.h" +#include "syslib/cy_syslib.h" +#include "sysclk/cy_sysclk.h" +#include "systick/cy_systick.h" +#include "sysanalog/cy_sysanalog.h" + +#if FEATURE_BLE +#include "ble/cy_ble_clk.h" +#endif // FEATURE_BLE + +#define CY_NEED_CYCLOCKSTARTUPERROR 1 +#include "syspm/cy_syspm.h" + +#include "psoc6_utils.h" + +#if defined(__GNUC__) || defined(__ARMCC_VERSION) +#define CYPACKED +#define CYPACKED_ATTR __attribute__ ((packed)) +#define CYALIGNED __attribute__ ((aligned)) +#define CY_CFG_UNUSED __attribute__ ((unused)) +#ifndef CY_CFG_SECTION +#define CY_CFG_SECTION __attribute__ ((section(".psocinit"))) +#endif + +#if defined(__ARMCC_VERSION) +#define CY_CFG_MEMORY_BARRIER() __memory_changed() +#else +#define CY_CFG_MEMORY_BARRIER() __sync_synchronize() +#endif + +#elif defined(__ICCARM__) +#include + +#define CYPACKED __packed +#define CYPACKED_ATTR +#define CYALIGNED _Pragma("data_alignment=4") +#define CY_CFG_UNUSED _Pragma("diag_suppress=Pe177") +#define CY_CFG_SECTION _Pragma("location=\".psocinit\"") + +#define CY_CFG_MEMORY_BARRIER() __DMB() + +#else +#error Unsupported toolchain +#endif + +#ifndef CYCODE +#define CYCODE +#endif +#ifndef CYDATA +#define CYDATA +#endif +#ifndef CYFAR +#define CYFAR +#endif +#ifndef CYXDATA +#define CYXDATA +#endif + + +CY_CFG_UNUSED +static void CYMEMZERO(void *s, size_t n); +CY_CFG_UNUSED +static void CYMEMZERO(void *s, size_t n) +{ + (void)memset(s, 0, n); +} +CY_CFG_UNUSED +static void CYCONFIGCPY(void *dest, const void *src, size_t n); +CY_CFG_UNUSED +static void CYCONFIGCPY(void *dest, const void *src, size_t n) +{ + (void)memcpy(dest, src, n); +} +CY_CFG_UNUSED +static void CYCONFIGCPYCODE(void *dest, const void *src, size_t n); +CY_CFG_UNUSED +static void CYCONFIGCPYCODE(void *dest, const void *src, size_t n) +{ + (void)memcpy(dest, src, n); +} + + + + +/* Clock startup error codes */ +#define CYCLOCKSTART_NO_ERROR 0u +#define CYCLOCKSTART_XTAL_ERROR 1u +#define CYCLOCKSTART_32KHZ_ERROR 2u +#define CYCLOCKSTART_PLL_ERROR 3u +#define CYCLOCKSTART_FLL_ERROR 4u +#define CYCLOCKSTART_WCO_ERROR 5u + +#ifdef CY_NEED_CYCLOCKSTARTUPERROR +/******************************************************************************* +* Function Name: CyClockStartupError +******************************************************************************** +* Summary: +* If an error is encountered during clock configuration (crystal startup error, +* PLL lock error, etc.), the system will end up here. Unless reimplemented by +* the customer, this function will stop in an infinite loop. +* +* Parameters: +* void +* +* Return: +* void +* +*******************************************************************************/ +CY_CFG_UNUSED +static void CyClockStartupError(uint8 errorCode); +CY_CFG_UNUSED +static void CyClockStartupError(uint8 errorCode) +{ + /* To remove the compiler warning if errorCode not used. */ + errorCode = errorCode; + + /* If we have a clock startup error (bad MHz crystal, PLL lock, etc.), */ + /* we will end up here to allow the customer to implement something to */ + /* deal with the clock condition. */ + +#ifdef CY_CFG_CLOCK_STARTUP_ERROR_CALLBACK + CY_CFG_Clock_Startup_ErrorCallback(); +#else + while(1) {} +#endif /* CY_CFG_CLOCK_STARTUP_ERROR_CALLBACK */ +} +#endif + +static void ClockInit(void) +{ + uint32_t status; + + /* Enable all source clocks */ + status = Cy_SysClk_WcoEnable(500000u); + if (CY_RET_SUCCESS != status) { + CyClockStartupError(CYCLOCKSTART_WCO_ERROR); + } + Cy_SysClk_ClkLfSetSource(CY_SYSCLK_CLKLF_IN_WCO); + +#if FEATURE_BLE + { + cy_stc_ble_bless_eco_cfg_params_t bleCfg = { + .ecoXtalStartUpTime = (785 / 31.25), + .loadCap = ((9.9 - 7.5) / 0.075), + .ecoFreq = CY_BLE_BLESS_ECO_FREQ_32MHZ, + .ecoSysDiv = CY_BLE_SYS_ECO_CLK_DIV_4 + }; + Cy_BLE_EcoStart(&bleCfg); + } +#endif // FEATURE_BLE + + /* Configure CPU clock dividers */ + Cy_SysClk_ClkFastSetDivider(0u); + Cy_SysClk_ClkPeriSetDivider((CY_CLK_HFCLK0_FREQ_HZ / CY_CLK_PERICLK_FREQ_HZ) - 1); + Cy_SysClk_ClkSlowSetDivider((CY_CLK_PERICLK_FREQ_HZ / CY_CLK_SYSTEM_FREQ_HZ) - 1); + + /* Configure LF & HF clocks */ + Cy_SysClk_ClkHfSetSource(0u, CY_SYSCLK_CLKHF_IN_CLKPATH1); + Cy_SysClk_ClkHfSetDivider(0u, CY_SYSCLK_CLKHF_NO_DIVIDE); + Cy_SysClk_ClkHfEnable(0u); + + /* Configure Path Clocks */ + /* PLL path is used to clock HF domain from BLE ECO */ + Cy_SysClk_ClkPathSetSource(2, CY_SYSCLK_CLKPATH_IN_IMO); + Cy_SysClk_ClkPathSetSource(3, CY_SYSCLK_CLKPATH_IN_IMO); + Cy_SysClk_ClkPathSetSource(4, CY_SYSCLK_CLKPATH_IN_IMO); +#if FEATURE_BLE + Cy_SysClk_ClkPathSetSource(0, CY_SYSCLK_CLKPATH_IN_ALTHF); + Cy_SysClk_ClkPathSetSource(1, CY_SYSCLK_CLKPATH_IN_ALTHF); + { + const cy_stc_pll_config_t pllConfig = { + .inputFreq = CY_CLK_ALTHF_FREQ_HZ, + .outputFreq = CY_CLK_HFCLK0_FREQ_HZ, + .lfMode = false, + .outputMode = CY_SYSCLK_FLLPLL_OUTPUT_AUTO + }; +#else + Cy_SysClk_ClkPathSetSource(0, CY_SYSCLK_CLKPATH_IN_IMO); + Cy_SysClk_ClkPathSetSource(1, CY_SYSCLK_CLKPATH_IN_IMO); + { + const cy_stc_pll_config_t pllConfig = { + .inputFreq = CY_CLK_IMO_FREQ_HZ, + .outputFreq = CY_CLK_HFCLK0_FREQ_HZ, + .lfMode = false, + .outputMode = CY_SYSCLK_FLLPLL_OUTPUT_AUTO + }; +#endif // FEATURE_BLE + status = Cy_SysClk_PllConfigure(1u, &pllConfig); + if (CY_SYSCLK_SUCCESS != status) { + CyClockStartupError(CYCLOCKSTART_PLL_ERROR); + } + } + status = Cy_SysClk_PllEnable(1u, 10000u); + if (CY_SYSCLK_SUCCESS != status) { + CyClockStartupError(CYCLOCKSTART_PLL_ERROR); + } + + /* Configure miscellaneous clocks */ + Cy_SysClk_ClkTimerSetSource(CY_SYSCLK_CLKTIMER_IN_HF0_NODIV); + Cy_SysClk_ClkTimerSetDivider(0); + Cy_SysClk_ClkTimerEnable(); + Cy_SysClk_ClkPumpSetSource(CY_SYSCLK_PUMP_IN_CLKPATH0); + Cy_SysClk_ClkPumpSetDivider(CY_SYSCLK_PUMP_DIV_4); + Cy_SysClk_ClkPumpEnable(); + Cy_SysClk_ClkBakSetSource(CY_SYSCLK_BAK_IN_WCO); + + /* Disable unused clocks started by default */ + Cy_SysClk_IloDisable(); + + /* Set memory wait states based on HFClk[0] */ + Cy_SysLib_SetWaitStates(false, (CY_CLK_HFCLK0_FREQ_HZ + 990000) / 1000000UL); +} + + +/* Analog API Functions */ + + +/******************************************************************************* +* Function Name: AnalogSetDefault +******************************************************************************** +* +* Summary: +* Sets up the analog portions of the chip to default values based on chip +* configuration options from the project. +* +* Parameters: +* void +* +* Return: +* void +* +*******************************************************************************/ +static void AnalogSetDefault(void) +{ + const cy_stc_sysanalog_config_t config = { + .startup = CY_SYSANALOG_STARTUP_NORMAL, + .iztat = CY_SYSANALOG_IZTAT_SOURCE_LOCAL, + .vref = CY_SYSANALOG_VREF_SOURCE_LOCAL_1_2V, + .deepSleep = CY_SYSANALOG_DEEPSLEEP_IPTAT_1 + }; + Cy_SysAnalog_Init(&config); + Cy_SysAnalog_Enable(); +} + + + + +/******************************************************************************* +* Function Name: Cy_SystemInit +******************************************************************************** +* Summary: +* This function is called by the start-up code for the selected device. It +* performs all of the necessary device configuration based on the design +* settings. This includes settings from the Design Wide Resources (DWR) such +* as Clocks and Pins as well as any component configuration that is necessary. +* +* Parameters: +* void +* +* Return: +* void +* +*******************************************************************************/ + +void Cy_SystemInit(void) +{ + /* Set worst case memory wait states (150 MHz), ClockInit() will update */ + Cy_SysLib_SetWaitStates(false, 150); + + if(0u == Cy_SysLib_GetResetReason()) { /* POR, XRES, or BOD */ + Cy_SysLib_ResetBackupDomain(); + } + + /* Power Mode */ + Cy_SysPm_LdoSetVoltage(CY_SYSPM_LDO_VOLTAGE_1_1V); + + /* PMIC Control */ + Cy_SysPm_UnlockPmic(); + Cy_SysPm_DisablePmicOutput(); + + /* Pin0_0 and Pin0_1 drive WCO, configure as analog before configuring clock */ + cy_reserve_io_pin(P0_0); + cy_reserve_io_pin(P0_1); + Cy_GPIO_Pin_FastInit(GPIO_PRT0, 0, CY_GPIO_DM_ANALOG, 0, P0_0_GPIO); + Cy_GPIO_Pin_FastInit(GPIO_PRT0, 1, CY_GPIO_DM_ANALOG, 0, P0_1_GPIO); + + /* Clock */ + ClockInit(); + + /******* Pre-defined port configuration section ********/ + { + /* RGB LED is P_0_3 (R), P_1_1 (G) and P_11_1 (B) */ + const uint32_t led_off = 1; + Cy_GPIO_Pin_FastInit(GPIO_PRT0, 3, CY_GPIO_DM_STRONG_IN_OFF, led_off, P0_3_GPIO); + Cy_GPIO_Pin_FastInit(GPIO_PRT1, 1, CY_GPIO_DM_STRONG_IN_OFF, led_off, P1_1_GPIO); + Cy_GPIO_Pin_FastInit(GPIO_PRT11, 1, CY_GPIO_DM_STRONG_IN_OFF, led_off, P11_1_GPIO); + + /* USER BUTTON is P_0_4 */ + Cy_GPIO_Pin_FastInit(GPIO_PRT0, 4, CY_GPIO_DM_PULLUP, 1, P0_4_GPIO); + + /* Configure hw debug interface on port 6 */ + cy_reserve_io_pin(P6_6); + cy_reserve_io_pin(P6_7); + Cy_GPIO_Pin_FastInit(GPIO_PRT6, 6, CY_GPIO_DM_PULLUP, 0, P6_6_CPUSS_SWJ_SWDIO_TMS); + Cy_GPIO_Pin_FastInit(GPIO_PRT6, 7, CY_GPIO_DM_PULLDOWN, 0, P6_7_CPUSS_SWJ_SWCLK_TCLK); + } + + /* Perform basic analog initialization to defaults */ + AnalogSetDefault(); + +} diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_FUTURE_SEQUANA/stdio_init.cpp b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_FUTURE_SEQUANA/stdio_init.cpp new file mode 100644 index 0000000000..5aabfe4b3b --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/TARGET_FUTURE_SEQUANA/stdio_init.cpp @@ -0,0 +1,30 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#include "mbed.h" + +/* + * This makes sure, stdio serial is initialized on M4 core at the very beginning + * and outside of any critical context, so printf is usable anywhere, including + * interrupt and fault handlers. + * Hardware devices cannot be initialized in the interrupt or critical section context + * on PSoC 6 M4 core. + */ + +#if DEVICE_STDIO_MESSAGES && !defined(TARGET_MCU_PSOC6_M0) +Serial _stdio_uart_object(STDIO_UART_TX, STDIO_UART_RX); +#endif diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/analogin_api.c b/targets/TARGET_Cypress/TARGET_PSOC6/analogin_api.c new file mode 100644 index 0000000000..9e57aa551b --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/analogin_api.c @@ -0,0 +1,171 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#include "device.h" +#include "analogin_api.h" +#include "cy_sar.h" +#include "psoc6_utils.h" +#include "mbed_assert.h" +#include "mbed_error.h" +#include "pinmap.h" +#include "PeripheralPins.h" +#include "platform/mbed_error.h" + +#if DEVICE_ANALOGIN + +const uint16_t ADC_MAX_VALUE = 0x0fff; + +const uint32_t SAR_BASE_CLOCK_HZ = 18000000; // 18 MHz or less + +/** Default SAR channel configuration. + * Notice, that because dynamic SAR MUX switching is disabled, + * per-channel MUX configuration is ignored, thus not configured here. + */ +#define DEFAULT_CHANNEL_CONFIG ( \ + CY_SAR_CHAN_SINGLE_ENDED | \ + CY_SAR_CHAN_AVG_ENABLE | \ + CY_SAR_CHAN_SAMPLE_TIME_0 \ +) + + +/** Global SAR configuration data, modified as channels are configured. + */ +static cy_stc_sar_config_t sar_config = { + .ctrl = CY_SAR_VREF_SEL_VDDA_DIV_2 | + CY_SAR_NEG_SEL_VREF | + CY_SAR_CTRL_COMP_DLY_12 | + CY_SAR_COMP_PWR_50 | + CY_SAR_SARSEQ_SWITCH_DISABLE, /**< Control register */ + .sampleCtrl = CY_SAR_RIGHT_ALIGN | + CY_SAR_SINGLE_ENDED_UNSIGNED | + CY_SAR_AVG_CNT_16 | + CY_SAR_AVG_MODE_SEQUENTIAL_FIXED | + CY_SAR_TRIGGER_MODE_FW_ONLY, /**< Sample control register */ + .sampleTime01 = (4uL << CY_SAR_SAMPLE_TIME0_SHIFT) | + (4uL << CY_SAR_SAMPLE_TIME1_SHIFT), /**< Sample time in ADC clocks for ST0 and ST1 */ + .sampleTime23 = (4uL << CY_SAR_SAMPLE_TIME2_SHIFT) | + (4uL << CY_SAR_SAMPLE_TIME3_SHIFT), /**< Sample time in ADC clocks for ST2 and ST3 */ + .rangeThres = 0, /**< Range detect threshold register for all channels (unused)*/ + .rangeCond = 0, /**< Range detect mode for all channels (unused)*/ + .chanEn = 0, /**< Enable bits for the channels */ + .chanConfig = { /**< Channel configuration registers */ + DEFAULT_CHANNEL_CONFIG, // chn 0 + DEFAULT_CHANNEL_CONFIG, // chn 1 + DEFAULT_CHANNEL_CONFIG, // chn 2 + DEFAULT_CHANNEL_CONFIG, // chn 3 + DEFAULT_CHANNEL_CONFIG, // chn 4 + DEFAULT_CHANNEL_CONFIG, // chn 5 + DEFAULT_CHANNEL_CONFIG, // chn 6 + DEFAULT_CHANNEL_CONFIG, // chn 7 + DEFAULT_CHANNEL_CONFIG, // chn 8 + DEFAULT_CHANNEL_CONFIG, // chn 9 + DEFAULT_CHANNEL_CONFIG, // chn 10 + DEFAULT_CHANNEL_CONFIG, // chn 11 + DEFAULT_CHANNEL_CONFIG, // chn 12 + DEFAULT_CHANNEL_CONFIG, // chn 13 + DEFAULT_CHANNEL_CONFIG, // chn 14 + DEFAULT_CHANNEL_CONFIG, // chn 15 + }, + .intrMask = 0, /**< Interrupt enable mask */ + .satIntrMask = 0, /**< Saturate interrupt mask register */ + .rangeIntrMask = 0, /**< Range interrupt mask register */ + .muxSwitch = 0, /**< SARMUX firmware switches to connect analog signals to SAR */ + .muxSwitchSqCtrl = 0, /**< SARMUX Switch SAR sequencer control */ + .configRouting = false, /**< Configure or ignore routing related registers (muxSwitch, muxSwitchSqCtrl) */ + .vrefMvValue = 0, /**< Reference voltage in millivolts used in counts to volts conversion */ +}; + +static bool sar_initialized = false; + + +static void sar_init(analogin_t *obj) +{ + if (!sar_initialized) { + uint32_t sar_clock_divider = CY_INVALID_DIVIDER; + + sar_initialized = true; + // Allocate and setup clock. + sar_clock_divider = cy_clk_allocate_divider(CY_SYSCLK_DIV_8_BIT); + if (sar_clock_divider == CY_INVALID_DIVIDER) { + error("SAR clock divider allocation failed."); + return; + } + Cy_SysClk_PeriphSetDivider(CY_SYSCLK_DIV_8_BIT, + sar_clock_divider, + ((CY_CLK_PERICLK_FREQ_HZ + SAR_BASE_CLOCK_HZ / 2) / SAR_BASE_CLOCK_HZ) - 1); + Cy_SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_8_BIT, sar_clock_divider); + Cy_SysClk_PeriphAssignDivider(obj->clock, CY_SYSCLK_DIV_8_BIT, sar_clock_divider); + + Cy_SAR_Init(obj->base, &sar_config); + Cy_SAR_Enable(obj->base); + } +} + +void analogin_init(analogin_t *obj, PinName pin) +{ + uint32_t sar = 0; + uint32_t sar_function = 0; + + MBED_ASSERT(obj); + MBED_ASSERT(pin != (PinName)NC); + + + sar = pinmap_peripheral(pin, PinMap_ADC); + if (sar != (uint32_t)NC) { + if (cy_reserve_io_pin(pin)) { + error("ANALOG IN pin reservation conflict."); + } + obj->base = (SAR_Type*)CY_PERIPHERAL_BASE(sar); + obj->pin = pin; + obj->channel_mask = 1 << CY_PIN(pin); + + // Configure clock. + sar_function = pinmap_function(pin, PinMap_ADC); + obj->clock = CY_PIN_CLOCK(sar_function); + sar_init(obj); + pin_function(pin, sar_function); + } else { + error("ANALOG IN pinout mismatch."); + } +} + +float analogin_read(analogin_t *obj) +{ + uint16_t result = analogin_read_u16(obj); + + return (float)result * (1.0 / ADC_MAX_VALUE); +} + +uint16_t analogin_read_u16(analogin_t *obj) +{ + uint32_t result = 0; + + Cy_SAR_SetChanMask(obj->base, obj->channel_mask); + Cy_SAR_SetAnalogSwitch(obj->base, CY_SAR_MUX_SWITCH0, obj->channel_mask, CY_SAR_SWITCH_CLOSE); + Cy_SAR_StartConvert(obj->base, CY_SAR_START_CONVERT_SINGLE_SHOT); + if (Cy_SAR_IsEndConversion(obj->base, CY_SAR_WAIT_FOR_RESULT) == CY_SAR_SUCCESS) { + result = Cy_SAR_GetResult32(obj->base, CY_PIN(obj->pin)); + } else { + error("ANALOG IN: measurement failed!"); + } + Cy_SAR_SetAnalogSwitch(obj->base, CY_SAR_MUX_SWITCH0, obj->channel_mask, CY_SAR_SWITCH_OPEN); + // We are running 16x oversampling extending results to 16 bits. + return (uint16_t)(result); +} + +#endif // DEVICE_ANALOGIN + diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/analogout_api.c b/targets/TARGET_Cypress/TARGET_PSOC6/analogout_api.c new file mode 100644 index 0000000000..98be654530 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/analogout_api.c @@ -0,0 +1,150 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * + * 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. + */ + +#include "device.h" +#include "analogout_api.h" +#include "cy_ctdac.h" +#include "psoc6_utils.h" +#include "mbed_assert.h" +#include "mbed_error.h" +#include "pinmap.h" +#include "PeripheralPins.h" +#include "platform/mbed_error.h" + +#if DEVICE_ANALOGOUT + +#define CTDAC_NUM_BITS 12 +const uint16_t CTDAC_MAX_VALUE = (uint16_t)((1UL << CTDAC_NUM_BITS) - 1); + +const uint32_t CTDAC_BASE_CLOCK_HZ = 500000; // 500 kHz or less + +#define CTDAC_DEGLITCH_CYCLES 35 + + + +/** Global CTDAC configuration data. + */ +static cy_stc_ctdac_config_t ctdac_config = { + .refSource = CY_CTDAC_REFSOURCE_VDDA, /**< Reference source: Vdda or externally through Opamp1 of CTB */ + .formatMode = CY_CTDAC_FORMAT_UNSIGNED, /**< Format of DAC value: signed or unsigned */ + .updateMode = CY_CTDAC_UPDATE_BUFFERED_WRITE, /**< Update mode: direct or buffered writes or hardware, edge or level */ + .deglitchMode = CY_CTDAC_DEGLITCHMODE_UNBUFFERED, /**< Deglitch mode: disabled, buffered, unbuffered, or both */ + .outputMode = CY_CTDAC_OUTPUT_VALUE, /**< Output mode: enabled (value or value + 1), high-z, Vssa, or Vdda */ + .outputBuffer = CY_CTDAC_OUTPUT_UNBUFFERED, /**< Output path: Buffered through Opamp0 of CTB or connected directly to Pin 6 */ + .deepSleep = CY_CTDAC_DEEPSLEEP_DISABLE, /**< Enable or disable the CTDAC during Deep Sleep */ + .deglitchCycles = CTDAC_DEGLITCH_CYCLES, /**< Number of deglitch cycles from 0 to 63 */ + .value = 0, /**< Current DAC value */ + .nextValue = 0, /**< Next DAC value for double buffering */ + .enableInterrupt = false, /**< If true, enable interrupt when next value register is transferred to value register */ + .configClock = false, /**< Configure or ignore clock information */ +}; + + +static bool ctdac_initialized = 0; + +static void ctdac_init(dac_t *obj) +{ + if (!ctdac_initialized) { + uint32_t dac_clock_divider = CY_INVALID_DIVIDER; + + ctdac_initialized = true; + // Allocate and setup clock. + dac_clock_divider = cy_clk_allocate_divider(CY_SYSCLK_DIV_8_BIT); + if (dac_clock_divider == CY_INVALID_DIVIDER) { + error("CTDAC clock divider allocation failed."); + return; + } + Cy_SysClk_PeriphSetDivider(CY_SYSCLK_DIV_8_BIT, + dac_clock_divider, + ((CY_CLK_PERICLK_FREQ_HZ + CTDAC_BASE_CLOCK_HZ / 2) / CTDAC_BASE_CLOCK_HZ) - 1); + Cy_SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_8_BIT, dac_clock_divider); + Cy_SysClk_PeriphAssignDivider(obj->clock, CY_SYSCLK_DIV_8_BIT, dac_clock_divider); + + Cy_CTDAC_Init(obj->base, &ctdac_config); + Cy_CTDAC_Enable(obj->base); + } +} + + +void analogout_init(dac_t *obj, PinName pin) +{ + uint32_t dac = 0; + uint32_t dac_function = 0; + + MBED_ASSERT(obj); + MBED_ASSERT(pin != (PinName)NC); + + dac = pinmap_peripheral(pin, PinMap_DAC); + if (dac != (uint32_t)NC) { + if (cy_reserve_io_pin(pin)) { + error("ANALOG OUT pin reservation conflict."); + } + obj->base = (CTDAC_Type*)CY_PERIPHERAL_BASE(dac); + obj->pin = pin; + + // Configure clock. + dac_function = pinmap_function(pin, PinMap_DAC); + obj->clock = CY_PIN_CLOCK(dac_function); + pin_function(pin, dac_function); + ctdac_init(obj); + } else { + error("ANALOG OUT pinout mismatch."); + } +} + +void analogout_free(dac_t *obj) +{ + // Not supported yet. +} + +void analogout_write(dac_t *obj, float value) +{ + uint32_t val = 0; + + if (value > 1.0) { + val = CTDAC_MAX_VALUE; + } else if (value > 0.0) { + val = value * CTDAC_MAX_VALUE; + } + Cy_CTDAC_SetValueBuffered(obj->base, val); +} + +void analogout_write_u16(dac_t *obj, uint16_t value) +{ + uint32_t val = 0; + + val = (value >> (16 - CTDAC_NUM_BITS)); // Convert from 16-bit range. + + Cy_CTDAC_SetValueBuffered(obj->base, val); +} + +float analogout_read(dac_t *obj) +{ + return (float)analogout_read_u16(obj) / 0xffff; +} + +uint16_t analogout_read_u16(dac_t *obj) +{ + uint16_t value = (obj->base->CTDAC_VAL_NXT >> CTDAC_CTDAC_VAL_NXT_VALUE_Pos) & CTDAC_CTDAC_VAL_NXT_VALUE_Msk; + + value <<= (16 - CTDAC_NUM_BITS); // Convert to 16-bit range. + + return value; +} + +#endif // DEVICE_ANALOGIN + diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/PDL_Version.txt b/targets/TARGET_Cypress/TARGET_PSOC6/device/PDL_Version.txt new file mode 100644 index 0000000000..9cac515901 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/PDL_Version.txt @@ -0,0 +1,2 @@ +version 3.0.1 + diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/README.md b/targets/TARGET_Cypress/TARGET_PSOC6/device/README.md new file mode 100644 index 0000000000..9d2b3a0bdc --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/README.md @@ -0,0 +1,4 @@ +README for Cypress Peripheral Driver Library +============================================ + +This folder tree contains parts of Cypress Peripheral Driver Library (PDL) necessary to support PSoC 6 MCUs. See [Cypress PDL page](http://www.cypress.com/documentation/software-and-drivers/peripheral-driver-library-pdl) for details. diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ctb/cy_ctb.c b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ctb/cy_ctb.c new file mode 100644 index 0000000000..ba0d725b21 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ctb/cy_ctb.c @@ -0,0 +1,1355 @@ +/***************************************************************************//** +* \file cy_ctb.c +* \version 1.0 +* +* \brief +* Provides the public functions for the CTB driver. +* +******************************************************************************** +* \copyright +* Copyright 2017-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include "ctb/cy_ctb.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/*************************************** +* Fast Config Selections +***************************************/ +const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Unused = +{ + /*.oa0Power */ CY_CTB_POWER_OFF, + /*.oa0Mode */ CY_CTB_MODE_OPAMP1X, + /*.oa0SwitchCtrl */ CY_CTB_DEINIT, + /*.ctdSwitchCtrl */ CY_CTB_DEINIT, +}; + +const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Comp = +{ + /*.oa0Power */ CY_CTB_POWER_MEDIUM, + /*.oa0Mode */ CY_CTB_MODE_COMP, + /*.oa0SwitchCtrl */ CY_CTB_DEINIT, + /*.ctdSwitchCtrl */ CY_CTB_DEINIT, +}; + +const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Opamp1x = +{ + /*.oa0Power */ CY_CTB_POWER_MEDIUM, + /*.oa0Mode */ CY_CTB_MODE_OPAMP1X, + /*.oa0SwitchCtrl */ CY_CTB_DEINIT, + /*.ctdSwitchCtrl */ CY_CTB_DEINIT, +}; + +const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Opamp10x = +{ + /*.oa0Power */ CY_CTB_POWER_MEDIUM, + /*.oa0Mode */ CY_CTB_MODE_OPAMP10X, + /*.oa0SwitchCtrl */ CY_CTB_DEINIT, + /*.ctdSwitchCtrl */ CY_CTB_DEINIT, +}; + +const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Diffamp = +{ + /*.oa0Power */ CY_CTB_POWER_MEDIUM, + /*.oa0Mode */ CY_CTB_MODE_OPAMP10X, + /*.oa0SwitchCtrl */ (uint32_t) CY_CTB_SW_OA0_POS_PIN0_MASK | (uint32_t) CY_CTB_SW_OA0_NEG_PIN1_MASK, + /*.ctdSwitchCtrl */ (uint32_t) CY_CTB_SW_CTD_CHOLD_OA0_POS_ISOLATE_MASK, +}; + +const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Vdac_Out = +{ + /*.oa0Power */ CY_CTB_POWER_MEDIUM, + /*.oa0Mode */ CY_CTB_MODE_OPAMP10X, + /*.oa0SwitchCtrl */ (uint32_t) CY_CTB_SW_OA0_NEG_OUT_MASK | (uint32_t) CY_CTB_SW_OA0_OUT_SHORT_1X_10X_MASK, + /*.ctdSwitchCtrl */ (uint32_t) CY_CTB_SW_CTD_OUT_CHOLD_MASK | (uint32_t) CY_CTB_SW_CTD_CHOLD_OA0_POS_MASK, +}; + +const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Vdac_Out_SH = +{ + /*.oa0Power */ CY_CTB_POWER_MEDIUM, + /*.oa0Mode */ CY_CTB_MODE_OPAMP10X, + /*.oa0SwitchCtrl */ (uint32_t) CY_CTB_SW_OA0_NEG_OUT_MASK | (uint32_t) CY_CTB_SW_OA0_OUT_SHORT_1X_10X_MASK, + /*.ctdSwitchCtrl */ (uint32_t) CY_CTB_SW_CTD_OUT_CHOLD_MASK | (uint32_t) CY_CTB_SW_CTD_CHOLD_OA0_POS_MASK | (uint32_t) CY_CTB_SW_CTD_CHOLD_CONNECT_MASK, +}; + +const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Unused = +{ + /*.oa1Power */ CY_CTB_POWER_OFF, + /*.oa1Mode */ CY_CTB_MODE_OPAMP1X, + /*.oa1SwitchCtrl */ CY_CTB_DEINIT, + /*.ctdSwitchCtrl */ CY_CTB_DEINIT, +}; + +const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Comp = +{ + /*.oa1Power */ CY_CTB_POWER_MEDIUM, + /*.oa1Mode */ CY_CTB_MODE_COMP, + /*.oa1SwitchCtrl */ CY_CTB_DEINIT, + /*.ctdSwitchCtrl */ CY_CTB_DEINIT, +}; + +const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Opamp1x = +{ + /*.oa1Power */ CY_CTB_POWER_MEDIUM, + /*.oa1Mode */ CY_CTB_MODE_OPAMP1X, + /*.oa1SwitchCtrl */ CY_CTB_DEINIT, + /*.ctdSwitchCtrl */ CY_CTB_DEINIT, +}; + +const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Opamp10x = +{ + /*.oa1Power */ CY_CTB_POWER_MEDIUM, + /*.oa1Mode */ CY_CTB_MODE_OPAMP10X, + /*.oa1SwitchCtrl */ CY_CTB_DEINIT, + /*.ctdSwitchCtrl */ CY_CTB_DEINIT, +}; + +const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Diffamp = +{ + /*.oa1Power */ CY_CTB_POWER_MEDIUM, + /*.oa1Mode */ CY_CTB_MODE_OPAMP10X, + /*.oa1SwitchCtrl */ (uint32_t) CY_CTB_SW_OA1_POS_PIN7_MASK | (uint32_t) CY_CTB_SW_OA1_NEG_PIN4_MASK, + /*.ctdSwitchCtrl */ CY_CTB_DEINIT, +}; + +const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Vdac_Ref_Aref = +{ + /*.oa1Power */ CY_CTB_POWER_MEDIUM, + /*.oa1Mode */ CY_CTB_MODE_OPAMP1X, + /*.oa1SwitchCtrl */ (uint32_t) CY_CTB_SW_OA1_NEG_OUT_MASK | (uint32_t) CY_CTB_SW_OA1_POS_AREF_MASK, + /*.ctdSwitchCtrl */ (uint32_t) CY_CTB_SW_CTD_REF_OA1_OUT_MASK, +}; + +const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Vdac_Ref_Pin5 = +{ + /*.oa1Power */ CY_CTB_POWER_MEDIUM, + /*.oa1Mode */ CY_CTB_MODE_OPAMP1X, + /*.oa1SwitchCtrl */ (uint32_t) CY_CTB_SW_OA1_NEG_OUT_MASK | (uint32_t) CY_CTB_SW_OA1_POS_PIN5_MASK, + /*.ctdSwitchCtrl */ (uint32_t) CY_CTB_SW_CTD_REF_OA1_OUT_MASK, +}; + +/******************************************************************************* +* Function Name: Cy_CTB_Init +****************************************************************************//** +* +* Initialize or restore the CTB and both opamps according to the +* provided settings. Parameters are usually set only once, at initialization. +* +* \param base +* Pointer to structure describing registers +* +* \param config +* Pointer to structure containing configuration data for entire CTB +* +* \return +* Status of initialization, \ref CY_CTB_SUCCESS or \ref CY_CTB_BAD_PARAM +* +* \funcusage +* +* The following code snippet configures Opamp0 as a comparator +* and Opamp1 as an opamp follower with 10x drive. The terminals +* are routed to external pins by closing the switches shown. +* +* \image html ctb_init_funcusage.png +* \image latex ctb_init_funcusage.png +* +* \snippet ctb_sut_01.cydsn/main_cm0p.c SNIPPET_CTBINIT +* +*******************************************************************************/ +cy_en_ctb_status_t Cy_CTB_Init(CTBM_Type *base, const cy_stc_ctb_config_t *config) +{ + CY_ASSERT_L1(NULL != base); + CY_ASSERT_L1(NULL != config); + + cy_en_ctb_status_t result; + + if ((NULL == base) || (NULL == config)) + { + result = CY_CTB_BAD_PARAM; + } + else + { + CY_ASSERT_L3(CY_CTB_DEEPSLEEP(config->deepSleep)); + + /* Enum checks for Opamp0 config */ + CY_ASSERT_L3(CY_CTB_OAPOWER(config->oa0Power)); + CY_ASSERT_L3(CY_CTB_OAMODE(config->oa0Mode)); + CY_ASSERT_L3(CY_CTB_OAPUMP(config->oa0Pump)); + CY_ASSERT_L3(CY_CTB_COMPEDGE(config->oa0CompEdge)); + CY_ASSERT_L3(CY_CTB_COMPLEVEL(config->oa0CompLevel)); + CY_ASSERT_L3(CY_CTB_COMPBYPASS(config->oa0CompBypass)); + CY_ASSERT_L3(CY_CTB_COMPHYST(config->oa0CompHyst)); + + /* Enum checks for Opamp0 config */ + CY_ASSERT_L3(CY_CTB_OAPOWER(config->oa1Power)); + CY_ASSERT_L3(CY_CTB_OAMODE(config->oa1Mode)); + CY_ASSERT_L3(CY_CTB_OAPUMP(config->oa1Pump)); + CY_ASSERT_L3(CY_CTB_COMPEDGE(config->oa1CompEdge)); + CY_ASSERT_L3(CY_CTB_COMPLEVEL(config->oa1CompLevel)); + CY_ASSERT_L3(CY_CTB_COMPBYPASS(config->oa1CompBypass)); + CY_ASSERT_L3(CY_CTB_COMPHYST(config->oa1CompHyst)); + + /* Boundary checks for analog routing switch masks */ + CY_ASSERT_L2(CY_CTB_OA0SWITCH(config->oa0SwitchCtrl)); + CY_ASSERT_L2(CY_CTB_OA1SWITCH(config->oa1SwitchCtrl)); + CY_ASSERT_L2(CY_CTB_CTDSWITCH(config->ctdSwitchCtrl)); + + base->CTB_CTRL = (uint32_t) config->deepSleep; + base->OA_RES0_CTRL = (uint32_t) config->oa0Power \ + | (uint32_t) config->oa0Mode \ + | (uint32_t) config->oa0Pump \ + | (uint32_t) config->oa0CompEdge \ + | (uint32_t) config->oa0CompLevel \ + | (uint32_t) config->oa0CompBypass \ + | (uint32_t) config->oa0CompHyst \ + | ((CY_CTB_MODE_OPAMP1X == config->oa0Mode) ? CY_CTB_OPAMP_BOOST_ENABLE : CY_CTB_OPAMP_BOOST_DISABLE); + + base->OA_RES1_CTRL = (uint32_t) config->oa1Power \ + | (uint32_t) config->oa1Mode \ + | (uint32_t) config->oa1Pump \ + | (uint32_t) config->oa1CompEdge \ + | (uint32_t) config->oa1CompLevel \ + | (uint32_t) config->oa1CompBypass \ + | (uint32_t) config->oa1CompHyst \ + | ((CY_CTB_MODE_OPAMP1X == config->oa1Mode) ? CY_CTB_OPAMP_BOOST_ENABLE : CY_CTB_OPAMP_BOOST_DISABLE); + + base->INTR_MASK = (config->oa0CompIntrEn ? CTBM_INTR_MASK_COMP0_MASK_Msk : CY_CTB_DEINIT) \ + | (config->oa1CompIntrEn ? CTBM_INTR_MASK_COMP1_MASK_Msk : CY_CTB_DEINIT); + + base->OA0_COMP_TRIM = (uint32_t) ((config->oa0Mode == CY_CTB_MODE_OPAMP10X) ? CY_CTB_OPAMP_COMPENSATION_CAP_MAX: CY_CTB_OPAMP_COMPENSATION_CAP_MIN); + base->OA1_COMP_TRIM = (uint32_t) ((config->oa1Mode == CY_CTB_MODE_OPAMP10X) ? CY_CTB_OPAMP_COMPENSATION_CAP_MAX: CY_CTB_OPAMP_COMPENSATION_CAP_MIN); + + if (config->configRouting) + { + base->OA0_SW = config->oa0SwitchCtrl; + base->OA1_SW = config->oa1SwitchCtrl; + base->CTD_SW = config->ctdSwitchCtrl; + } + + result = CY_CTB_SUCCESS; + } + + return result; +} + +/******************************************************************************* +* Function Name: Cy_CTB_OpampInit +****************************************************************************//** +* +* Initialize each opamp separately without impacting analog routing. +* Intended for use by automatic analog routing and configuration tools +* to configure each opamp without having to integrate the settings with +* those of the other opamp first. +* +* Can also be used to configure both opamps to have the same settings. +* +* \param base +* Pointer to structure describing registers +* +* \param opampNum +* \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH +* +* \param config +* Pointer to structure containing configuration data +* +* \return +* Status of initialization, \ref CY_CTB_SUCCESS or \ref CY_CTB_BAD_PARAM +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm0p.c SNIPPET_OPAMPINIT +* +*******************************************************************************/ +cy_en_ctb_status_t Cy_CTB_OpampInit(CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum, const cy_stc_ctb_opamp_config_t *config) +{ + CY_ASSERT_L1(NULL != base); + CY_ASSERT_L1(NULL != config); + + cy_en_ctb_status_t result; + uint32_t oaResCtrl; + + if ((NULL == base) || (NULL == config)) + { + result = CY_CTB_BAD_PARAM; + } + else + { + CY_ASSERT_L3(CY_CTB_OPAMPNUM(opampNum)); + CY_ASSERT_L3(CY_CTB_DEEPSLEEP(config->deepSleep)); + CY_ASSERT_L3(CY_CTB_OAPOWER(config->oaPower)); + CY_ASSERT_L3(CY_CTB_OAMODE(config->oaMode)); + CY_ASSERT_L3(CY_CTB_OAPUMP(config->oaPump)); + CY_ASSERT_L3(CY_CTB_COMPEDGE(config->oaCompEdge)); + CY_ASSERT_L3(CY_CTB_COMPLEVEL(config->oaCompLevel)); + CY_ASSERT_L3(CY_CTB_COMPBYPASS(config->oaCompBypass)); + CY_ASSERT_L3(CY_CTB_COMPHYST(config->oaCompHyst)); + + base->CTB_CTRL = (uint32_t) config->deepSleep; + + /* The two opamp control registers are symmetrical */ + oaResCtrl = (uint32_t) config->oaPower \ + | (uint32_t) config->oaMode \ + | (uint32_t) config->oaPump \ + | (uint32_t) config->oaCompEdge \ + | (uint32_t) config->oaCompLevel \ + | (uint32_t) config->oaCompBypass \ + | (uint32_t) config->oaCompHyst \ + | ((CY_CTB_MODE_OPAMP1X == config->oaMode) ? CY_CTB_OPAMP_BOOST_ENABLE : CY_CTB_OPAMP_BOOST_DISABLE); + + if ((opampNum == CY_CTB_OPAMP_0) || (opampNum == CY_CTB_OPAMP_BOTH)) + { + base->OA_RES0_CTRL = oaResCtrl; + base->OA0_COMP_TRIM = (uint32_t) ((config->oaMode == CY_CTB_MODE_OPAMP10X) ? CY_CTB_OPAMP_COMPENSATION_CAP_MAX: CY_CTB_OPAMP_COMPENSATION_CAP_MIN); + + /* The INTR_MASK register is shared between the two opamps */ + base->INTR_MASK |= (config->oaCompIntrEn ? CTBM_INTR_MASK_COMP0_MASK_Msk : CY_CTB_DEINIT); + } + + if ((opampNum == CY_CTB_OPAMP_1) || (opampNum == CY_CTB_OPAMP_BOTH)) + { + base->OA_RES1_CTRL = oaResCtrl; + base->OA1_COMP_TRIM = (uint32_t) ((config->oaMode == CY_CTB_MODE_OPAMP10X) ? CY_CTB_OPAMP_COMPENSATION_CAP_MAX: CY_CTB_OPAMP_COMPENSATION_CAP_MIN); + + /* The INTR_MASK register is shared between the two opamps */ + base->INTR_MASK |= (config->oaCompIntrEn ? CTBM_INTR_MASK_COMP1_MASK_Msk : CY_CTB_DEINIT); + } + + result = CY_CTB_SUCCESS; + } + + return result; +} + +/******************************************************************************* +* Function Name: Cy_CTB_DeInit +****************************************************************************//** +* +* Reset CTB registers back to power on reset defaults. +* +* \param base +* Pointer to structure describing registers +* +* \param deInitRouting +* If true, all analog routing switches are reset to their default state. +* If false, analog switch registers are untouched. +* +* \return +* Status of initialization, \ref CY_CTB_SUCCESS or \ref CY_CTB_BAD_PARAM +* +*******************************************************************************/ +cy_en_ctb_status_t Cy_CTB_DeInit(CTBM_Type *base, bool deInitRouting) +{ + CY_ASSERT_L1(NULL != base); + + cy_en_ctb_status_t result; + + if (NULL == base) + { + result = CY_CTB_BAD_PARAM; + } + else + { + base->CTB_CTRL = CY_CTB_DEINIT; + base->OA_RES0_CTRL = CY_CTB_DEINIT; + base->OA_RES1_CTRL = CY_CTB_DEINIT; + base->INTR_MASK = CY_CTB_DEINIT; + + if (deInitRouting) + { + base->OA0_SW_CLEAR = CY_CTB_DEINIT_OA0_SW; + base->OA1_SW_CLEAR = CY_CTB_DEINIT_OA1_SW; + base->CTD_SW_CLEAR = CY_CTB_DEINIT_CTD_SW; + } + + result = CY_CTB_SUCCESS; + } + + return result; +} + +/******************************************************************************* +* Function Name: Cy_CTB_FastInit +****************************************************************************//** +* +* Initialize each opamp of the CTB to one of the common use modes. +* +* This function provides a quick and easy method of configuring the CTB +* using pre-defined configurations. +* Only routing switches required for the selected mode are configured, leaving final input and output connections +* to the user. +* Additional use modes that relate to the \ref group_ctdac "CTDAC" +* are provided to support easy configuration of the CTDAC output buffer and input +* reference buffer. +* +* The fast configuration structures define the opamp power, mode, and routing. +* This function sets the other configuration options of the CTB to: +* - .deepSleep = CY_CTB_DEEPSLEEP_DISABLE +* - .oaPump = \ref CY_CTB_PUMP_ENABLE +* - .oaCompEdge = \ref CY_CTB_COMP_EDGE_BOTH +* - .oaCompLevel = \ref CY_CTB_COMP_DSI_TRIGGER_OUT_LEVEL +* - .oaCompBypass = \ref CY_CTB_COMP_BYPASS_SYNC +* - .oaCompHyst = \ref CY_CTB_COMP_HYST_10MV +* - .oaCompIntrEn = true + +* \param base +* Pointer to structure describing registers +* +* \param config0 +* Pointer to structure containing configuration data for quick initialization +* of Opamp0. Defined your own or use one of the provided structures: +* - \ref Cy_CTB_Fast_Opamp0_Unused +* - \ref Cy_CTB_Fast_Opamp0_Comp +* - \ref Cy_CTB_Fast_Opamp0_Opamp1x +* - \ref Cy_CTB_Fast_Opamp0_Opamp10x +* - \ref Cy_CTB_Fast_Opamp0_Diffamp +* - \ref Cy_CTB_Fast_Opamp0_Vdac_Out +* - \ref Cy_CTB_Fast_Opamp0_Vdac_Out_SH +* +* \param config1 +* Pointer to structure containing configuration data for quick initialization +* of Opamp1. Defined your own or use one of the provided structures: +* - \ref Cy_CTB_Fast_Opamp1_Unused +* - \ref Cy_CTB_Fast_Opamp1_Comp +* - \ref Cy_CTB_Fast_Opamp1_Opamp1x +* - \ref Cy_CTB_Fast_Opamp1_Opamp10x +* - \ref Cy_CTB_Fast_Opamp1_Diffamp +* - \ref Cy_CTB_Fast_Opamp1_Vdac_Ref_Aref +* - \ref Cy_CTB_Fast_Opamp1_Vdac_Ref_Pin5 +* +* \return +* Status of initialization, \ref CY_CTB_SUCCESS or \ref CY_CTB_BAD_PARAM +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm0p.c SNIPPET_FASTINIT +* +*******************************************************************************/ +cy_en_ctb_status_t Cy_CTB_FastInit(CTBM_Type *base, const cy_stc_ctb_fast_config_oa0_t *config0, const cy_stc_ctb_fast_config_oa1_t *config1) +{ + CY_ASSERT_L1(NULL != base); + CY_ASSERT_L1(NULL != config0); + CY_ASSERT_L1(NULL != config1); + + cy_en_ctb_status_t result; + + if ((NULL == base) || (NULL == config0) || (NULL == config1)) + { + result = CY_CTB_BAD_PARAM; + } + else + { + /* Enum and boundary checks for config0 */ + CY_ASSERT_L3(CY_CTB_OAPOWER(config0->oa0Power)); + CY_ASSERT_L3(CY_CTB_OAMODE(config0->oa0Mode)); + CY_ASSERT_L2(CY_CTB_OA0SWITCH(config0->oa0SwitchCtrl)); + CY_ASSERT_L2(CY_CTB_CTDSWITCH(config0->ctdSwitchCtrl)); + + /* Enum and boundary checks for config1 */ + CY_ASSERT_L3(CY_CTB_OAPOWER(config1->oa1Power)); + CY_ASSERT_L3(CY_CTB_OAMODE(config1->oa1Mode)); + CY_ASSERT_L2(CY_CTB_OA1SWITCH(config1->oa1SwitchCtrl)); + CY_ASSERT_L2(CY_CTB_CTDSWITCH(config1->ctdSwitchCtrl)); + + base->CTB_CTRL = (uint32_t) CY_CTB_DEEPSLEEP_DISABLE; + + base->OA_RES0_CTRL = (uint32_t) config0->oa0Power \ + | (uint32_t) config0->oa0Mode \ + | (uint32_t) CY_CTB_PUMP_ENABLE \ + | (uint32_t) CY_CTB_COMP_EDGE_BOTH \ + | (uint32_t) CY_CTB_COMP_DSI_TRIGGER_OUT_LEVEL \ + | (uint32_t) CY_CTB_COMP_BYPASS_SYNC \ + | (uint32_t) CY_CTB_COMP_HYST_10MV \ + | ((CY_CTB_MODE_OPAMP1X == config0->oa0Mode) ? CY_CTB_OPAMP_BOOST_ENABLE : CY_CTB_OPAMP_BOOST_DISABLE); + + base->OA_RES1_CTRL = (uint32_t) config1->oa1Power \ + | (uint32_t) config1->oa1Mode \ + | (uint32_t) CY_CTB_PUMP_ENABLE \ + | (uint32_t) CY_CTB_COMP_EDGE_BOTH \ + | (uint32_t) CY_CTB_COMP_DSI_TRIGGER_OUT_LEVEL \ + | (uint32_t) CY_CTB_COMP_BYPASS_SYNC \ + | (uint32_t) CY_CTB_COMP_HYST_10MV \ + | ((CY_CTB_MODE_OPAMP1X == config1->oa1Mode) ? CY_CTB_OPAMP_BOOST_ENABLE : CY_CTB_OPAMP_BOOST_DISABLE); + + base->INTR_MASK = CTBM_INTR_MASK_COMP0_MASK_Msk | CTBM_INTR_MASK_COMP1_MASK_Msk; + + base->OA0_COMP_TRIM = (uint32_t) ((config0->oa0Mode == CY_CTB_MODE_OPAMP10X) ? CY_CTB_OPAMP_COMPENSATION_CAP_MAX: CY_CTB_OPAMP_COMPENSATION_CAP_MIN); + base->OA1_COMP_TRIM = (uint32_t) ((config1->oa1Mode == CY_CTB_MODE_OPAMP10X) ? CY_CTB_OPAMP_COMPENSATION_CAP_MAX: CY_CTB_OPAMP_COMPENSATION_CAP_MIN); + + base->OA0_SW = config0->oa0SwitchCtrl; + base->OA1_SW = config1->oa1SwitchCtrl; + base->CTD_SW = config0->ctdSwitchCtrl | config1->ctdSwitchCtrl; + + result = CY_CTB_SUCCESS; + } + + return result; +} + +/******************************************************************************* +* Function Name: Cy_CTB_SetCurrentMode +****************************************************************************//** +* +* High level function to configure the current modes of the opamps. +* This function configures all opamps of the CTB to the same current mode. +* These modes are differentiated by the reference current level, the opamp +* input range, and the Deep Sleep mode operation. +* +* - The reference current level is set using \ref Cy_CTB_SetIptatLevel +* - When 1 uA current level is used in Deep Sleep, +* - All generators in the AREF must be enabled in Deep Sleep. That is, +* \ref Cy_SysAnalog_SetDeepSleepMode is called with CY_SYSANALOG_DEEPSLEEP_IPTAT_IZTAT_VREF. +* - When 100 nA current level is used, +* - \ref Cy_CTB_EnableRedirect is called to route the AREF IPTAT reference +* to the opamp IZTAT and disable the opamps IPTAT. +* - The IPTAT generator is enabled in Deep Sleep. That is, +* \ref Cy_SysAnalog_SetDeepSleepMode is called with CY_SYSANALOG_DEEPSLEEP_IPTAT_2 +* unless it is already configured for CY_SYSANALOG_DEEPSLEEP_IPTAT_IZTAT_VREF. +* +* \note +* The IPTAT level is a chip wide configuration so multiple +* opamps cannot operate at different IPTAT levels. +* When calling \ref Cy_CTB_SetCurrentMode for a CTB instance on the device, +* it should be called for all other CTB instances as well. +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
Current ModeIPTAT LevelInput RangeDeep Sleep Operation
\ref CY_CTB_CURRENT_HIGH_ACTIVE1 uARail-to-Rail (charge pump enabled)Disabled in Deep Sleep
\ref CY_CTB_CURRENT_HIGH_ACTIVE_DEEPSLEEP1 uA0 - VDDA-1.5 V (charge pump disabled)Enabled in Deep Sleep
\ref CY_CTB_CURRENT_LOW_ACTIVE_DEEPSLEEP100 nA0 - VDDA-1.5 V (charge pump disabled)Enabled in Deep Sleep
+* +* \note +* The output range of the opamp is 0.2 V to VDDA - 0.2 V (depending on output load). +* +* \param base +* Pointer to structure describing registers +* +* \param currentMode +* Current mode selection +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_CURRENT_MODE +* +*******************************************************************************/ +void Cy_CTB_SetCurrentMode(CTBM_Type *base, cy_en_ctb_current_mode_t currentMode) +{ + CY_ASSERT_L3(CY_CTB_CURRENTMODE(currentMode)); + + cy_en_sysanalog_deep_sleep_t arefDeepSleep; + + switch(currentMode) + { + case CY_CTB_CURRENT_HIGH_ACTIVE: + + /* Does not disable AREF for Deep Sleep in case the AREF is used by other blocks */ + + /* Use a 1 uA IPTAT level and disable redirection */ + Cy_CTB_SetIptatLevel(CY_CTB_IPTAT_NORMAL); + Cy_CTB_DisableRedirect(); + + /* Disable Deep Sleep mode for the CTB - not opamp specific */ + Cy_CTB_SetDeepSleepMode(base, CY_CTB_DEEPSLEEP_DISABLE); + + /* Enable Opamp0 pump */ + base->OA_RES0_CTRL |= CTBM_OA_RES0_CTRL_OA0_PUMP_EN_Msk; + + /* Enable Opamp1 pump */ + base->OA_RES1_CTRL |= CTBM_OA_RES1_CTRL_OA1_PUMP_EN_Msk; + + break; + case CY_CTB_CURRENT_HIGH_ACTIVE_DEEPSLEEP: + + /* All generators (IPTAT, IZTAT, and VREF) of the AREF block must be enabled for Deep Sleep */ + Cy_SysAnalog_SetDeepSleepMode(CY_SYSANALOG_DEEPSLEEP_IPTAT_IZTAT_VREF); + + /* Use a 1 uA IPTAT level and disable redirection */ + Cy_CTB_SetIptatLevel(CY_CTB_IPTAT_NORMAL); + Cy_CTB_DisableRedirect(); + + /* Enable Deep Sleep mode for the CTB - not opamp specific */ + Cy_CTB_SetDeepSleepMode(base, CY_CTB_DEEPSLEEP_ENABLE); + + /* Disable Opamp0 pump */ + base->OA_RES0_CTRL &= ~CTBM_OA_RES0_CTRL_OA0_PUMP_EN_Msk; + + /* Disable Opamp1 pump */ + base->OA_RES1_CTRL &= ~CTBM_OA_RES1_CTRL_OA1_PUMP_EN_Msk; + + break; + case CY_CTB_CURRENT_LOW_ACTIVE_DEEPSLEEP: + default: + + /* The AREF IPTAT output for the opamps must be enabled in Deep Sleep. + * This means a minimum Deep Sleep mode setting of CY_SYSANALOG_DEEPSLEEP_IPTAT_2. */ + arefDeepSleep = Cy_SysAnalog_GetDeepSleepMode(); + if ((arefDeepSleep == CY_SYSANALOG_DEEPSLEEP_DISABLE) || (arefDeepSleep == CY_SYSANALOG_DEEPSLEEP_IPTAT_1)) + { + Cy_SysAnalog_SetDeepSleepMode(CY_SYSANALOG_DEEPSLEEP_IPTAT_2); + } + + /* Use a 100 nA IPTAT level and enable redirection */ + Cy_CTB_SetIptatLevel(CY_CTB_IPTAT_LOW); + Cy_CTB_EnableRedirect(); + + /* Enable Deep Sleep mode for the CTB - not opamp specific */ + Cy_CTB_SetDeepSleepMode(base, CY_CTB_DEEPSLEEP_ENABLE); + + /* Disable Opamp0 pump */ + base->OA_RES0_CTRL &= ~CTBM_OA_RES0_CTRL_OA0_PUMP_EN_Msk; + + /* Disable Opamp1 pump */ + base->OA_RES1_CTRL &= ~CTBM_OA_RES1_CTRL_OA1_PUMP_EN_Msk; + break; + } +} + +/******************************************************************************* +* Function Name: Cy_CTB_SetDeepSleepMode +****************************************************************************//** +* +* Enable or disable the entire CTB (not per opamp) in Deep Sleep mode. +* +* If enabled, the AREF block must also be enabled for Deep Sleep to provide +* the needed reference currents to the opamps (see \ref Cy_SysAnalog_SetDeepSleepMode). +* Additionally, ensure that only internal CTB switches are used for routing. +* Switches on AMUXBUSA and AMUXBUSB are not enabled in Deep Sleep. +* See the \ref group_ctb_dependencies section for more information. +* +* \note +* In Deep Sleep mode, the charge pumps are disabled so the input +* range of the opamps is reduced to 0 V to VDDA - 1.5 V. +* +* \param base +* Pointer to structure describing registers +* +* \param deepSleep +* \ref CY_CTB_DEEPSLEEP_DISABLE or \ref CY_CTB_DEEPSLEEP_ENABLE from +* \ref cy_en_ctb_deep_sleep_t. +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_DEEPSLEEP_MODE +* +*******************************************************************************/ +void Cy_CTB_SetDeepSleepMode(CTBM_Type *base, cy_en_ctb_deep_sleep_t deepSleep) +{ + CY_ASSERT_L3(CY_CTB_DEEPSLEEP(deepSleep)); + + uint32_t ctbCtrl; + + ctbCtrl = base->CTB_CTRL & ~CTBM_CTB_CTRL_DEEPSLEEP_ON_Msk; + + base->CTB_CTRL = ctbCtrl | (uint32_t)deepSleep; +} + +/******************************************************************************* +* Function Name: Cy_CTB_SetOutputMode +****************************************************************************//** +* +* Set the opamp output mode to 1x drive, 10x drive, or comparator mode. +* +* \param base +* Pointer to structure describing registers +* +* \param opampNum +* \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH +* +* \param mode +* Opamp mode selection. Select a value from \ref cy_en_ctb_mode_t. +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_OUTPUT_MODE +* +*******************************************************************************/ +void Cy_CTB_SetOutputMode(CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum, cy_en_ctb_mode_t mode) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM(opampNum)); + CY_ASSERT_L3(CY_CTB_OAMODE(mode)); + + uint32_t oaCtrlReg; + + if ((opampNum == CY_CTB_OPAMP_0) || (opampNum == CY_CTB_OPAMP_BOTH)) + { + + /* Clear the three affected bits before setting them */ + oaCtrlReg = base->OA_RES0_CTRL & ~(CTBM_OA_RES0_CTRL_OA0_DRIVE_STR_SEL_Msk | CTBM_OA_RES0_CTRL_OA0_COMP_EN_Msk | CTBM_OA_RES0_CTRL_OA0_BOOST_EN_Msk); + base->OA_RES0_CTRL = oaCtrlReg | (uint32_t) mode | ((mode == CY_CTB_MODE_OPAMP10X) ? CY_CTB_OPAMP_BOOST_DISABLE : CY_CTB_OPAMP_BOOST_ENABLE); + base->OA0_COMP_TRIM = (uint32_t) ((mode == CY_CTB_MODE_OPAMP10X) ? CY_CTB_OPAMP_COMPENSATION_CAP_MAX: CY_CTB_OPAMP_COMPENSATION_CAP_MIN); + } + + if ((opampNum == CY_CTB_OPAMP_1) || (opampNum == CY_CTB_OPAMP_BOTH)) + { + oaCtrlReg = base->OA_RES1_CTRL & ~(CTBM_OA_RES1_CTRL_OA1_DRIVE_STR_SEL_Msk | CTBM_OA_RES1_CTRL_OA1_COMP_EN_Msk | CTBM_OA_RES1_CTRL_OA1_BOOST_EN_Msk); + base->OA_RES1_CTRL = oaCtrlReg | (uint32_t) mode | ((mode == CY_CTB_MODE_OPAMP10X) ? CY_CTB_OPAMP_BOOST_DISABLE : CY_CTB_OPAMP_BOOST_ENABLE); + base->OA1_COMP_TRIM = (uint32_t) ((mode == CY_CTB_MODE_OPAMP10X) ? CY_CTB_OPAMP_COMPENSATION_CAP_MAX: CY_CTB_OPAMP_COMPENSATION_CAP_MIN); + } +} + +/******************************************************************************* +* Function Name: Cy_CTB_SetPower +****************************************************************************//** +* +* Configure the power level and charge pump for a specific opamp. +* +* At higher power levels, the opamp consumes more current but provides more +* gain bandwidth. +* Enabling the charge pump increases current but provides +* rail-to-rail input range. Disabling the charge pump limits the input range to +* VDDA - 1.5 V. +* See the device datasheet for performance specifications. +* +* \param base +* Pointer to structure describing registers +* +* \param opampNum +* \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH +* +* \param power +* Power mode selection. Select a value from \ref cy_en_ctb_power_t. +* +* \param pump +* Enable or disable the charge pump. Select a value from \ref cy_en_ctb_pump_t. +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_POWER +* +*******************************************************************************/ +void Cy_CTB_SetPower(CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum, cy_en_ctb_power_t power, cy_en_ctb_pump_t pump) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM(opampNum)); + CY_ASSERT_L3(CY_CTB_OAPOWER(power)); + CY_ASSERT_L3(CY_CTB_OAPUMP(pump)); + + uint32_t oaCtrlReg; + + if ((opampNum == CY_CTB_OPAMP_0) || (opampNum == CY_CTB_OPAMP_BOTH)) + { + + /* Clear the two affected bits before setting them */ + oaCtrlReg = base->OA_RES0_CTRL & ~(CTBM_OA_RES0_CTRL_OA0_PWR_MODE_Msk | CTBM_OA_RES0_CTRL_OA0_PUMP_EN_Msk); + base->OA_RES0_CTRL = oaCtrlReg | (uint32_t) power | (uint32_t) pump; + } + + if ((opampNum == CY_CTB_OPAMP_1) || (opampNum == CY_CTB_OPAMP_BOTH)) + { + oaCtrlReg = base->OA_RES1_CTRL & ~(CTBM_OA_RES1_CTRL_OA1_PWR_MODE_Msk | CTBM_OA_RES1_CTRL_OA1_PUMP_EN_Msk); + base->OA_RES1_CTRL = oaCtrlReg | (uint32_t) power | (uint32_t) pump; + } +} + +/******************************************************************************* +* Function Name: Cy_CTB_DACSampleAndHold +****************************************************************************//** +* +* Perform sampling and holding of the CTDAC output. +* To perform a sample or a hold, a preparation step must first be executed to +* open the required switches. Because of this, each sample or hold +* requires three function calls: +* +* -# Call this function to prepare for a sample or hold +* -# Enable or disable the CTDAC output +* -# Call this function again to perform a sample or hold +* +* It takes 10 us to perform a sample of the CTDAC output to provide +* time for the capacitor to settle to the new value. +* +* \param base +* Pointer to structure describing registers +* +* \param mode +* Mode to prepare or perform a sample or hold, or disable the ability +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SAMPLE_CODE_SNIPPET +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_HOLD_CODE_SNIPPET +* +*******************************************************************************/ +void Cy_CTB_DACSampleAndHold(CTBM_Type *base, cy_en_ctb_sample_hold_mode_t mode) +{ + CY_ASSERT_L3(CY_CTB_SAMPLEHOLD(mode)); + + switch(mode) + { + case CY_CTB_SH_DISABLE: + base->CTD_SW_CLEAR = (uint32_t) CY_CTB_SW_CTD_OUT_OA0_1X_OUT_MASK /* Open COB switch */ + | (uint32_t) CY_CTB_SW_CTD_CHOLD_OA0_POS_ISOLATE_MASK /* Open CIS switch */ + | (uint32_t) CY_CTB_SW_CTD_CHOLD_LEAKAGE_REDUCTION_MASK /* Open ILR switch */ + | (uint32_t) CY_CTB_SW_CTD_CHOLD_CONNECT_MASK; /* Open CHD switch */ + base->CTD_SW = (uint32_t) CY_CTB_SW_CTD_OUT_CHOLD_MASK; /* Close COS switch */ + break; + case CY_CTB_SH_PREPARE_SAMPLE: + base->CTD_SW_CLEAR = (uint32_t) CY_CTB_SW_CTD_OUT_OA0_1X_OUT_MASK /* Open COB switch */ + | (uint32_t) CY_CTB_SW_CTD_CHOLD_OA0_POS_ISOLATE_MASK /* Open CIS switch */ + | (uint32_t) CY_CTB_SW_CTD_CHOLD_LEAKAGE_REDUCTION_MASK; /* Open ILR switch */ + base->CTD_SW = (uint32_t) CY_CTB_SW_CTD_CHOLD_CONNECT_MASK; /* Close CHD switch */ + break; + case CY_CTB_SH_SAMPLE: + base->CTD_SW = (uint32_t) CY_CTB_SW_CTD_OUT_CHOLD_MASK; /* Close COS switch */ + break; + case CY_CTB_SH_PREPARE_HOLD: + base->CTD_SW_CLEAR = (uint32_t) CY_CTB_SW_CTD_OUT_CHOLD_MASK /* Open COS switch */ + | (uint32_t) CY_CTB_SW_CTD_CHOLD_OA0_POS_ISOLATE_MASK; /* Open CIS switch */ + break; + case CY_CTB_SH_HOLD: + default: + base->CTD_SW = (uint32_t) CY_CTB_SW_CTD_OUT_OA0_1X_OUT_MASK /* Close COB switch to reduce leakage through COS switch */ + | (uint32_t) CY_CTB_SW_CTD_CHOLD_LEAKAGE_REDUCTION_MASK; /* Close ILR switch to reduce leakage through CIS switch */ + break; + } +} + +/******************************************************************************* +* Function Name: Cy_CTB_OpampSetOffset +****************************************************************************//** +* +* Override the CTB opamp offset factory trim. +* The trim is a six bit value and the MSB is a direction bit. +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
Bit 5Bits 4:0Note
000000Negative trim direction - minimum setting
011111Negative trim direction - maximum setting
100000Positive trim direction - minimum setting
111111Positive trim direction - maximum setting
+* +* \param base +* Pointer to structure describing registers +* +* \param opampNum +* \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH +* +* \param trim +* Trim value from 0 to 63 +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_OFFSET_TRIM +* +*******************************************************************************/ +void Cy_CTB_OpampSetOffset(CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum, uint32_t trim) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM(opampNum)); + CY_ASSERT_L2(CY_CTB_TRIM(trim)); + + if ((opampNum == CY_CTB_OPAMP_0) || (opampNum == CY_CTB_OPAMP_BOTH)) + { + base->OA0_OFFSET_TRIM = (trim << CTBM_OA0_OFFSET_TRIM_OA0_OFFSET_TRIM_Pos) & CTBM_OA0_OFFSET_TRIM_OA0_OFFSET_TRIM_Msk; + } + + if ((opampNum == CY_CTB_OPAMP_1) || (opampNum == CY_CTB_OPAMP_BOTH)) + { + base->OA1_OFFSET_TRIM = (trim << CTBM_OA1_OFFSET_TRIM_OA1_OFFSET_TRIM_Pos) & CTBM_OA1_OFFSET_TRIM_OA1_OFFSET_TRIM_Msk; + } +} + +/******************************************************************************* +* Function Name: Cy_CTB_OpampGetOffset +****************************************************************************//** +* +* Return the current CTB opamp offset trim value. +* +* \param base +* Pointer to structure describing registers +* +* \param opampNum +* \ref CY_CTB_OPAMP_0 or \ref CY_CTB_OPAMP_1 +* +* \return Offset trim value +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_GET_OFFSET_TRIM +* +*******************************************************************************/ +uint32_t Cy_CTB_OpampGetOffset(const CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM_0_1(opampNum)); + + uint32_t trimReg; + + if (opampNum == CY_CTB_OPAMP_0) + { + trimReg = base->OA0_OFFSET_TRIM; + } + else + { + trimReg = base->OA1_OFFSET_TRIM; + } + + return trimReg; +} + +/******************************************************************************* +* Function Name: Cy_CTB_OpampSetSlope +****************************************************************************//** +* +* Override the CTB opamp slope factory trim. +* The offset of the opamp will vary across temperature. +* This trim compensates for the slope of the offset across temperature. +* This compensation uses a bias current from the Analaog Reference block. +* To disable it, set the trim to 0. +* +* The trim is a six bit value and the MSB is a direction bit. +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
Bit 5Bits 4:0Note
000000Negative trim direction - minimum setting
011111Negative trim direction - maximum setting
100000Positive trim direction - minimum setting
111111Positive trim direction - maximum setting
+* +* \param base +* Pointer to structure describing registers +* +* \param opampNum +* \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH +* +* \param trim +* Trim value from 0 to 63 +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_SLOPE_TRIM +* +*******************************************************************************/ +void Cy_CTB_OpampSetSlope(CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum, uint32_t trim) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM(opampNum)); + CY_ASSERT_L2(CY_CTB_TRIM(trim)); + + if ((opampNum == CY_CTB_OPAMP_0) || (opampNum == CY_CTB_OPAMP_BOTH)) + { + base->OA0_SLOPE_OFFSET_TRIM = (trim << CTBM_OA0_SLOPE_OFFSET_TRIM_OA0_SLOPE_OFFSET_TRIM_Pos) & CTBM_OA0_SLOPE_OFFSET_TRIM_OA0_SLOPE_OFFSET_TRIM_Msk; + } + + if ((opampNum == CY_CTB_OPAMP_1) || (opampNum == CY_CTB_OPAMP_BOTH)) + { + base->OA1_SLOPE_OFFSET_TRIM = (trim << CTBM_OA1_SLOPE_OFFSET_TRIM_OA1_SLOPE_OFFSET_TRIM_Pos) & CTBM_OA1_SLOPE_OFFSET_TRIM_OA1_SLOPE_OFFSET_TRIM_Msk; + } +} + +/******************************************************************************* +* Function Name: Cy_CTB_OpampGetSlope +****************************************************************************//** +* +* Return the CTB opamp slope trim value. +* +* \param base +* Pointer to structure describing registers +* +* \param opampNum +* \ref CY_CTB_OPAMP_0 or \ref CY_CTB_OPAMP_1 +* +* \return Slope trim value +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_GET_SLOPE_TRIM +* +*******************************************************************************/ +uint32_t Cy_CTB_OpampGetSlope(const CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM_0_1(opampNum)); + + uint32_t trimReg; + + if (opampNum == CY_CTB_OPAMP_0) + { + trimReg = base->OA0_SLOPE_OFFSET_TRIM; + } + else + { + trimReg = base->OA1_SLOPE_OFFSET_TRIM; + } + + return trimReg; +} + +/******************************************************************************* +* Function Name: Cy_CTB_SetAnalogSwitch +****************************************************************************//** +* +* Provide firmware control of the CTB switches. Each call to this function +* can open a set of switches or close a set of switches in one register. +* +* \param base +* Pointer to structure describing registers +* +* \param switchSelect +* A value of the enum \ref cy_en_ctb_switch_register_sel_t to select the switch +* register +* +* \param switchMask +* The mask of the switches to either open or close. +* The switch masks can be found in the following enums: \ref cy_en_ctb_oa0_switches_t, +* \ref cy_en_ctb_oa1_switches_t, and \ref cy_en_ctb_ctd_switches_t. +* Use the enum that is consistent with the provided register. +* +* \param state +* \ref CY_CTB_SWITCH_OPEN or \ref CY_CTB_SWITCH_CLOSE +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_ANALOG_SWITCH +* +*******************************************************************************/ +void Cy_CTB_SetAnalogSwitch(CTBM_Type *base, cy_en_ctb_switch_register_sel_t switchSelect, uint32_t switchMask, cy_en_ctb_switch_state_t state) +{ + CY_ASSERT_L3(CY_CTB_SWITCHSELECT(switchSelect)); + CY_ASSERT_L2(CY_CTB_SWITCHMASK(switchSelect, switchMask)); + CY_ASSERT_L3(CY_CTB_SWITCHSTATE(state)); + + __IOM uint32_t *switchReg; + __IOM uint32_t *switchClearReg; + + switch(switchSelect) + { + case CY_CTB_SWITCH_OA0_SW: + switchReg = &base->OA0_SW; + switchClearReg = &base->OA0_SW_CLEAR; + break; + case CY_CTB_SWITCH_OA1_SW: + switchReg = &base->OA1_SW; + switchClearReg = &base->OA1_SW_CLEAR; + break; + case CY_CTB_SWITCH_CTD_SW: + default: + switchReg = &base->CTD_SW; + switchClearReg = &base->CTD_SW_CLEAR; + break; + } + + switch(state) + { + case CY_CTB_SWITCH_CLOSE: + *switchReg = switchMask; + break; + case CY_CTB_SWITCH_OPEN: + default: + *switchClearReg = switchMask; + break; + } +} + +/******************************************************************************* +* Function Name: Cy_CTB_GetAnalogSwitch +****************************************************************************//** +* +* Return the open or closed state of the specified analog switch. +* +* \param base +* Pointer to structure describing registers +* +* \param switchSelect +* A value of the enum \ref cy_en_ctb_switch_register_sel_t to select the switch +* register +* +* \return +* The state of the switches in the provided register. +* Compare this value to the switch masks in the following enums: +* \ref cy_en_ctb_oa0_switches_t, \ref cy_en_ctb_oa1_switches_t, and \ref cy_en_ctb_ctd_switches_t. +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_GET_ANALOG_SWITCH +* +*******************************************************************************/ +uint32_t Cy_CTB_GetAnalogSwitch(const CTBM_Type *base, cy_en_ctb_switch_register_sel_t switchSelect) +{ + CY_ASSERT_L3(CY_CTB_SWITCHSELECT(switchSelect)); + + uint32_t switchRegValue; + + switch(switchSelect) + { + case CY_CTB_SWITCH_OA0_SW: + switchRegValue = base->OA0_SW; + break; + case CY_CTB_SWITCH_OA1_SW: + switchRegValue = base->OA1_SW; + break; + case CY_CTB_SWITCH_CTD_SW: + default: + switchRegValue = base->CTD_SW; + break; + } + + return switchRegValue; +} + +/******************************************************************************* +* Function Name: Cy_CTB_CompSetConfig +****************************************************************************//** +* +* Configure the CTB comparator for pulse or level output, to bypass clock +* synchronization, and to enable hysteresis. +* +* \param base +* Pointer to structure describing registers +* +* \param compNum +* \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH +* +* \param level +* Configure output to produce a pulse or level output signal + +* \param bypass +* Configure output to be clock synchronized or unsynchronized + +* \param hyst +* Enable or disable input hysteresis + +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_COMP_SET_CONFIG +* +*******************************************************************************/ +void Cy_CTB_CompSetConfig(CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum, cy_en_ctb_comp_level_t level, cy_en_ctb_comp_bypass_t bypass, cy_en_ctb_comp_hyst_t hyst) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM(compNum)); + CY_ASSERT_L3(CY_CTB_COMPLEVEL(level)); + CY_ASSERT_L3(CY_CTB_COMPBYPASS(bypass)); + CY_ASSERT_L3(CY_CTB_COMPHYST(hyst)); + + uint32_t opampCtrlReg; + + if ((compNum == CY_CTB_OPAMP_0) || (compNum == CY_CTB_OPAMP_BOTH)) + { + opampCtrlReg = base->OA_RES0_CTRL & ~(CTBM_OA_RES0_CTRL_OA0_HYST_EN_Msk | CTBM_OA_RES0_CTRL_OA0_BYPASS_DSI_SYNC_Msk | CTBM_OA_RES0_CTRL_OA0_DSI_LEVEL_Msk); + base->OA_RES0_CTRL = opampCtrlReg | (uint32_t) level |(uint32_t) bypass | (uint32_t) hyst; + } + + if ((compNum == CY_CTB_OPAMP_1) || (compNum == CY_CTB_OPAMP_BOTH)) + { + opampCtrlReg = base->OA_RES1_CTRL & ~(CTBM_OA_RES1_CTRL_OA1_HYST_EN_Msk | CTBM_OA_RES1_CTRL_OA1_BYPASS_DSI_SYNC_Msk | CTBM_OA_RES1_CTRL_OA1_DSI_LEVEL_Msk); + base->OA_RES1_CTRL = opampCtrlReg | (uint32_t) level |(uint32_t) bypass | (uint32_t) hyst; + } +} + +/******************************************************************************* +* Function Name: Cy_CTB_CompGetConfig +****************************************************************************//** +* +* Return the CTB comparator operating configuration as set by \ref Cy_CTB_CompSetConfig. +* +* \param base +* Pointer to structure describing registers +* +* \param compNum +* \ref CY_CTB_OPAMP_0 or \ref CY_CTB_OPAMP_1 +* +* \return +* The comparator configuration. +* Compare the register value with the masks in \ref cy_en_ctb_comp_level_t, +* \ref cy_en_ctb_comp_bypass_t, and \ref cy_en_ctb_comp_hyst_t. +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_COMP_GET_CONFIG +* +*******************************************************************************/ +uint32_t Cy_CTB_CompGetConfig(const CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM_0_1(compNum)); + + uint32_t config; + + if (compNum == CY_CTB_OPAMP_0) + { + config = base->OA_RES0_CTRL & (CTBM_OA_RES0_CTRL_OA0_HYST_EN_Msk | CTBM_OA_RES0_CTRL_OA0_BYPASS_DSI_SYNC_Msk | CTBM_OA_RES0_CTRL_OA0_DSI_LEVEL_Msk); + } + else + { + config = base->OA_RES1_CTRL & (CTBM_OA_RES1_CTRL_OA1_HYST_EN_Msk | CTBM_OA_RES1_CTRL_OA1_BYPASS_DSI_SYNC_Msk | CTBM_OA_RES1_CTRL_OA1_DSI_LEVEL_Msk); + } + + return config; +} + +/******************************************************************************* +* Function Name: Cy_CTB_CompSetInterruptEdgeType +****************************************************************************//** +* +* Configure the type of edge that will trigger a comparator interrupt. +* +* \param base +* Pointer to structure describing registers +* +* \param compNum +* \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH +* +* \param edge +* Edge type that will trigger an interrupt. Select a value from \ref cy_en_ctb_comp_edge_t. +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_COMP_SET_INTERRUPT_EDGE_TYPE +* +*******************************************************************************/ +void Cy_CTB_CompSetInterruptEdgeType(CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum, cy_en_ctb_comp_edge_t edge) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM(compNum)); + CY_ASSERT_L3(CY_CTB_COMPEDGE(edge)); + + uint32_t opampCtrlReg; + + if ((compNum == CY_CTB_OPAMP_0) || (compNum == CY_CTB_OPAMP_BOTH)) + { + opampCtrlReg = base->OA_RES0_CTRL & ~(CTBM_OA_RES0_CTRL_OA0_COMPINT_Msk); + base->OA_RES0_CTRL = opampCtrlReg | (uint32_t) edge; + } + + if ((compNum == CY_CTB_OPAMP_1) || (compNum == CY_CTB_OPAMP_BOTH)) + { + opampCtrlReg = base->OA_RES1_CTRL & ~(CTBM_OA_RES1_CTRL_OA1_COMPINT_Msk); + base->OA_RES1_CTRL = opampCtrlReg | (uint32_t) edge; + } +} + +/******************************************************************************* +* Function Name: Cy_CTB_CompGetStatus +****************************************************************************//** +* +* Return the comparator output status. +* When the positive input voltage is greater than the negative input voltage, +* the comparator status is high. Otherwise, the status is low. +* +* \param base +* Pointer to structure describing registers +* +* \param compNum +* \ref CY_CTB_OPAMP_0 or \ref CY_CTB_OPAMP_1. +* \ref CY_CTB_OPAMP_NONE and \ref CY_CTB_OPAMP_BOTH are invalid options. +* +* \return +* The comparator status. +* A value of 0 is returned if compNum is invalid. +* - 0: Status is low +* - 1: Status is high +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_COMP_GET_STATUS +* +*******************************************************************************/ +uint32_t Cy_CTB_CompGetStatus(const CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM_0_1(compNum)); + + uint32_t compStatusResult; + + if (CY_CTB_OPAMP_0 == compNum) + { + compStatusResult = (base->COMP_STAT & CTBM_COMP_STAT_OA0_COMP_Msk) >> CTBM_COMP_STAT_OA0_COMP_Pos; + } + else if (CY_CTB_OPAMP_1 == compNum) + { + compStatusResult = (base->COMP_STAT & CTBM_COMP_STAT_OA1_COMP_Msk) >> CTBM_COMP_STAT_OA1_COMP_Pos; + } + else + { + compStatusResult = 0uL; + } + + return compStatusResult; +} + +#if defined(__cplusplus) +} +#endif + +/* [] END OF FILE */ + diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ctb/cy_ctb.h b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ctb/cy_ctb.h new file mode 100644 index 0000000000..cceedf093b --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ctb/cy_ctb.h @@ -0,0 +1,1508 @@ +/***************************************************************************//** +* \file cy_ctb.h +* \version 1.0 +* +* Header file for the CTB driver +* +******************************************************************************** +* \copyright +* Copyright 2017-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +/** +* \defgroup group_ctb Continuous Time Block (CTB) +* \{ +* This driver provides API functions to configure and use the analog CTB. +* The CTB comprises two identical opamps, a switch routing matrix, +* and a sample and hold (SH) circuit. The high level features are: +* +* - Two highly configurable opamps +* - Each opamp has programmable power and output drive strength +* - Each opamp can be configured as a voltage follower using internal routing +* - Each opamp can be configured as a comparator with optional 10 mV hysteresis +* - Flexible input and output routing +* - Works as a buffer or amplifier for SAR ADC inputs +* - Works as a buffer, amplifier, or sample and hold (SH) for the CTDAC output +* - Can operate in Deep Sleep power mode +* +* Each opamp, marked OA0 and OA1, has one input and three output stages, +* all of which share the common input stage. +* Note that only one output stage can be selected at a time. +* The output stage can operate as a low-drive strength opamp for internal connections (1X), a high-drive strength +* opamp for driving a device pin (10X), or a comparator. +* +* Using the switching matrix, the opamp inputs and outputs +* can be connected to dedicated general-purpose I/Os or other internal analog +* blocks. See the device datasheet for the dedicated CTB port. +* +* \image html ctb_block_diagram.png "CTB Switch Diagram" width=1000px +* \image latex ctb_block_diagram.png +* +* \section group_ctb_init Initialization and Enable +* +* Before enabling the CTB, set up any external components (such as resistors) +* that are needed for the design. To configure the entire hardware block, call \ref Cy_CTB_Init. +* The base address of the CTB hardware can be found in the device specific header file. +* Alternatively, to configure only one opamp without any routing, call \ref Cy_CTB_OpampInit. +* The driver also provides a \ref Cy_CTB_FastInit function for fast and easy initialization of the CTB +* based on commonly used configurations. They are pre-defined in the driver as: +* +* Opamp0 +* - \ref Cy_CTB_Fast_Opamp0_Unused +* - \ref Cy_CTB_Fast_Opamp0_Comp +* - \ref Cy_CTB_Fast_Opamp0_Opamp1x +* - \ref Cy_CTB_Fast_Opamp0_Opamp10x +* - \ref Cy_CTB_Fast_Opamp0_Diffamp +* - \ref Cy_CTB_Fast_Opamp0_Vdac_Out +* - \ref Cy_CTB_Fast_Opamp0_Vdac_Out_SH +* +* Opamp1 +* - \ref Cy_CTB_Fast_Opamp1_Unused +* - \ref Cy_CTB_Fast_Opamp1_Comp +* - \ref Cy_CTB_Fast_Opamp1_Opamp1x +* - \ref Cy_CTB_Fast_Opamp1_Opamp10x +* - \ref Cy_CTB_Fast_Opamp1_Diffamp +* - \ref Cy_CTB_Fast_Opamp1_Vdac_Ref_Aref +* - \ref Cy_CTB_Fast_Opamp1_Vdac_Ref_Pin5 +* +* After initialization, call \ref Cy_CTB_Enable to enable the hardware. +* +* \section group_ctb_io_connections Input/Output Connections +* +* The CTB has internal switches to support flexible input and output routing. If these switches +* have not been configured during initialization, call \ref Cy_CTB_SetAnalogSwitch to +* make the input and output connections. +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_ANALOG_SWITCH +* +* As shown in the CTB switch diagram, the 10x output of OA0 and OA1 have dedicated +* connections to Pin 2 and Pin 3, respectively, of the CTB port. If different output +* connections are required, the other CTB switches and/or AMUXBUX A/B switches can be used. +* +* \section group_ctb_comparator Comparator Mode +* +* Each opamp can be configured as a comparator. Note that when used as a +* comparator, the hardware shuts down the 1X and 10X output drivers. +* Specific to the comparator mode, there is an optional 10 mV input hysteresis +* and configurable edge detection interrupt handling. +* +* - Negative input terminal: This input is usually connected to the reference voltage. +* - Positive input terminal: This input is usually connected to the voltage that is being compared. +* - Comparator digital output: This output goes high when the positive input voltage +* is greater than the negative input voltage. +* +* The comparator output can be routed to a pin or other components using HSIOM or trigger muxes. +* +* \snippet ctb_sut_01.cydsn/main_cm0p.c SNIPPET_COMP_OUT_ROUTING +* +* \subsection group_ctb_comparator_handling_interrupts Handling interrupts +* +* The comparator output is connected to an edge detector +* block, which is used to detect the edge (rising, falling, both, or disabled) +* for interrupt generation. +* +* The following code snippet demonstrates how to implement a routine to handle the interrupt. +* The routine gets called when any comparator on the device generates an interrupt. +* +* \snippet ctb_sut_01.cydsn/main_cm0p.c SNIPPET_COMP_ISR +* +* The following code snippet demonstrates how to configure and enable the interrupt. +* +* \snippet ctb_sut_01.cydsn/main_cm0p.c SNIPPET_COMP_INTR_SETUP +* +* \section group_ctb_opamp_range Opamp Input and Output Range +* +* The input range of the opamp can be rail-to-rail if the charge pump is enabled. +* Without the charge pump, the input range is 0 V to VDDA - 1.5 V. The output range +* of the opamp is typically 0.2 V to VDDA - 0.2 V and will depend on the load. See the +* device datasheet for more detail. +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
Charge PumpInput Range
Output Range
Enabled0 V to VDDA0.2 V to VDDA - 0.2 V
Disabled0 V to VDDA - 1.5 V0.2 V to VDDA - 0.2 V
+* +* \section group_ctb_sample_hold Sample and Hold Mode +* +* The CTB has a sample and hold (SH) circuit at the non-inverting input of Opamp0. +* The circuit includes a hold capacitor, Chold, with a firmware controlled switch, CHD. +* Sampling and holding the source voltage is performed +* by closing and opening appropriate switches in the CTB using firmware. +* If the SH circuit is used for the CTDAC, the \ref Cy_CTB_DACSampleAndHold function +* should be called. +* +* \image html ctb_fast_config_vdac_sh.png +* \image latex ctb_fast_config_vdac_sh.png +* +* \section group_ctb_dependencies Configuration Dependencies +* +* The CTB relies on other blocks to function properly. The dependencies +* are documented here. +* +* \subsection group_ctb_dependencies_charge_pump Charge Pump Configuration +* +* Each opamp of the CTB has a charge pump that when enabled increases the +* input range to the supply rails. When disabled, the opamp input range is 0 - VDDA - 1.5 V. +* When enabled, the pump requires a clock. +* Call the \ref Cy_CTB_SetClkPumpSource function in the \ref group_sysanalog driver to +* set the clock source for all CTBs. This clock can come from one of two sources: +* +* -# A dedicated clock divider from one of the CLK_PATH in the SRSS +* +* Call the following functions to configure the pump clock from the SRSS: +* - \ref Cy_SysClk_ClkPumpSetSource +* - \ref Cy_SysClk_ClkPumpSetDivider +* - \ref Cy_SysClk_ClkPumpEnable +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_CLK_PUMP_SOURCE_SRSS +* +* -# One of the Peri Clock dividers +* +* Call the following functions to configure a Peri Clock divider as the +* pump clock: +* - \ref Cy_SysClk_PeriphAssignDivider with the IP block set to PCLK_PASS_CLOCK_PUMP_PERI +* - \ref Cy_SysClk_PeriphSetDivider +* - \ref Cy_SysClk_PeriphEnableDivider +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_CLK_PUMP_SOURCE_PERI +* +* When the charge pump is enabled, the clock frequency should be set as follows: +* +* +* +* +* +* +* +* +* +* +* +*
Opamp Power LevelPump Clock Freq
Low or Medium8 - 24 MHz
High24 MHz
+* +* The High power level of the opamp requires a 24 MHz pump clock. +* In Deep Sleep mode, all high frequency clocks are +* disabled and the charge pump will be disabled. +* +* \note +* The same pump clock is used by all opamps on the device. Be aware of this +* when configuring different opamps to different power levels. +* +* \subsection group_ctb_dependencies_reference_current Reference Current Configurations +* +* The CTB uses two reference current generators, IPTAT and IZTAT, from +* the AREF block (see \ref group_sysanalog driver). The IPTAT current is +* used to trim the slope of the opamp offset across temperature. +* The AREF must be initialized and enabled for the CTB to function properly. +* +* If the CTB is configured to operate in Deep Sleep mode, +* the appropriate reference current generators from the AREF block must be enabled in Deep Sleep. +* When waking up from Deep Sleep, +* the AREF block has a wakeup time that must be +* considered. Note that configurations in the AREF block +* are chip wide and affect all CTBs on the device. +* +* The following reference current configurations are supported: +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
Reference Current LevelSupported ModeInput Range
1 uAActive/Low PowerRail-to-Rail (charge pump enabled)
1 uAActive/Low Power/Deep Sleep0 - VDDA-1.5 V (charge pump disabled)
100 nAActive/Low Power/Deep Sleep0 - VDDA-1.5 V (charge pump disabled)
+* +* The first configuration provides low offset and drift with maximum input range +* while consuming the most current. +* For Deep Sleep operation, use the other two configurations with the charge pump disabled. +* For ultra low power, use the 100 nA current level. +* To configure the opamps to operate in one of these options, call \ref Cy_CTB_SetCurrentMode. +* +* \subsection group_ctb_dependencies_sample_hold Sample and Hold Switch Control +* +* If you are using rev-08 of the CY8CKIT-062, the following eight switches +* in the CTB are enabled by the CTDAC IP block: +* +* - COS, CA0, CHD, CH6, COB, COR, CRS, and CRD +* +* On the rev-08 board, if any of the above switches are used, you must call \ref Cy_CTDAC_Enable +* to enable these switches. +* +* Additionally, on the rev-08 board, if any of the switches are used in Deep Sleep mode, +* the CTDAC must also be configured to operate in Deep Sleep (see \ref Cy_CTDAC_SetDeepSleepMode). +* +* In later revisions of the board, the switches are enabled by the CTB block so +* calls to the CTDAC IP block are not necessary. +* +* \section group_ctb_more_information More Information +* +* Refer to technical reference manual (TRM) and the device datasheet. +* +* \section group_ctb_MISRA MISRA-C Compliance] +* +* This driver does not have any specific deviations. +* +* \section group_ctb_changelog Changelog +* +* +* +* +* +* +* +*
VersionChangesReason for Change
1.0Initial version
+* +* \defgroup group_ctb_macros Macros +* \defgroup group_ctb_functions Functions +* \{ +* \defgroup group_ctb_functions_init Initialization Functions +* \defgroup group_ctb_functions_basic Basic Configuration Functions +* \defgroup group_ctb_functions_comparator Comparator Functions +* \defgroup group_ctb_functions_sample_hold Sample and Hold Functions +* \defgroup group_ctb_functions_interrupts Interrupt Functions +* \defgroup group_ctb_functions_switches Switch Control Functions +* \defgroup group_ctb_functions_trim Offset and Slope Trim Functions +* \defgroup group_ctb_functions_aref Reference Current Mode Functions +* \} +* \defgroup group_ctb_globals Global Variables +* \defgroup group_ctb_data_structures Data Structures +* \defgroup group_ctb_enums Enumerated Types +*/ + +#if !defined(CY_CTB_H) +#define CY_CTB_H + +#include +#include +#include +#include "cy_device_headers.h" +#include "syslib/cy_syslib.h" +#include "sysanalog/cy_sysanalog.h" + +#ifndef CY_IP_MXS40PASS_CTB + #error "The CTB driver is not supported on this device" +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \addtogroup group_ctb_macros +* \{ +*/ + +/** Driver major version */ +#define CY_CTB_DRV_VERSION_MAJOR 1 + +/** Driver minor version */ +#define CY_CTB_DRV_VERSION_MINOR 0 + +/** CTB driver identifier*/ +#define CY_CTB_ID CY_PDL_DRV_ID(0x0Bu) + +/** \cond INTERNAL */ + +/**< De-init value for most CTB registers */ +#define CY_CTB_DEINIT (0uL) + +/**< De-init value for the opamp0 switch control register */ +#define CY_CTB_DEINIT_OA0_SW (CTBM_OA0_SW_CLEAR_OA0P_A00_Msk \ + | CTBM_OA0_SW_CLEAR_OA0P_A20_Msk \ + | CTBM_OA0_SW_CLEAR_OA0P_A30_Msk \ + | CTBM_OA0_SW_CLEAR_OA0M_A11_Msk \ + | CTBM_OA0_SW_CLEAR_OA0M_A81_Msk \ + | CTBM_OA0_SW_CLEAR_OA0O_D51_Msk \ + | CTBM_OA0_SW_CLEAR_OA0O_D81_Msk) + +/**< De-init value for the opamp1 switch control register */ +#define CY_CTB_DEINIT_OA1_SW (CTBM_OA1_SW_CLEAR_OA1P_A03_Msk \ + | CTBM_OA1_SW_CLEAR_OA1P_A13_Msk \ + | CTBM_OA1_SW_CLEAR_OA1P_A43_Msk \ + | CTBM_OA1_SW_CLEAR_OA1P_A73_Msk \ + | CTBM_OA1_SW_CLEAR_OA1M_A22_Msk \ + | CTBM_OA1_SW_CLEAR_OA1M_A82_Msk \ + | CTBM_OA1_SW_CLEAR_OA1O_D52_Msk \ + | CTBM_OA1_SW_CLEAR_OA1O_D62_Msk \ + | CTBM_OA1_SW_CLEAR_OA1O_D82_Msk) + +/**< De-init value for the CTDAC switch control register */ +#define CY_CTB_DEINIT_CTD_SW (CTBM_CTD_SW_CLEAR_CTDD_CRD_Msk \ + | CTBM_CTD_SW_CLEAR_CTDS_CRS_Msk \ + | CTBM_CTD_SW_CLEAR_CTDS_COR_Msk \ + | CTBM_CTD_SW_CLEAR_CTDO_C6H_Msk \ + | CTBM_CTD_SW_CLEAR_CTDO_COS_Msk \ + | CTBM_CTD_SW_CLEAR_CTDH_COB_Msk \ + | CTBM_CTD_SW_CLEAR_CTDH_CHD_Msk \ + | CTBM_CTD_SW_CLEAR_CTDH_CA0_Msk \ + | CTBM_CTD_SW_CLEAR_CTDH_CIS_Msk \ + | CTBM_CTD_SW_CLEAR_CTDH_ILR_Msk) + +#define CY_CTB_TRIM_VALUE_MAX (63uL) + +/**< Macros for conditions used by CY_ASSERT calls */ + +#define CY_CTB_OPAMPNUM(num) (((num) == CY_CTB_OPAMP_0) || ((num) == CY_CTB_OPAMP_1) || ((num) == CY_CTB_OPAMP_BOTH)) +#define CY_CTB_OPAMPNUM_0_1(num) (((num) == CY_CTB_OPAMP_0) || ((num) == CY_CTB_OPAMP_1)) +#define CY_CTB_OPAMPNUM_ALL(num) (((num) == CY_CTB_OPAMP_NONE) \ + || ((num) == CY_CTB_OPAMP_0) \ + || ((num) == CY_CTB_OPAMP_1) \ + || ((num) == CY_CTB_OPAMP_BOTH)) +#define CY_CTB_IPTAT(iptat) (((iptat) == CY_CTB_IPTAT_NORMAL) || ((iptat) == CY_CTB_IPTAT_LOW)) +#define CY_CTB_CLKPUMP(clkPump) (((clkPump) == CY_CTB_CLK_PUMP_SRSS) || ((clkPump) == CY_CTB_CLK_PUMP_PERI)) +#define CY_CTB_DEEPSLEEP(deepSleep) (((deepSleep) == CY_CTB_DEEPSLEEP_DISABLE) || ((deepSleep) == CY_CTB_DEEPSLEEP_ENABLE)) +#define CY_CTB_OAPOWER(power) ((power) <= CY_CTB_POWER_HIGH) +#define CY_CTB_OAMODE(mode) (((mode) == CY_CTB_MODE_OPAMP1X) \ + || ((mode) == CY_CTB_MODE_OPAMP10X) \ + || ((mode) == CY_CTB_MODE_COMP)) +#define CY_CTB_OAPUMP(pump) (((pump) == CY_CTB_PUMP_DISABLE) || ((pump) == CY_CTB_PUMP_ENABLE)) +#define CY_CTB_COMPEDGE(edge) (((edge) == CY_CTB_COMP_EDGE_DISABLE) \ + || ((edge) == CY_CTB_COMP_EDGE_RISING) \ + || ((edge) == CY_CTB_COMP_EDGE_FALLING) \ + || ((edge) == CY_CTB_COMP_EDGE_BOTH)) +#define CY_CTB_COMPLEVEL(level) (((level) == CY_CTB_COMP_DSI_TRIGGER_OUT_PULSE) || ((level) == CY_CTB_COMP_DSI_TRIGGER_OUT_LEVEL)) +#define CY_CTB_COMPBYPASS(bypass) (((bypass) == CY_CTB_COMP_BYPASS_SYNC) || ((bypass) == CY_CTB_COMP_BYPASS_NO_SYNC)) +#define CY_CTB_COMPHYST(hyst) (((hyst) == CY_CTB_COMP_HYST_DISABLE) || ((hyst) == CY_CTB_COMP_HYST_10MV)) +#define CY_CTB_CURRENTMODE(mode) (((mode) == CY_CTB_CURRENT_HIGH_ACTIVE) \ + || ((mode) == CY_CTB_CURRENT_HIGH_ACTIVE_DEEPSLEEP) \ + || ((mode) == CY_CTB_CURRENT_LOW_ACTIVE_DEEPSLEEP)) +#define CY_CTB_SAMPLEHOLD(mode) ((mode) <= CY_CTB_SH_HOLD) +#define CY_CTB_TRIM(trim) ((trim) <= CY_CTB_TRIM_VALUE_MAX) +#define CY_CTB_SWITCHSELECT(select) (((select) == CY_CTB_SWITCH_OA0_SW) \ + || ((select) == CY_CTB_SWITCH_OA1_SW) \ + || ((select) == CY_CTB_SWITCH_CTD_SW)) +#define CY_CTB_SWITCHSTATE(state) (((state) == CY_CTB_SWITCH_OPEN) || ((state) == CY_CTB_SWITCH_CLOSE)) +#define CY_CTB_OA0SWITCH(mask) (((mask) & (~CY_CTB_DEINIT_OA0_SW)) == 0uL) +#define CY_CTB_OA1SWITCH(mask) (((mask) & (~CY_CTB_DEINIT_OA1_SW)) == 0uL) +#define CY_CTB_CTDSWITCH(mask) (((mask) & (~CY_CTB_DEINIT_CTD_SW)) == 0uL) +#define CY_CTB_SWITCHMASK(select,mask) (((select) == CY_CTB_SWITCH_OA0_SW) ? (((mask) & (~CY_CTB_DEINIT_OA0_SW)) == 0uL) : \ + (((select) == CY_CTB_SWITCH_OA1_SW) ? (((mask) & (~CY_CTB_DEINIT_OA1_SW)) == 0uL) : \ + (((mask) & (~CY_CTB_DEINIT_CTD_SW)) == 0uL))) +#define CY_CTB_SARSEQCTRL(mask) (((mask) == CY_CTB_SW_SEQ_CTRL_D51_MASK) \ + || ((mask) == CY_CTB_SW_SEQ_CTRL_D52_D62_MASK) \ + || ((mask) == CY_CTB_SW_SEQ_CTRL_D51_D52_D62_MASK)) + +/** \endcond */ + +/** \} group_ctb_macros */ + +/*************************************** +* Enumerated Types +***************************************/ + +/** +* \addtogroup group_ctb_enums +* \{ +*/ + +/** +* Most functions allow you to configure a single opamp or both opamps at once. +* The \ref Cy_CTB_SetInterruptMask function can be called with \ref CY_CTB_OPAMP_NONE +* and interrupts will be disabled. +*/ +typedef enum{ + CY_CTB_OPAMP_NONE = 0, /**< For disabling interrupts for both opamps. Used with \ref Cy_CTB_SetInterruptMask */ + CY_CTB_OPAMP_0 = CTBM_INTR_COMP0_Msk, /**< For configuring Opamp0 */ + CY_CTB_OPAMP_1 = CTBM_INTR_COMP1_Msk, /**< For configuring Opamp1 */ + CY_CTB_OPAMP_BOTH = CTBM_INTR_COMP0_Msk | CTBM_INTR_COMP1_Msk, /**< For configuring both Opamp0 and Opamp1 */ +}cy_en_ctb_opamp_sel_t; + +/** Enable or disable CTB while in Deep Sleep mode. +*/ +typedef enum { + CY_CTB_DEEPSLEEP_DISABLE = 0u, /**< CTB is disabled during Deep Sleep power mode */ + CY_CTB_DEEPSLEEP_ENABLE = CTBM_CTB_CTRL_DEEPSLEEP_ON_Msk, /**< CTB remains enabled during Deep Sleep power mode */ +}cy_en_ctb_deep_sleep_t; + +/** +* Configure the power mode of each opamp. Each power setting +* consumes different levels of current and supports a different +* input range and gain bandwidth. +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
Opamp PowerIDDGain bandwidth
OFF0NA
LOW350 uA1 MHz
MEDIUM600 uA3 MHz for 1X, 2.5 MHz for 10x
HIGH1.5 mA8 MHz for 1X, 6 MHz for 10x
+* +*/ +typedef enum { + CY_CTB_POWER_OFF = 0u, /**< Opamp is off */ + CY_CTB_POWER_LOW = 1u, /**< Low power: IDD = 350 uA, GBW = 1 MHz for both 1x and 10x */ + CY_CTB_POWER_MEDIUM = 2u, /**< Medium power: IDD = 600 uA, GBW = 3 MHz for 1x and 2.5 MHz for 10x */ + CY_CTB_POWER_HIGH = 3u, /**< High power: IDD = 1500 uA, GBW = 8 MHz for 1x and 6 MHz for 10x */ +}cy_en_ctb_power_t; + +/** +* The output stage of each opamp can be configured for low-drive strength (1X) to drive internal circuits, +* for high-drive strength (10X) to drive external circuits, or as a comparator. +*/ +typedef enum { + CY_CTB_MODE_OPAMP1X = 0u, /**< Configure opamp for low drive strength for internal connections (1x) */ + CY_CTB_MODE_OPAMP10X = 1u << CTBM_OA_RES0_CTRL_OA0_DRIVE_STR_SEL_Pos, /**< Configure opamp high drive strength for driving a device pin (10x) */ + CY_CTB_MODE_COMP = 1u << CTBM_OA_RES0_CTRL_OA0_COMP_EN_Pos, /**< Configure opamp as a comparator */ +}cy_en_ctb_mode_t; + +/** +* Each opamp has a charge pump to increase the input range to the rails. +* When the charge pump is enabled, the input range is 0 to VDDA. +* When disabled, the input range is 0 to VDDA - 1.5 V. +* +** +* +* +* +* +* +* +* +* +* +*
Charge PumpInput Range (V)
OFF0 to VDDA-1.5
ON0 to VDDA
+* +* Note that in Deep Sleep mode, the charge pump is disabled so the input +* range is reduced. +*/ +typedef enum{ + CY_CTB_PUMP_DISABLE = 0u, /**< Charge pump is disabled for an input range of 0 to VDDA - 1.5 V */ + CY_CTB_PUMP_ENABLE = CTBM_OA_RES0_CTRL_OA0_PUMP_EN_Msk, /**< Charge pump is enabled for an input range of 0 to VDDA */ +}cy_en_ctb_pump_t; + +/** +* Configure the type of edge that will trigger a comparator interrupt or +* disable the interrupt entirely. +*/ +typedef enum +{ + CY_CTB_COMP_EDGE_DISABLE = 0u, /**< Disabled, no interrupts generated */ + CY_CTB_COMP_EDGE_RISING = 1u << CTBM_OA_RES0_CTRL_OA0_COMPINT_Pos, /**< Rising edge generates an interrupt */ + CY_CTB_COMP_EDGE_FALLING = 2u << CTBM_OA_RES0_CTRL_OA0_COMPINT_Pos, /**< Falling edge generates an interrupt */ + CY_CTB_COMP_EDGE_BOTH = 3u << CTBM_OA_RES0_CTRL_OA0_COMPINT_Pos, /**< Both edges generate an interrupt */ +}cy_en_ctb_comp_edge_t; + +/** Configure the comparator DSI trigger output level when output is synchronized. */ +typedef enum +{ + CY_CTB_COMP_DSI_TRIGGER_OUT_PULSE = 0u, /**< Send pulse on DSI for each edge of comparator output */ + CY_CTB_COMP_DSI_TRIGGER_OUT_LEVEL = CTBM_OA_RES0_CTRL_OA0_DSI_LEVEL_Msk, /**< DSI output is synchronized version of comparator output */ +}cy_en_ctb_comp_level_t; + +/** Bypass the comparator output synchronization for DSI trigger. */ +typedef enum +{ + CY_CTB_COMP_BYPASS_SYNC = 0u, /**< Comparator output is synchronized for DSI trigger */ + CY_CTB_COMP_BYPASS_NO_SYNC = CTBM_OA_RES0_CTRL_OA0_BYPASS_DSI_SYNC_Msk, /**< Comparator output is not synchronized for DSI trigger */ +}cy_en_ctb_comp_bypass_t; + +/** Disable or enable the 10 mV hysteresis for the comparator. */ +typedef enum +{ + CY_CTB_COMP_HYST_DISABLE = 0u, /**< Disable hysteresis */ + CY_CTB_COMP_HYST_10MV = CTBM_OA_RES0_CTRL_OA0_HYST_EN_Msk, /**< Enable the 10 mV hysteresis */ +}cy_en_ctb_comp_hyst_t; + +/** Switch state, either open or closed, to be used in \ref Cy_CTB_SetAnalogSwitch. */ +typedef enum +{ + CY_CTB_SWITCH_OPEN = 0uL, /**< Open the switch */ + CY_CTB_SWITCH_CLOSE = 1uL /**< Close the switch */ +}cy_en_ctb_switch_state_t; + +/** +* The switch register to be used in \ref Cy_CTB_SetAnalogSwitch. +* The CTB has three registers for configuring the switch routing matrix. +* */ +typedef enum +{ + CY_CTB_SWITCH_OA0_SW = 0u, /**< Switch register for Opamp0 */ + CY_CTB_SWITCH_OA1_SW = 1u, /**< Switch register for Opamp1 */ + CY_CTB_SWITCH_CTD_SW = 2u, /**< Switch register for CTDAC routing */ +}cy_en_ctb_switch_register_sel_t; + +/** +* Switch masks for Opamp0 to be used in \ref Cy_CTB_SetAnalogSwitch. +*/ +typedef enum +{ + CY_CTB_SW_OA0_POS_AMUXBUSA_MASK = CTBM_OA0_SW_OA0P_A00_Msk, /**< Switch A00: Opamp0 non-inverting input to AMUXBUS A */ + CY_CTB_SW_OA0_POS_PIN0_MASK = CTBM_OA0_SW_OA0P_A20_Msk, /**< Switch A20: Opamp0 non-inverting input to Pin 0 of CTB device port */ + CY_CTB_SW_OA0_POS_PIN6_MASK = CTBM_OA0_SW_OA0P_A30_Msk, /**< Switch A30: Opamp0 non-inverting input to Pin 6 of CTB device port */ + CY_CTB_SW_OA0_NEG_PIN1_MASK = CTBM_OA0_SW_OA0M_A11_Msk, /**< Switch A11: Opamp0 inverting input to Pin 1 of CTB device port */ + CY_CTB_SW_OA0_NEG_OUT_MASK = CTBM_OA0_SW_OA0M_A81_Msk, /**< Switch A81: Opamp0 inverting input to Opamp0 output */ + CY_CTB_SW_OA0_OUT_SARBUS0_MASK = CTBM_OA0_SW_OA0O_D51_Msk, /**< Switch D51: Opamp0 output to sarbus0 */ + CY_CTB_SW_OA0_OUT_SHORT_1X_10X_MASK = CTBM_OA0_SW_OA0O_D81_Msk, /**< Switch D81: Short Opamp0 1x with 10x outputs */ +}cy_en_ctb_oa0_switches_t; + +/** +* Switch masks for Opamp1 to be used in \ref Cy_CTB_SetAnalogSwitch. +*/ +typedef enum +{ + CY_CTB_SW_OA1_POS_AMUXBUSB_MASK = CTBM_OA1_SW_OA1P_A03_Msk, /**< Switch A03: Opamp1 non-inverting input to AMUXBUS B */ + CY_CTB_SW_OA1_POS_PIN5_MASK = CTBM_OA1_SW_OA1P_A13_Msk, /**< Switch A13: Opamp1 non-inverting input to Pin 5 of CTB device port */ + CY_CTB_SW_OA1_POS_PIN7_MASK = CTBM_OA1_SW_OA1P_A43_Msk, /**< Switch A43: Opamp1 non-inverting input to Pin 7 of CTB device port */ + CY_CTB_SW_OA1_POS_AREF_MASK = CTBM_OA1_SW_OA1P_A73_Msk, /**< Switch A73: Opamp1 non-inverting input to device Analog Reference (AREF) */ + CY_CTB_SW_OA1_NEG_PIN4_MASK = CTBM_OA1_SW_OA1M_A22_Msk, /**< Switch A22: Opamp1 inverting input to Pin 4 of CTB device port */ + CY_CTB_SW_OA1_NEG_OUT_MASK = CTBM_OA1_SW_OA1M_A82_Msk, /**< switch A82: Opamp1 inverting input to Opamp1 output */ + CY_CTB_SW_OA1_OUT_SARBUS0_MASK = CTBM_OA1_SW_OA1O_D52_Msk, /**< Switch D52: Opamp1 output to sarbus0 */ + CY_CTB_SW_OA1_OUT_SARBUS1_MASK = CTBM_OA1_SW_OA1O_D62_Msk, /**< Switch D62: Opamp1 output to sarbus1 */ + CY_CTB_SW_OA1_OUT_SHORT_1X_10X_MASK = CTBM_OA1_SW_OA1O_D82_Msk, /**< Switch D82: Short Opamp1 1x with 10x outputs */ +}cy_en_ctb_oa1_switches_t; + +/** +* Switch masks for CTDAC to CTB routing to be used in \ref Cy_CTB_SetAnalogSwitch. +*/ +typedef enum +{ + CY_CTB_SW_CTD_REF_OA1_OUT_MASK = CTBM_CTD_SW_CTDD_CRD_Msk, /**< Switch CRD: Opamp1 output to CTDAC reference. */ + CY_CTB_SW_CTD_REFSENSE_OA1_NEG_MASK = CTBM_CTD_SW_CTDS_CRS_Msk, /**< Switch CRS: CTDAC reference sense to Opamp1 inverting input. */ + CY_CTB_SW_CTD_OUT_OA1_NEG_MASK = CTBM_CTD_SW_CTDS_COR_Msk, /**< Switch COR: CTDAC output to Opamp1 inverting input. */ + CY_CTB_SW_CTD_OUT_PIN6_MASK = CTBM_CTD_SW_CTDO_C6H_Msk, /**< Switch C6H: CTDAC output to P6 of CTB device port. */ + CY_CTB_SW_CTD_OUT_CHOLD_MASK = CTBM_CTD_SW_CTDO_COS_Msk, /**< Switch COS: CTDAC output to hold cap (deglitch capable). */ + CY_CTB_SW_CTD_OUT_OA0_1X_OUT_MASK = CTBM_CTD_SW_CTDH_COB_Msk, /**< Switch COB: Drive CTDAC output with opamp0 1x output during hold mode. */ + CY_CTB_SW_CTD_CHOLD_CONNECT_MASK = CTBM_CTD_SW_CTDH_CHD_Msk, /**< Switch CHD: Hold cap connection. */ + CY_CTB_SW_CTD_CHOLD_OA0_POS_MASK = CTBM_CTD_SW_CTDH_CA0_Msk, /**< Switch CA0: Hold cap to Opamp0 non-inverting input. */ + CY_CTB_SW_CTD_CHOLD_OA0_POS_ISOLATE_MASK = CTBM_CTD_SW_CTDH_CIS_Msk, /**< Switch CIS: Opamp0 non-inverting input isolation (for hold cap) */ + CY_CTB_SW_CTD_CHOLD_LEAKAGE_REDUCTION_MASK = CTBM_CTD_SW_CTDH_ILR_Msk, /**< Switch ILR: Hold cap leakage reduction (drives far side of isolation switch CIS) */ +}cy_en_ctb_ctd_switches_t; + + +/** +* Masks for CTB switches that can be controlled by the SAR sequencer. +* These masks are used in \ref Cy_CTB_EnableSarSeqCtrl and \ref Cy_CTB_DisableSarSeqCtrl. +* +* The SAR ADC subsystem supports analog routes through three CTB switches on SARBUS0 and SARBUS1. +* This control allows for pins on the CTB dedicated port to route to the SAR ADC input channels: +* +* - D51: Connects the inverting terminal of OA0 to SARBUS0 +* - D52: Connects the inverting terminal of OA1 to SARBUS0 +* - D62: Connects the inverting terminal of OA1 to SARBUS1 +*/ +typedef enum +{ + CY_CTB_SW_SEQ_CTRL_D51_MASK = CTBM_CTB_SW_SQ_CTRL_P2_SQ_CTRL23_Msk, /**< Enable SAR sequencer control of the D51 switch */ + CY_CTB_SW_SEQ_CTRL_D52_D62_MASK = CTBM_CTB_SW_SQ_CTRL_P3_SQ_CTRL23_Msk, /**< Enable SAR sequencer control of the D52 and D62 switches */ + CY_CTB_SW_SEQ_CTRL_D51_D52_D62_MASK = CTBM_CTB_SW_SQ_CTRL_P2_SQ_CTRL23_Msk | CTBM_CTB_SW_SQ_CTRL_P3_SQ_CTRL23_Msk, /**< Enable SAR sequency control of all three switches */ +}cy_en_ctb_switch_sar_seq_t; + +/** +* Each opamp also has a programmable compensation capacitor block, +* that optimizes the stability of the opamp performance based on output load. +* The compensation cap will be set by the driver based on the opamp drive strength (1x or 10x) selection. +*/ +typedef enum +{ + CY_CTB_OPAMP_COMPENSATION_CAP_OFF = 0u, /**< No compensation */ + CY_CTB_OPAMP_COMPENSATION_CAP_MIN = 1u, /**< Minimum compensation - for 1x drive*/ + CY_CTB_OPAMP_COMPENSATION_CAP_MED = 2u, /**< Medium compensation */ + CY_CTB_OPAMP_COMPENSATION_CAP_MAX = 3u, /**< Maximum compensation - for 10x drive */ +}cy_en_ctb_compensation_cap_t; + +/** Enable or disable the gain booster. +* The gain booster will be set by the driver based on the opamp drive strength (1x or 10x) selection. +*/ +typedef enum +{ + CY_CTB_OPAMP_BOOST_DISABLE = 0u, /**< Disable gain booster - for 10x drive */ + CY_CTB_OPAMP_BOOST_ENABLE = CTBM_OA_RES0_CTRL_OA0_BOOST_EN_Msk, /**< Enable gain booster - for 1x drive */ +}cy_en_ctb_boost_en_t; + +/** Sample and hold modes for firmware sampling of the CTDAC output. +* +* To perform a sample or a hold, a preparation step must first be executed to +* open the required switches. +* +* -# Call \ref Cy_CTB_DACSampleAndHold with \ref CY_CTB_SH_PREPARE_SAMPLE or \ref CY_CTB_SH_PREPARE_HOLD +* -# Enable or disable CTDAC output +* -# Call \ref Cy_CTB_DACSampleAndHold with \ref CY_CTB_SH_SAMPLE or \ref CY_CTB_SH_HOLD +*/ +typedef enum +{ + CY_CTB_SH_DISABLE = 0u, /**< The hold capacitor is not connected - this disables sample and hold */ + CY_CTB_SH_PREPARE_SAMPLE = 1u, /**< Prepares the required switches for a following sample */ + CY_CTB_SH_SAMPLE = 2u, /**< Performs a sample of the voltage */ + CY_CTB_SH_PREPARE_HOLD = 3u, /**< Prepares the required switches for a following hold */ + CY_CTB_SH_HOLD = 4u, /**< Performs a hold of the previously sampled voltage */ +}cy_en_ctb_sample_hold_mode_t; + +/** AREF IPTAT bias current output for the CTB +* +* The CTB bias current can be 1 uA (normal) or 100 nA (low current). +*/ +typedef enum +{ + CY_CTB_IPTAT_NORMAL = 0u, /**< 1 uA bias current to the CTB */ + CY_CTB_IPTAT_LOW = 1u << PASS_AREF_AREF_CTRL_CTB_IPTAT_SCALE_Pos, /**< 100 nA bias current to the CTB */ +}cy_en_ctb_iptat_t; + +/** CTB charge pump clock sources +* +* The CTB pump clock can come from: +* - a dedicated divider clock in the SRSS +* - one of the CLK_PERI dividers +*/ +typedef enum +{ + CY_CTB_CLK_PUMP_SRSS = 0u, /**< Use the dedicated pump clock from SRSSp */ + CY_CTB_CLK_PUMP_PERI = 1u << PASS_AREF_AREF_CTRL_CLOCK_PUMP_PERI_SEL_Pos, /**< Use one of the CLK_PERI dividers */ +}cy_en_ctb_clk_pump_source_t; + +/** High level opamp current modes */ +typedef enum +{ + CY_CTB_CURRENT_HIGH_ACTIVE = 0u, /**< Uses 1 uA reference current with charge pump enabled. Available in Active and Low Power */ + CY_CTB_CURRENT_HIGH_ACTIVE_DEEPSLEEP = 1u, /**< Uses 1 uA reference current with charge pump disabled. Available in all power modes */ + CY_CTB_CURRENT_LOW_ACTIVE_DEEPSLEEP = 2u, /**< Uses 100 nA reference current with charge pump disabled. Available in all power modes */ +}cy_en_ctb_current_mode_t; + +/** Return states for \ref Cy_CTB_Init, \ref Cy_CTB_OpampInit, \ref Cy_CTB_DeInit, and \ref Cy_CTB_FastInit */ +typedef enum { + CY_CTB_SUCCESS = 0x00uL, /**< Initialization completed successfully */ + CY_CTB_BAD_PARAM = CY_CTB_ID | CY_PDL_STATUS_ERROR | 0x01uL, /**< Input pointers were NULL and initialization could not be completed */ +}cy_en_ctb_status_t; + +/** \} group_ctb_enums */ + +/*************************************** +* Configuration Structures +***************************************/ + +/** +* \addtogroup group_ctb_data_structures +* \{ +*/ + +/** +* Configuration structure to set up the entire CTB to be used with \ref Cy_CTB_Init. +*/ +typedef struct { + cy_en_ctb_deep_sleep_t deepSleep; /**< Enable or disable the CTB during Deep Sleep */ + + /* Opamp0 configuration */ + cy_en_ctb_power_t oa0Power; /**< Opamp0 power mode: off, low, medium, or high */ + cy_en_ctb_mode_t oa0Mode; /**< Opamp0 usage mode: 1x drive, 10x drive, or as a comparator */ + cy_en_ctb_pump_t oa0Pump; /**< Opamp0 charge pump: enable to increase input range for rail-to-rail operation */ + cy_en_ctb_comp_edge_t oa0CompEdge; /**< Opamp0 comparator edge detection: disable, rising, falling, or both */ + cy_en_ctb_comp_level_t oa0CompLevel; /**< Opamp0 comparator DSI (trigger) output: pulse or level */ + cy_en_ctb_comp_bypass_t oa0CompBypass; /**< Opamp0 comparator DSI (trigger) output synchronization */ + cy_en_ctb_comp_hyst_t oa0CompHyst; /**< Opamp0 comparator hysteresis: enable for 10 mV hysteresis */ + bool oa0CompIntrEn; /**< Opamp0 comparator interrupt enable */ + + /* Opamp1 configuration */ + cy_en_ctb_power_t oa1Power; /**< Opamp1 power mode: off, low, medium, or high */ + cy_en_ctb_mode_t oa1Mode; /**< Opamp1 usage mode: 1x drive, 10x drive, or as a comparator */ + cy_en_ctb_pump_t oa1Pump; /**< Opamp1 charge pump: enable to increase input range for rail-to-rail operation */ + cy_en_ctb_comp_edge_t oa1CompEdge; /**< Opamp1 comparator edge detection: disable, rising, falling, or both */ + cy_en_ctb_comp_level_t oa1CompLevel; /**< Opamp1 comparator DSI (trigger) output: pulse or level */ + cy_en_ctb_comp_bypass_t oa1CompBypass; /**< Opamp1 comparator DSI (trigger) output synchronization */ + cy_en_ctb_comp_hyst_t oa1CompHyst; /**< Opamp1 comparator hysteresis: enable for 10 mV hysteresis */ + bool oa1CompIntrEn; /**< Opamp1 comparator interrupt enable */ + + /* Switch analog routing configuration */ + bool configRouting; /**< Configure or ignore routing related registers */ + uint32_t oa0SwitchCtrl; /**< Opamp0 routing control */ + uint32_t oa1SwitchCtrl; /**< Opamp1 routing control */ + uint32_t ctdSwitchCtrl; /**< Routing control between the CTDAC and CTB blocks */ +}cy_stc_ctb_config_t; + +/** +* This configuration structure is used to initialize only one opamp of the CTB +* without impacting analog routing. This structure is used with \ref Cy_CTB_OpampInit. +*/ +typedef struct { + cy_en_ctb_deep_sleep_t deepSleep; /**< Enable or disable the CTB during Deep Sleep */ + + /* Opamp configuration */ + cy_en_ctb_power_t oaPower; /**< Opamp power mode: off, low, medium, or high */ + cy_en_ctb_mode_t oaMode; /**< Opamp usage mode: 1x drive, 10x drive, or as a comparator */ + cy_en_ctb_pump_t oaPump; /**< Opamp charge pump: enable to increase input range for rail-to-rail operation */ + cy_en_ctb_comp_edge_t oaCompEdge; /**< Opamp comparator edge detection: disable, rising, falling, or both */ + cy_en_ctb_comp_level_t oaCompLevel; /**< Opamp comparator DSI (trigger) output: pulse or level */ + cy_en_ctb_comp_bypass_t oaCompBypass; /**< Opamp comparator DSI (trigger) output synchronization */ + cy_en_ctb_comp_hyst_t oaCompHyst; /**< Opamp comparator hysteresis: enable for 10 mV hysteresis */ + bool oaCompIntrEn; /**< Opamp comparator interrupt enable */ +}cy_stc_ctb_opamp_config_t; + +/** This configuration structure is used to quickly initialize Opamp0 for the most commonly used configurations. +* +* Other configuration options are set to: +* - .oa0Pump = \ref CY_CTB_PUMP_ENABLE +* - .oa0CompEdge = \ref CY_CTB_COMP_EDGE_BOTH +* - .oa0CompLevel = \ref CY_CTB_COMP_DSI_TRIGGER_OUT_LEVEL +* - .oa0CompBypass = \ref CY_CTB_COMP_BYPASS_SYNC +* - .oa0CompHyst = \ref CY_CTB_COMP_HYST_10MV +* - .oa0CompIntrEn = true +*/ +typedef struct +{ + cy_en_ctb_power_t oa0Power; /**< Opamp0 power mode: off, low, medium, or high */ + cy_en_ctb_mode_t oa0Mode; /**< Opamp0 usage mode: 1x drive, 10x drive, or as a comparator */ + uint32_t oa0SwitchCtrl; /**< Opamp0 routing control */ + uint32_t ctdSwitchCtrl; /**< Routing control between the CTDAC and CTB blocks */ +}cy_stc_ctb_fast_config_oa0_t; + +/** This configuration structure is used to quickly initialize Opamp1 for the most commonly used configurations. +* +* Other configuration options are set to: +* - .oa1Pump = \ref CY_CTB_PUMP_ENABLE +* - .oa1CompEdge = \ref CY_CTB_COMP_EDGE_BOTH +* - .oa1CompLevel = \ref CY_CTB_COMP_DSI_TRIGGER_OUT_LEVEL +* - .oa1CompBypass = \ref CY_CTB_COMP_BYPASS_SYNC +* - .oa1CompHyst = \ref CY_CTB_COMP_HYST_10MV +* - .oa1CompIntrEn = true +*/ +typedef struct +{ + cy_en_ctb_power_t oa1Power; /**< Opamp1 power mode: off, low, medium, or high */ + cy_en_ctb_mode_t oa1Mode; /**< Opamp1 usage mode: 1x drive, 10x drive, or as a comparator */ + uint32_t oa1SwitchCtrl; /**< Opamp1 routing control */ + uint32_t ctdSwitchCtrl; /**< Routing control between the CTDAC and CTB blocks */ +}cy_stc_ctb_fast_config_oa1_t; + +/** \} group_ctb_data_structures */ + + +/** \addtogroup group_ctb_globals +* \{ +*/ +/*************************************** +* Global Variables +***************************************/ + +/** Configure Opamp0 as unused - powered down. See \ref Cy_CTB_FastInit. */ +extern const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Unused; + +/** Configure Opamp0 as a comparator. No routing is configured. +* +* \image html ctb_fast_config_comp.png +* \image latex ctb_fast_config_comp.png width=100px +* +* See \ref Cy_CTB_FastInit. +*/ +extern const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Comp; + +/** Configure Opamp0 as an opamp with 1x drive. No routing is configured. +* +* \image html ctb_fast_config_opamp1x.png +* \image latex ctb_fast_config_opamp1x.png width=100px +* +* See \ref Cy_CTB_FastInit. +*/ +extern const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Opamp1x; + +/** Configure Opamp0 as an opamp with 10x drive. No routing is configured. +* +* \image html ctb_fast_config_opamp10x.png +* \image latex ctb_fast_config_opamp10x.png width=100px +* +* See \ref Cy_CTB_FastInit. +*/ +extern const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Opamp10x; + +/** Configure Opamp0 as one stage of a differential amplifier. +* The opamp is in 10x drive and the switches shown are closed. +* +* \image html ctb_fast_config_oa0_diffamp.png +* \image latex ctb_fast_config_oa0_diffamp.png width=100px +* +* See the device datasheet for the dedicated CTB port. +* +* To be used with \ref Cy_CTB_FastInit and \ref Cy_CTB_Fast_Opamp1_Diffamp. +*/ +extern const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Diffamp; + +/** Configure Opamp0 as a buffer for the CTDAC output. +* The buffer is in 10x drive and the switches shown are closed. +* Configure the CTDAC for output buffer mode by calling \ref Cy_CTDAC_FastInit +* with \ref Cy_CTDAC_Fast_VddaRef_BufferedOut or \ref Cy_CTDAC_Fast_OA1Ref_BufferedOut. +* +* \image html ctb_fast_config_vdac_output.png +* \image latex ctb_fast_config_vdac_output.png +* +* See the device datasheet for the dedicated CTB port. +* +* See \ref Cy_CTB_FastInit. +*/ +extern const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Vdac_Out; + +/** Configure Opamp0 as a buffer for the CTDAC output with the sample and hold capacitor connected. +* The buffer is in 10x drive and the switches shown are closed. +* Configure the CTDAC for output buffer mode by calling \ref Cy_CTDAC_FastInit +* with \ref Cy_CTDAC_Fast_VddaRef_BufferedOut or \ref Cy_CTDAC_Fast_OA1Ref_BufferedOut. + +* \image html ctb_fast_config_vdac_sh.png +* \image latex ctb_fast_config_vdac_sh.png +* +* See the device datasheet for the dedicated CTB port. +* +* See \ref Cy_CTB_FastInit. +*/ +extern const cy_stc_ctb_fast_config_oa0_t Cy_CTB_Fast_Opamp0_Vdac_Out_SH; + +/** Configure Opamp1 as unused - powered down. See \ref Cy_CTB_FastInit.*/ +extern const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Unused; + +/** Configure Opamp1 as a comparator. No routing is configured. +* +* \image html ctb_fast_config_comp.png +* \image latex ctb_fast_config_comp.png width=100px +* +* See \ref Cy_CTB_FastInit. +*/ +extern const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Comp; + +/** Configure Opamp1 as an opamp with 1x drive. No routing is configured. +* +* \image html ctb_fast_config_opamp1x.png +* \image latex ctb_fast_config_opamp1x.png width=100px +* +* See \ref Cy_CTB_FastInit. +*/ +extern const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Opamp1x; + +/** Configure Opamp1 as an opamp with 10x drive. No routing is configured. +* +* \image html ctb_fast_config_opamp10x.png +* \image latex ctb_fast_config_opamp10x.png width=100px +* +* See \ref Cy_CTB_FastInit. +*/ +extern const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Opamp10x; + +/** Configure Opamp1 as one stage of a differential amplifier. +* The opamp is in 10x drive and the switches shown are closed. +* +* \image html ctb_fast_config_oa1_diffamp.png +* \image latex ctb_fast_config_oa1_diffamp.png width=100px +* +* See the device datasheet for the dedicated CTB port. +* +* To be used with \ref Cy_CTB_FastInit and \ref Cy_CTB_Fast_Opamp0_Diffamp. +* +*/ +extern const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Diffamp; + +/** Configure Opamp1 as a buffer for the CTDAC reference. The reference comes from the +* internal analog reference block (AREF). +* The buffer is in 1x drive and the switches shown are closed. +* Configure the CTDAC to use the buffered reference by calling \ref Cy_CTDAC_FastInit +* with \ref Cy_CTDAC_Fast_OA1Ref_UnbufferedOut or \ref Cy_CTDAC_Fast_OA1Ref_BufferedOut. +* +* \image html ctb_fast_config_vdac_aref.png +* \image latex ctb_fast_config_vdac_aref.png +* +* See \ref Cy_CTB_FastInit. +* +* Note the AREF block needs to be configured using a separate driver. +*/ +extern const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Vdac_Ref_Aref; + +/** Configure Opamp1 as a buffer for the CTDAC reference. The reference comes from Pin 5. +* The buffer is in 1x drive and the switches shown are closed. +* Configure the CTDAC to use the buffered reference by calling \ref Cy_CTDAC_FastInit +* with \ref Cy_CTDAC_Fast_OA1Ref_UnbufferedOut or \ref Cy_CTDAC_Fast_OA1Ref_BufferedOut. +* +* \image html ctb_fast_config_vdac_pin5.png +* \image latex ctb_fast_config_vdac_pin5.png +* +* See the device datasheet for the dedicated CTB port. +* +* See \ref Cy_CTB_FastInit. +*/ +extern const cy_stc_ctb_fast_config_oa1_t Cy_CTB_Fast_Opamp1_Vdac_Ref_Pin5; + +/** \} group_ctb_globals */ + +/*************************************** +* Function Prototypes +***************************************/ + +/** +* \addtogroup group_ctb_functions +* \{ +*/ + +/** +* \addtogroup group_ctb_functions_init +* This set of functions are for initializing, enabling, and disabling the CTB. +* \{ +*/ +cy_en_ctb_status_t Cy_CTB_Init(CTBM_Type *base, const cy_stc_ctb_config_t *config); +cy_en_ctb_status_t Cy_CTB_OpampInit(CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum, const cy_stc_ctb_opamp_config_t *config); +cy_en_ctb_status_t Cy_CTB_DeInit(CTBM_Type *base, bool deInitRouting); +cy_en_ctb_status_t Cy_CTB_FastInit(CTBM_Type *base, const cy_stc_ctb_fast_config_oa0_t *config0, const cy_stc_ctb_fast_config_oa1_t *config1); +__STATIC_INLINE void Cy_CTB_Enable(CTBM_Type *base); +__STATIC_INLINE void Cy_CTB_Disable(CTBM_Type *base); +/** \} */ + +/** +* \addtogroup group_ctb_functions_basic +* This set of functions are for configuring basic usage of the CTB. +* \{ +*/ +void Cy_CTB_SetDeepSleepMode(CTBM_Type *base, cy_en_ctb_deep_sleep_t deepSleep); +void Cy_CTB_SetOutputMode(CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum, cy_en_ctb_mode_t mode); +void Cy_CTB_SetPower(CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum, cy_en_ctb_power_t power, cy_en_ctb_pump_t pump); +/** \} */ + +/** +* \addtogroup group_ctb_functions_sample_hold +* This function enables sample and hold of the CTDAC output. +* \{ +*/ +void Cy_CTB_DACSampleAndHold(CTBM_Type *base, cy_en_ctb_sample_hold_mode_t mode); +/** \} */ + +/** +* \addtogroup group_ctb_functions_comparator +* This set of functions are specific to the comparator mode +* \{ +*/ +void Cy_CTB_CompSetConfig(CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum, cy_en_ctb_comp_level_t level, cy_en_ctb_comp_bypass_t bypass, cy_en_ctb_comp_hyst_t hyst); +uint32_t Cy_CTB_CompGetConfig(const CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum); +void Cy_CTB_CompSetInterruptEdgeType(CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum, cy_en_ctb_comp_edge_t edge); +uint32_t Cy_CTB_CompGetStatus(const CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum); +/** \} */ + +/** +* \addtogroup group_ctb_functions_trim +* These are advanced functions for trimming the offset and slope of the opamps. +* Most users do not need to call these functions and can use the factory trimmed values. +* \{ +*/ +void Cy_CTB_OpampSetOffset(CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum, uint32_t trim); +uint32_t Cy_CTB_OpampGetOffset(const CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum); +void Cy_CTB_OpampSetSlope(CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum, uint32_t trim); +uint32_t Cy_CTB_OpampGetSlope(const CTBM_Type *base, cy_en_ctb_opamp_sel_t opampNum); +/** \} */ + +/** +* \addtogroup group_ctb_functions_switches +* This set of functions is for controlling routing switches. +* \{ +*/ +void Cy_CTB_SetAnalogSwitch(CTBM_Type *base, cy_en_ctb_switch_register_sel_t switchSelect, uint32_t switchMask, cy_en_ctb_switch_state_t state); +uint32_t Cy_CTB_GetAnalogSwitch(const CTBM_Type *base, cy_en_ctb_switch_register_sel_t switchSelect); +__STATIC_INLINE void Cy_CTB_OpenAllSwitches(CTBM_Type *base); +__STATIC_INLINE void Cy_CTB_EnableSarSeqCtrl(CTBM_Type *base, cy_en_ctb_switch_sar_seq_t switchMask); +__STATIC_INLINE void Cy_CTB_DisableSarSeqCtrl(CTBM_Type *base, cy_en_ctb_switch_sar_seq_t switchMask); +/** \} */ + +/** +* \addtogroup group_ctb_functions_interrupts +* This set of functions is related to the comparator interrupts. +* \{ +*/ +__STATIC_INLINE uint32_t Cy_CTB_GetInterruptStatus(const CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum); +__STATIC_INLINE void Cy_CTB_ClearInterrupt(CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum); +__STATIC_INLINE void Cy_CTB_SetInterrupt(CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum); +__STATIC_INLINE void Cy_CTB_SetInterruptMask(CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum); +__STATIC_INLINE uint32_t Cy_CTB_GetInterruptMask(const CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum); +__STATIC_INLINE uint32_t Cy_CTB_GetInterruptStatusMasked(const CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum); +/** \} */ + +/** +* \addtogroup group_ctb_functions_aref +* This set of functions impacts all opamps on the chip. +* Notice how some of these functions do not take a base address input. +* When calling \ref Cy_CTB_SetCurrentMode for a CTB instance on the device, +* it should be called for all other CTB instances as well. This is because +* there is only one IPTAT level (1 uA or 100 nA) chip wide. +* \{ +*/ +void Cy_CTB_SetCurrentMode(CTBM_Type *base, cy_en_ctb_current_mode_t currentMode); +__STATIC_INLINE void Cy_CTB_SetIptatLevel(cy_en_ctb_iptat_t iptat); +__STATIC_INLINE void Cy_CTB_SetClkPumpSource(cy_en_ctb_clk_pump_source_t clkPump); +__STATIC_INLINE void Cy_CTB_EnableRedirect(void); +__STATIC_INLINE void Cy_CTB_DisableRedirect(void); +/** \} */ + +/** +* \addtogroup group_ctb_functions_init +* \{ +*/ + +/******************************************************************************* +* Function Name: Cy_CTB_Enable +****************************************************************************//** +* +* Power up the CTB hardware block. +* +* \param base +* Pointer to structure describing registers +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTB_Enable(CTBM_Type *base) +{ + base->CTB_CTRL |= CTBM_CTB_CTRL_ENABLED_Msk; +} + +/******************************************************************************* +* Function Name: Cy_CTB_Disable +****************************************************************************//** +* +* Power down the CTB hardware block. +* +* \param base +* Pointer to structure describing registers +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTB_Disable(CTBM_Type *base) +{ + base->CTB_CTRL &= (~CTBM_CTB_CTRL_ENABLED_Msk); +} + +/** \} */ + +/** +* \addtogroup group_ctb_functions_switches +* \{ +*/ + +/******************************************************************************* +* Function Name: Cy_CTB_OpenAllSwitches +****************************************************************************//** +* +* Open all the switches and disable all hardware (SAR Sequencer and DSI) control of the switches. +* Primarily used as a quick method of re-configuring all analog connections +* that are sparsely closed. +* +* \param base +* Pointer to structure describing registers +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_OPEN_ALL_SWITCHES +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTB_OpenAllSwitches(CTBM_Type *base) +{ + base->OA0_SW_CLEAR = CY_CTB_DEINIT_OA0_SW; + base->OA1_SW_CLEAR = CY_CTB_DEINIT_OA1_SW; + base->CTD_SW_CLEAR = CY_CTB_DEINIT_CTD_SW; + base->CTB_SW_DS_CTRL = CY_CTB_DEINIT; + base->CTB_SW_SQ_CTRL = CY_CTB_DEINIT; +} + +/******************************************************************************* +* Function Name: Cy_CTB_EnableSarSeqCtrl +****************************************************************************//** +* +* Enable SAR sequencer control of specified switch(es). +* +* This allows the SAR ADC to use routes through the CTB when configuring its channels. +* +* There are three switches in the CTB that can be enabled by the SAR sequencer. +* - D51: This switch connects the negative input of Opamp0 to the SARBUS0 +* - D52: This switch connects the positive input of Opamp1 to the SARBUS0 +* - D62: This switch connects the positive input of Opamp1 to the SARBUS1 +* +* \param base +* Pointer to structure describing registers +* +* \param switchMask +* The switch or switches in which to enable SAR sequencer control. +* Use an enumerated value from \ref cy_en_ctb_switch_sar_seq_t. +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_ENABLE_SAR_SEQ_CTRL +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTB_EnableSarSeqCtrl(CTBM_Type *base, cy_en_ctb_switch_sar_seq_t switchMask) +{ + CY_ASSERT_L3(CY_CTB_SARSEQCTRL(switchMask)); + + base->CTB_SW_SQ_CTRL |= (uint32_t) switchMask; +} + +/******************************************************************************* +* Function Name: Cy_CTB_DisableSarSeqCtrl +****************************************************************************//** +* +* Disable SAR sequencer control of specified switch(es). +* +* \param base +* Pointer to structure describing registers +* +* \param switchMask +* The switch or switches in which to disable SAR sequencer control. +* Use an enumerated value from \ref cy_en_ctb_switch_sar_seq_t. +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_DISABLE_SAR_SEQ_CTRL +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTB_DisableSarSeqCtrl(CTBM_Type *base, cy_en_ctb_switch_sar_seq_t switchMask) +{ + CY_ASSERT_L3(CY_CTB_SARSEQCTRL(switchMask)); + + base->CTB_SW_SQ_CTRL &= ~((uint32_t) switchMask); +} +/** \} */ + +/** +* \addtogroup group_ctb_functions_interrupts +* \{ +*/ + +/******************************************************************************* +* Function Name: Cy_CTB_GetInterruptStatus +****************************************************************************//** +* +* Return the status of the interrupt when the configured comparator +* edge is detected. +* +* \param base +* Pointer to structure describing registers +* +* \param compNum +* \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH +* +* \return +* The interrupt status. +* If compNum is \ref CY_CTB_OPAMP_BOTH, cast the returned status +* to \ref cy_en_ctb_opamp_sel_t to determine which comparator edge (or both) +* was detected. +* - 0: Edge was not detected +* - Non-zero: Configured edge type was detected +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm0p.c SNIPPET_COMP_GETINTERRUPTSTATUS +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_CTB_GetInterruptStatus(const CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM(compNum)); + + return base->INTR & (uint32_t) compNum; +} + +/******************************************************************************* +* Function Name: Cy_CTB_ClearInterrupt +****************************************************************************//** +* +* Clear the CTB comparator triggered interrupt. +* The interrupt must be cleared with this function so that the hardware +* can set subsequent interrupts and those interrupts can be forwarded +* to the interrupt controller, if enabled. +* +* \param base +* Pointer to structure describing registers +* +* \param compNum +* \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTB_ClearInterrupt(CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM(compNum)); + + base->INTR = (uint32_t) compNum; + + /* Dummy read for buffered writes. */ + (void) base->INTR; +} + +/******************************************************************************* +* Function Name: Cy_CTB_SetInterrupt +****************************************************************************//** +* +* Force the CTB interrupt to trigger using software. +* +* \param base +* Pointer to structure describing registers +* +* \param compNum +* \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTB_SetInterrupt(CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM(compNum)); + + base->INTR_SET = (uint32_t) compNum; +} + +/******************************************************************************* +* Function Name: Cy_CTB_SetInterruptMask +****************************************************************************//** +* +* Configure the CTB comparator edge interrupt to be forwarded to the +* CPU interrupt controller. +* +* \param base +* Pointer to structure describing registers +* +* \param compNum +* \ref CY_CTB_OPAMP_NONE, \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH. +* Calling this function with CY_CTB_OPAMP_NONE will disable all interrupt requests. +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_INTERRUPT_MASK +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTB_SetInterruptMask(CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM_ALL(compNum)); + + base->INTR_MASK = (uint32_t) compNum; +} + +/******************************************************************************* +* Function Name: Cy_CTB_GetInterruptMask +****************************************************************************//** +* +* Return whether the CTB comparator edge interrupt output is +* forwarded to the CPU interrupt controller as configured by +* \ref Cy_CTB_SetInterruptMask. +* +* \param base +* Pointer to structure describing registers +* +* \param compNum +* \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH +* +* \return +* The interrupt mask. +* If compNum is \ref CY_CTB_OPAMP_BOTH, cast the returned mask +* to \ref cy_en_ctb_opamp_sel_t to determine which comparator interrupt +* output (or both) is forwarded. +* - 0: Interrupt output not forwarded to interrupt controller +* - Non-zero: Interrupt output forwarded to interrupt controller +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_GET_INTERRUPT_MASK +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_CTB_GetInterruptMask(const CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM(compNum)); + + return base->INTR_MASK & (uint32_t) compNum; +} + +/******************************************************************************* +* Function Name: Cy_CTB_GetInterruptStatusMasked +****************************************************************************//** +* +* Return the CTB comparator edge output interrupt state after being masked. +* This is the bitwise AND of \ref Cy_CTB_GetInterruptStatus and \ref Cy_CTB_GetInterruptMask. +* +* \param base +* Pointer to structure describing registers +* +* \param compNum +* \ref CY_CTB_OPAMP_0, \ref CY_CTB_OPAMP_1, or \ref CY_CTB_OPAMP_BOTH +* +* \return +* If compNum is \ref CY_CTB_OPAMP_BOTH, cast the returned value +* to \ref cy_en_ctb_opamp_sel_t to determine which comparator interrupt +* output (or both) is detected and masked. +* - 0: Configured edge not detected or not masked +* - Non-zero: Configured edge type detected and masked +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_CTB_GetInterruptStatusMasked(const CTBM_Type *base, cy_en_ctb_opamp_sel_t compNum) +{ + CY_ASSERT_L3(CY_CTB_OPAMPNUM(compNum)); + + return base->INTR_MASKED & (uint32_t) compNum; +} +/** \} */ + +/** +* \addtogroup group_ctb_functions_aref +* \{ +*/ + +/******************************************************************************* +* Function Name: Cy_CTB_SetIptatLevel +****************************************************************************//** +* +* Set the IPTAT reference level to 1 uA or 100 nA. The IPTAT generator is used by the CTB +* for slope offset drift. +* +* \param iptat +* Value from enum \ref cy_en_ctb_iptat_t +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_IPTAT_LEVEL +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTB_SetIptatLevel(cy_en_ctb_iptat_t iptat) +{ + CY_ASSERT_L3(CY_CTB_IPTAT(iptat)); + + PASS_AREF->AREF_CTRL = (PASS_AREF->AREF_CTRL & ~PASS_AREF_AREF_CTRL_CTB_IPTAT_SCALE_Msk) | (uint32_t) iptat; +} + +/******************************************************************************* +* Function Name: Cy_CTB_SetClkPumpSource +****************************************************************************//** +* +* Set the clock source for both charge pumps in the CTB. Recall that each opamp +* has its own charge pump. The clock can come from: +* +* - A dedicated divider off of one of the CLK_PATH in the SRSS. +* Call the following functions to configure the pump clock from the SRSS: +* - \ref Cy_SysClk_ClkPumpSetSource +* - \ref Cy_SysClk_ClkPumpSetDivider +* - \ref Cy_SysClk_ClkPumpEnable +* - One of the Peri Clock dividers. +* Call the following functions to configure a Peri Clock divider as the +* pump clock: +* - \ref Cy_SysClk_PeriphAssignDivider with the IP block set to PCLK_PASS_CLOCK_PUMP_PERI +* - \ref Cy_SysClk_PeriphSetDivider +* - \ref Cy_SysClk_PeriphEnableDivider +* +* \param clkPump +* Clock source selection (SRSS or PeriClk) for the pump. Select a value from +* \ref cy_en_ctb_clk_pump_source_t +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_CLK_PUMP_SOURCE_SRSS +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_SET_CLK_PUMP_SOURCE_PERI +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTB_SetClkPumpSource(cy_en_ctb_clk_pump_source_t clkPump) +{ + CY_ASSERT_L3(CY_CTB_CLKPUMP(clkPump)); + + PASS_AREF->AREF_CTRL = (PASS_AREF->AREF_CTRL & ~PASS_AREF_AREF_CTRL_CLOCK_PUMP_PERI_SEL_Msk) | (uint32_t) clkPump; +} + +/******************************************************************************* +* Function Name: Cy_CTB_EnableRedirect +****************************************************************************//** +* +* Normally, the AREF IZTAT is routed to the CTB IZTAT and the AREF IPTAT +* is routed to the CTB IPTAT: +* +* - CTB.IZTAT = AREF.IZTAT +* - CTB.IPTAT = AREF.IPTAT +* +* However, the AREF IPTAT can be redirected to the CTB IZTAT and the CTB IPTAT +* is off. +* +* - CTB.IZTAT = AREF.IPTAT +* - CTB.IPTAT = HiZ +* +* The redirection applies to all opamps on the device and +* should be used when the IPTAT bias level is set to 100 nA +* (see \ref Cy_CTB_SetIptatLevel). +* +* When the CTB.IPTAT is HiZ, the CTB cannot compensate for the slope of +* the offset across temperature. +* +* \return None +* +* \funcusage +* +* \snippet ctb_sut_01.cydsn/main_cm4.c CTB_SNIPPET_ENABLE_REDIRECT +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTB_EnableRedirect(void) +{ + PASS_AREF->AREF_CTRL |= PASS_AREF_AREF_CTRL_CTB_IPTAT_REDIRECT_Msk; +} + +/******************************************************************************* +* Function Name: Cy_CTB_DisableRedirect +****************************************************************************//** +* +* Disable the redirection of the AREF IPTAT to the CTB IZTAT for all opamps +* on the device as enabled by \ref Cy_CTB_EnableRedirect. +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTB_DisableRedirect(void) +{ + PASS_AREF->AREF_CTRL &= ~(PASS_AREF_AREF_CTRL_CTB_IPTAT_REDIRECT_Msk); +} + +/** \} */ + +/** \} group_ctb_functions */ + +#if defined(__cplusplus) +} +#endif + +#endif /** !defined(CY_CTB_H) */ + +/** \} group_ctb */ + +/* [] END OF FILE */ + diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ctdac/cy_ctdac.c b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ctdac/cy_ctdac.c new file mode 100644 index 0000000000..7ec4d5838d --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ctdac/cy_ctdac.c @@ -0,0 +1,721 @@ +/***************************************************************************//** +* \file cy_ctdac.c +* \version 1.0.1 +* +* Provides the public functions for the API for the CTDAC driver. +* +******************************************************************************** +* \copyright +* Copyright 2017-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include "ctdac/cy_ctdac.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** Static function to configure the clock */ +static void Cy_CTDAC_ConfigureClock(cy_en_ctdac_update_t updateMode, cy_en_divider_types_t dividerType, + uint32_t dividerNum, uint32_t dividerIntValue, uint32_t dividerFracValue); + +const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_VddaRef_UnbufferedOut = +{ + /*.refSource */ CY_CTDAC_REFSOURCE_VDDA, + /*.outputBuffer */ CY_CTDAC_OUTPUT_UNBUFFERED, +}; + +const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_VddaRef_BufferedOut = +{ + /*.refSource */ CY_CTDAC_REFSOURCE_VDDA, + /*.outputBuffer */ CY_CTDAC_OUTPUT_BUFFERED, +}; + +const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_OA1Ref_UnbufferedOut = +{ + /*.refSource */ CY_CTDAC_REFSOURCE_EXTERNAL, + /*.outputBuffer */ CY_CTDAC_OUTPUT_UNBUFFERED, +}; + +const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_OA1Ref_BufferedOut = +{ + /*.refSource */ CY_CTDAC_REFSOURCE_EXTERNAL, + /*.outputBuffer */ CY_CTDAC_OUTPUT_BUFFERED, +}; + +/******************************************************************************* +* Function Name: Cy_CTDAC_Init +****************************************************************************//** +* +* Initialize all CTDAC configuration registers +* +* \param base +* Pointer to structure describing registers +* +* \param config +* Pointer to structure containing configuration data +* +* \return +* Status of initialization, \ref CY_CTDAC_SUCCESS or \ref CY_CTDAC_BAD_PARAM +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_INIT_CUSTOM +* +*******************************************************************************/ +cy_en_ctdac_status_t Cy_CTDAC_Init(CTDAC_Type *base, const cy_stc_ctdac_config_t *config) +{ + CY_ASSERT_L1(NULL != base); + CY_ASSERT_L1(NULL != config); + + cy_en_ctdac_status_t result; + uint32_t ctdacCtrl = CY_CTDAC_DEINIT; + uint32_t setSwitch = CY_CTDAC_DEINIT; + uint32_t clearSwitch = CY_CTDAC_DEINIT; + + if ((NULL == base) || (NULL == config)) + { + result = CY_CTDAC_BAD_PARAM; + } + else + { + + CY_ASSERT_L3(CY_CTDAC_REFSOURCE(config->refSource)); + CY_ASSERT_L3(CY_CTDAC_FORMAT(config->formatMode)); + CY_ASSERT_L3(CY_CTDAC_UPDATE(config->updateMode)); + CY_ASSERT_L3(CY_CTDAC_DEGLITCH(config->deglitchMode)); + CY_ASSERT_L3(CY_CTDAC_OUTPUTMODE(config->outputMode)); + CY_ASSERT_L3(CY_CTDAC_OUTPUTBUFFER(config->outputBuffer)); + CY_ASSERT_L3(CY_CTDAC_DEEPSLEEP(config->deepSleep)); + CY_ASSERT_L2(CY_CTDAC_DEGLITCHCYCLES(config->deglitchCycles)); + + /* Handle the deglitch counts */ + ctdacCtrl |= (config->deglitchCycles << CTDAC_CTDAC_CTRL_DEGLITCH_CNT_Pos) & CTDAC_CTDAC_CTRL_DEGLITCH_CNT_Msk; + + /* Handle the deglitch mode */ + ctdacCtrl |= (uint32_t)config->deglitchMode; + + /* Handle the update mode */ + if ((config->updateMode == CY_CTDAC_UPDATE_STROBE_EDGE_IMMEDIATE) \ + || (config->updateMode == CY_CTDAC_UPDATE_STROBE_EDGE_SYNC) \ + || (config->updateMode == CY_CTDAC_UPDATE_STROBE_LEVEL)) + { + ctdacCtrl |= CTDAC_CTDAC_CTRL_DSI_STROBE_EN_Msk; + } + + if (config->updateMode == CY_CTDAC_UPDATE_STROBE_LEVEL) + { + ctdacCtrl |= CTDAC_CTDAC_CTRL_DSI_STROBE_LEVEL_Msk; + } + + /* Handle the sign format */ + ctdacCtrl |= (uint32_t)config->formatMode; + + /* Handle the Deep Sleep mode */ + ctdacCtrl |= (uint32_t)config->deepSleep; + + /* Handle the output mode */ + ctdacCtrl |= (uint32_t)config->outputMode; + + /* Handle the reference source */ + switch(config->refSource) + { + case CY_CTDAC_REFSOURCE_VDDA: + + /* Close the CVD switch to use Vdda as the reference source */ + setSwitch |= CTDAC_CTDAC_SW_CTDD_CVD_Msk; + break; + case CY_CTDAC_REFSOURCE_EXTERNAL: + default: + clearSwitch |= CTDAC_CTDAC_SW_CLEAR_CTDD_CVD_Msk; + break; + } + + /* Handle the output buffer switch CO6 */ + switch(config->outputBuffer) + { + case CY_CTDAC_OUTPUT_UNBUFFERED: + + /* Close the CO6 switch to send output to a direct pin unbuffered */ + setSwitch |= CTDAC_CTDAC_SW_CTDO_CO6_Msk; + break; + case CY_CTDAC_OUTPUT_BUFFERED: + default: + clearSwitch |= CTDAC_CTDAC_SW_CTDO_CO6_Msk; + break; + } + + base->INTR_MASK = (uint32_t)config->enableInterrupt << CTDAC_INTR_VDAC_EMPTY_Pos; + base->CTDAC_SW = setSwitch; + base->CTDAC_SW_CLEAR = clearSwitch; + base->CTDAC_VAL = (((uint32_t)config->value) << CTDAC_CTDAC_VAL_VALUE_Pos) & CTDAC_CTDAC_VAL_VALUE_Msk; + base->CTDAC_VAL_NXT = (((uint32_t)config->nextValue) << CTDAC_CTDAC_VAL_NXT_VALUE_Pos) & CTDAC_CTDAC_VAL_NXT_VALUE_Msk; + + if (config->configClock) + { + Cy_CTDAC_ConfigureClock(config->updateMode, config->dividerType, config->dividerNum, config->dividerIntValue, config->dividerFracValue); + } + + base->CTDAC_CTRL = ctdacCtrl; + result = CY_CTDAC_SUCCESS; + } + + return result; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_DeInit +****************************************************************************//** +* +* Reset CTDAC registers back to power on reset defaults. +* +* \note +* Does not disable the clock. +* +* \param base +* Pointer to structure describing registers +* +* \param deInitRouting +* If true, all switches are reset to their default state. +* If false, switch registers are untouched. +* +* \return +* Status of initialization, \ref CY_CTDAC_SUCCESS, or \ref CY_CTDAC_BAD_PARAM +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_DEINIT +* +*******************************************************************************/ +cy_en_ctdac_status_t Cy_CTDAC_DeInit(CTDAC_Type *base, bool deInitRouting) +{ + CY_ASSERT_L1(NULL != base); + + cy_en_ctdac_status_t result; + + if (NULL == base) + { + result = CY_CTDAC_BAD_PARAM; + } + else + { + base->CTDAC_CTRL = CY_CTDAC_DEINIT; + base->INTR_MASK = CY_CTDAC_DEINIT; + base->CTDAC_VAL = CY_CTDAC_DEINIT; + base->CTDAC_VAL_NXT = CY_CTDAC_DEINIT; + + if (deInitRouting) + { + base->CTDAC_SW_CLEAR = CY_CTDAC_DEINIT; + } + + result = CY_CTDAC_SUCCESS; + } + + return result; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_FastInit +****************************************************************************//** +* +* Initialize the CTDAC to one of the common use modes. +* This function provides a quick and easy method of configuring the CTDAC when using +* the PDL driver for device configuration. +* +* The other configuration options are set to: +* - .formatMode = \ref CY_CTDAC_FORMAT_UNSIGNED +* - .updateMode = \ref CY_CTDAC_UPDATE_BUFFERED_WRITE +* - .deglitchMode = \ref CY_CTDAC_DEGLITCHMODE_NONE +* - .outputMode = \ref CY_CTDAC_OUTPUT_VALUE +* - .deepSleep = \ref CY_CTDAC_DEEPSLEEP_DISABLE +* - .deglitchCycles = \ref CY_CTDAC_DEINIT +* - .value = \ref CY_CTDAC_UNSIGNED_MID_CODE_VALUE +* - .nextValue = \ref CY_CTDAC_UNSIGNED_MID_CODE_VALUE +* - .enableInterrupt = true +* - .configClock = true +* - .dividerType = \ref CY_CTDAC_FAST_CLKCFG_TYPE +* - .dividerNum = \ref CY_CTDAC_FAST_CLKCFG_NUM +* - .dividerInitValue = \ref CY_CTDAC_FAST_CLKCFG_DIV +* - .dividerFracValue = \ref CY_CTDAC_DEINIT +* +* A separate call to \ref Cy_CTDAC_Enable is needed to turn on the hardware. +* +* \param base +* Pointer to structure describing registers +* +* \param config +* Pointer to structure containing configuration data for quick initialization. +* Define your own or use one of the provided structures: +* - \ref Cy_CTDAC_Fast_VddaRef_UnbufferedOut +* - \ref Cy_CTDAC_Fast_VddaRef_BufferedOut +* - \ref Cy_CTDAC_Fast_OA1Ref_UnbufferedOut +* - \ref Cy_CTDAC_Fast_OA1Ref_BufferedOut +* +* \return +* Status of initialization, \ref CY_CTDAC_SUCCESS or \ref CY_CTDAC_BAD_PARAM +* +* \funcusage +* +* The following code snippets configures VDDA as the reference source and +* routes the output directly to Pin 6 (unbuffered). +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_FAST_INIT +* +* \funcusage +* +* The following code snippet shows how the CTDAC and CTB blocks can +* quickly be configured to work together. The code +* configures the CTDAC to use a buffered output, +* a buffered reference source from the internal bandgap voltage, and closes +* all required analog routing switches. +* +* \image html ctdac_fast_init_funcusage.png +* \image latex ctdac_fast_init_funcusage.png +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_FAST_INIT_CTB +* +*******************************************************************************/ +cy_en_ctdac_status_t Cy_CTDAC_FastInit(CTDAC_Type *base, const cy_stc_ctdac_fast_config_t *config) +{ + CY_ASSERT_L1(NULL != base); + CY_ASSERT_L1(NULL != config); + + cy_en_ctdac_status_t result; + uint32_t ctdacCtrl; + uint32_t setSwitch = CY_CTDAC_DEINIT; + uint32_t clearSwitch = CY_CTDAC_DEINIT; + + if ((NULL == base) || (NULL == config)) + { + result = CY_CTDAC_BAD_PARAM; + } + else + { + CY_ASSERT_L3(CY_CTDAC_REFSOURCE(config->refSource)); + CY_ASSERT_L3(CY_CTDAC_OUTPUTBUFFER(config->outputBuffer)); + + ctdacCtrl = (uint32_t) CY_CTDAC_DEGLITCHMODE_NONE \ + | (uint32_t) CY_CTDAC_UPDATE_BUFFERED_WRITE \ + | (uint32_t) CY_CTDAC_FORMAT_UNSIGNED \ + | (uint32_t) CY_CTDAC_DEEPSLEEP_DISABLE \ + | (uint32_t) CY_CTDAC_OUTPUT_VALUE; + + /* Handle the reference source */ + switch(config->refSource) + { + case CY_CTDAC_REFSOURCE_VDDA: + + /* Close the CVD switch to use Vdda as the reference source */ + setSwitch |= CTDAC_CTDAC_SW_CTDD_CVD_Msk; + break; + case CY_CTDAC_REFSOURCE_EXTERNAL: + default: + clearSwitch |= CTDAC_CTDAC_SW_CLEAR_CTDD_CVD_Msk; + break; + } + + /* Handle the output buffer switch CO6 */ + switch(config->outputBuffer) + { + case CY_CTDAC_OUTPUT_UNBUFFERED: + + /* Close the CO6 switch to send output to a direct pin unbuffered */ + setSwitch |= CTDAC_CTDAC_SW_CTDO_CO6_Msk; + break; + case CY_CTDAC_OUTPUT_BUFFERED: + default: + clearSwitch |= CTDAC_CTDAC_SW_CTDO_CO6_Msk; + break; + } + + base->INTR_MASK = CTDAC_INTR_VDAC_EMPTY_Msk; + base->CTDAC_SW = setSwitch; + base->CTDAC_SW_CLEAR = clearSwitch; + base->CTDAC_VAL = CY_CTDAC_UNSIGNED_MID_CODE_VALUE; + base->CTDAC_VAL_NXT = CY_CTDAC_UNSIGNED_MID_CODE_VALUE; + + /* For fast configuration, the DAC clock is the Peri clock divided by 100. */ + Cy_CTDAC_ConfigureClock(CY_CTDAC_UPDATE_BUFFERED_WRITE, CY_CTDAC_FAST_CLKCFG_TYPE, CY_CTDAC_FAST_CLKCFG_NUM, CY_CTDAC_FAST_CLKCFG_DIV, CY_CTDAC_DEINIT); + + base->CTDAC_CTRL = ctdacCtrl; + result = CY_CTDAC_SUCCESS; + } + + return result; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_ConfigureClock +****************************************************************************//** +* +* Private function for configuring the CTDAC clock based on the desired +* update mode. This function is called by \ref Cy_CTDAC_Init. +* +* \param updateMode +* Update mode value. See \ref cy_en_ctdac_update_t for values. +* +* \return None +* +*******************************************************************************/ +static void Cy_CTDAC_ConfigureClock(cy_en_ctdac_update_t updateMode, cy_en_divider_types_t dividerType, + uint32_t dividerNum, uint32_t dividerIntValue, uint32_t dividerFracValue) +{ + if (updateMode == CY_CTDAC_UPDATE_DIRECT_WRITE) + { /* In direct mode, there is not a clock */ + } + else if(updateMode == CY_CTDAC_UPDATE_STROBE_EDGE_IMMEDIATE) + { + + /* In this mode, the Peri Clock is divided by 1 to give a constant logic high on the CTDAC clock. */ + (void)Cy_SysClk_PeriphDisableDivider(dividerType, dividerNum); + + (void)Cy_SysClk_PeriphAssignDivider(PCLK_PASS_CLOCK_CTDAC, dividerType, dividerNum); + + if ((dividerType == CY_SYSCLK_DIV_8_BIT) || (dividerType == CY_SYSCLK_DIV_16_BIT)) + { + (void)Cy_SysClk_PeriphSetDivider(dividerType, dividerNum, CY_CTDAC_STROBE_EDGE_IMMEDIATE_DIV); + } + else + { + (void)Cy_SysClk_PeriphSetFracDivider(dividerType, dividerNum, CY_CTDAC_STROBE_EDGE_IMMEDIATE_DIV, CY_CTDAC_STROBE_EDGE_IMMEDIATE_DIV_FRAC); + } + + (void)Cy_SysClk_PeriphEnableDivider(dividerType, dividerNum); + } + else + { + + /* All other modes, require a CTDAC clock configured to the desired user frequency */ + (void)Cy_SysClk_PeriphDisableDivider(dividerType, dividerNum); + + (void)Cy_SysClk_PeriphAssignDivider(PCLK_PASS_CLOCK_CTDAC, dividerType, dividerNum); + + if ((dividerType == CY_SYSCLK_DIV_8_BIT) || (dividerType == CY_SYSCLK_DIV_16_BIT)) + { + (void)Cy_SysClk_PeriphSetDivider(dividerType, dividerNum, dividerIntValue); + } + else + { + (void)Cy_SysClk_PeriphSetFracDivider(dividerType, dividerNum, dividerIntValue, dividerFracValue); + } + (void)Cy_SysClk_PeriphEnableDivider(dividerType, dividerNum); + } + +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_SetSignMode +****************************************************************************//** +* +* Set whether to interpret the DAC value as signed or unsigned. +* In unsigned mode, the DAC value register is used without any decoding. +* In signed mode, the MSB is inverted by adding 0x800 to the DAC value. +* This converts the lowest signed number, 0x800, to the lowest unsigned +* number, 0x000. +* +* \param base +* Pointer to structure describing registers +* +* \param formatMode +* Mode can be signed or unsigned. See \ref cy_en_ctdac_format_t for values. +* +* \return None +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_SET_SIGN_MODE +* +*******************************************************************************/ +void Cy_CTDAC_SetSignMode(CTDAC_Type *base, cy_en_ctdac_format_t formatMode) +{ + CY_ASSERT_L3(CY_CTDAC_FORMAT(formatMode)); + + uint32_t ctdacCtrl; + + /* Clear the CTDAC_MODE bits */ + ctdacCtrl = base->CTDAC_CTRL & ~CTDAC_CTDAC_CTRL_CTDAC_MODE_Msk; + + base->CTDAC_CTRL = ctdacCtrl | (uint32_t)formatMode; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_SetDeepSleepMode +****************************************************************************//** +* +* Enable or disable the DAC hardware operation in Deep Sleep mode. +* +* \param base +* Pointer to structure describing registers +* +* \param deepSleep +* Enable or disable Deep Sleep operation. Select value from \ref cy_en_ctdac_deep_sleep_t. +* +* \return None +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_SET_DEEPSLEEP_MODE +* +*******************************************************************************/ +void Cy_CTDAC_SetDeepSleepMode(CTDAC_Type *base, cy_en_ctdac_deep_sleep_t deepSleep) +{ + CY_ASSERT_L3(CY_CTDAC_DEEPSLEEP(deepSleep)); + + uint32_t ctdacCtrl; + + ctdacCtrl = base->CTDAC_CTRL & ~CTDAC_CTDAC_CTRL_DEEPSLEEP_ON_Msk; + + base->CTDAC_CTRL = ctdacCtrl | (uint32_t)deepSleep; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_SetOutputMode +****************************************************************************//** +* +* Set the output mode of the CTDAC: +* - \ref CY_CTDAC_OUTPUT_HIGHZ : Disable the output +* - \ref CY_CTDAC_OUTPUT_VALUE : Enable the output and drive the value +* stored in the CTDAC_VAL register. +* - \ref CY_CTDAC_OUTPUT_VALUE_PLUS1 : Enable the output and drive the +* value stored in the CTDAC_VAL register plus 1. +* - \ref CY_CTDAC_OUTPUT_VSSA : Output pulled to VSSA through 1.1 MOhm (typ) resistor. +* - \ref CY_CTDAC_OUTPUT_VREF : Output pulled to VREF through 1.1 MOhm (typ) resistor. +* +* \param base +* Pointer to structure describing registers +* +* \param outputMode +* Select a value from \ref cy_en_ctdac_output_mode_t. +* +* \return None +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_SET_OUTPUT_MODE +* +*******************************************************************************/ +void Cy_CTDAC_SetOutputMode(CTDAC_Type *base, cy_en_ctdac_output_mode_t outputMode) +{ + CY_ASSERT_L3(CY_CTDAC_OUTPUTMODE(outputMode)); + + uint32_t ctdacCtrl; + + /* Clear out the three affected bits */ + ctdacCtrl = base->CTDAC_CTRL & ~(CTDAC_CTDAC_CTRL_OUT_EN_Msk | CTDAC_CTDAC_CTRL_DISABLED_MODE_Msk | CTDAC_CTDAC_CTRL_CTDAC_RANGE_Msk); + + base->CTDAC_CTRL = ctdacCtrl | (uint32_t)outputMode; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_SetDeglitchMode +****************************************************************************//** +* +* Enable deglitching on the unbuffered path, buffered path, both, or +* disable deglitching. The deglitch mode should match the configured output path. +* +* \param base +* Pointer to structure describing registers +* +* \param deglitchMode +* Deglitching mode selection. See \ref cy_en_ctdac_deglitch_t for values. +* +* \return None +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_SET_DEGLITCH_MODE +* +*******************************************************************************/ +void Cy_CTDAC_SetDeglitchMode(CTDAC_Type *base, cy_en_ctdac_deglitch_t deglitchMode) +{ + CY_ASSERT_L3(CY_CTDAC_DEGLITCH(deglitchMode)); + + uint32_t ctdacCtrl; + + /* Clear out DEGLITCH_CO6 and DEGLITCH_C0S bits */ + ctdacCtrl = base->CTDAC_CTRL & ~(CTDAC_CTDAC_CTRL_DEGLITCH_COS_Msk | CTDAC_CTDAC_CTRL_DEGLITCH_CO6_Msk); + + base->CTDAC_CTRL = ctdacCtrl | (uint32_t)deglitchMode; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_SetDeglitchCycles +****************************************************************************//** +* +* Set the number of deglitch cycles (0 to 63) that will be used. +* To calculate the deglitch time: +* +* (DEGLITCH_CNT + 1) / PERI_CLOCK_FREQ +* +* The optimal deglitch time is 700 ns. +* +* \param base +* Pointer to structure describing registers +* +* \param deglitchCycles +* Number of cycles to deglitch +* +* \return None +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_SET_DEGLITCH_CYCLES +* +*******************************************************************************/ +void Cy_CTDAC_SetDeglitchCycles(CTDAC_Type *base, uint32_t deglitchCycles) +{ + CY_ASSERT_L2(CY_CTDAC_DEGLITCHCYCLES(deglitchCycles)); + + uint32_t ctdacCtrl; + + ctdacCtrl = (base->CTDAC_CTRL) & ~CTDAC_CTDAC_CTRL_DEGLITCH_CNT_Msk; + + base->CTDAC_CTRL = ctdacCtrl | ((deglitchCycles << CTDAC_CTDAC_CTRL_DEGLITCH_CNT_Pos) & CTDAC_CTDAC_CTRL_DEGLITCH_CNT_Msk); +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_SetRef +****************************************************************************//** +* +* Set the CTDAC reference source to Vdda or an external reference. +* The external reference must come from Opamp1 of the CTB. +* +* \param base +* Pointer to structure describing registers +* +* \param refSource +* The reference source. Select a value from \ref cy_en_ctdac_ref_source_t. +* +* \return None +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_SET_REF +* +*******************************************************************************/ +void Cy_CTDAC_SetRef(CTDAC_Type *base, cy_en_ctdac_ref_source_t refSource) +{ + CY_ASSERT_L3(CY_CTDAC_REFSOURCE(refSource)); + + switch(refSource) + { + case CY_CTDAC_REFSOURCE_VDDA: + + /* Close the CVD switch to use Vdda as the reference source */ + base->CTDAC_SW |= CTDAC_CTDAC_SW_CTDD_CVD_Msk; + break; + case CY_CTDAC_REFSOURCE_EXTERNAL: + default: + base->CTDAC_SW_CLEAR = CTDAC_CTDAC_SW_CLEAR_CTDD_CVD_Msk; + break; + } +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_SetAnalogSwitch +****************************************************************************//** +* +* Provide firmware control of the CTDAC switches. Each call to this function +* can open a set of switches or close a set of switches. +* +* \note +* The switches are configured by the reference +* source and output mode selections during initialization. +* +* \param base +* Pointer to structure describing registers +* +* \param switchMask +* The mask of the switches to either open or close. +* Select one or more values from \ref cy_en_ctdac_switches_t and "OR" them together. +* +* \param state +* Open or close the switche(s). Select a value from \ref cy_en_ctdac_switch_state_t. +* +* \return None +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_SET_ANALOG_SWITCH +* +*******************************************************************************/ +void Cy_CTDAC_SetAnalogSwitch(CTDAC_Type *base, uint32_t switchMask, cy_en_ctdac_switch_state_t state) +{ + CY_ASSERT_L2(CY_CTDAC_SWITCHMASK(switchMask)); + CY_ASSERT_L3(CY_CTDAC_SWITCHSTATE(state)); + + switch(state) + { + case CY_CTDAC_SWITCH_CLOSE: + base->CTDAC_SW |= switchMask; + break; + case CY_CTDAC_SWITCH_OPEN: + default: + + /* Unlike the close case, do not OR the register. Set 1 to clear.*/ + base->CTDAC_SW_CLEAR = switchMask; + break; + } +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_DeepSleepCallback +****************************************************************************//** +* +* Callback to prepare the CTDAC before entering and after exiting Deep Sleep +* mode. If deglitching is used, it is disabled before entering Deep Sleep +* to ensure the deglitch switches are closed. This is needed only +* if the CTDAC will be enabled in DeepSleep. Upon wakeup, deglitching will +* be re-enabled if it was previously used. +* +* \param callbackParams +* Pointer to structure of type \ref cy_stc_syspm_callback_params_t +* +* \return +* See \ref cy_en_syspm_status_t +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_DEEP_SLEEP_CALLBACK +* +*******************************************************************************/ +cy_en_syspm_status_t Cy_CTDAC_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams) +{ + /* Static variable preserved between function calls. + * Tracks the state of the deglitch mode before sleep so that it can be re-enabled after wakeup */ + static uint32_t deglitchModeBeforeSleep; + + cy_en_syspm_status_t returnValue = CY_SYSPM_SUCCESS; + + CTDAC_Type *ctdacBase = (CTDAC_Type *)callbackParams->base; + + if (CY_SYSPM_BEFORE_TRANSITION == callbackParams->mode) + { /* Actions that should be done before entering the Deep Sleep mode */ + + /* Store the state of the deglitch switches before turning deglitch off */ + deglitchModeBeforeSleep = ctdacBase->CTDAC_CTRL & (CTDAC_CTDAC_CTRL_DEGLITCH_CO6_Msk | CTDAC_CTDAC_CTRL_DEGLITCH_COS_Msk); + + /* Turn deglitch off before entering Deep Sleep */ + ctdacBase->CTDAC_CTRL &= ~(CTDAC_CTDAC_CTRL_DEGLITCH_CO6_Msk | CTDAC_CTDAC_CTRL_DEGLITCH_COS_Msk); + } + else if (CY_SYSPM_AFTER_TRANSITION == callbackParams->mode) + { /* Actions that should be done after exiting the Deep Sleep mode */ + + /* Re-enable the deglitch mode that was configured before Deep Sleep entry */ + ctdacBase->CTDAC_CTRL |= deglitchModeBeforeSleep; + } + else + { /* Does nothing in other modes */ + } + + return returnValue; +} + +#if defined(__cplusplus) +} +#endif + +/* [] END OF FILE */ + diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ctdac/cy_ctdac.h b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ctdac/cy_ctdac.h new file mode 100644 index 0000000000..ddfb6b9922 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ctdac/cy_ctdac.h @@ -0,0 +1,1045 @@ +/***************************************************************************//** +* \file cy_ctdac.h +* \version 1.0.1 +* +* Header file for the CTDAC driver +* +******************************************************************************** +* \copyright +* Copyright 2017-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +/** +* \defgroup group_ctdac Continuous Time Digital to Analog Converter (CTDAC) +* \{ +* The CTDAC driver provides APIs to configure the 12-bit Continuous-Time DAC. +* +* - 12-bit continuous time output +* - 2 us settling time for a 25 pF load when output buffered through Opamp0 of \ref group_ctb "CTB" +* - Can be enabled in Deep Sleep power mode +* - Selectable voltage reference: +* - VDDA +* - Internal analog reference buffered through Opamp1 of \ref group_ctb "CTB" +* - External reference buffered through Opamp1 of \ref group_ctb "CTB" +* - Selectable output paths: +* - Direct DAC output to a pin +* - Buffered DAC output through Opamp0 of \ref group_ctb "CTB" +* - Sample and hold output path through Opamp0 of \ref group_ctb "CTB" +* - Selectable input modes: +* - Unsigned 12-bit mode +* - Virtual signed 12-bit mode +* - Configurable update rate using clock or strobe signal +* - Double buffered DAC voltage control register +* - Interrupt and DMA trigger on DAC buffer empty +* - Configurable as PGA along with Opamp1 of the \ref group_ctb "CTB" +* +* The CTDAC generates a 12-bit DAC output voltage from the reference. +* The DAC reference can come from VDDA or from any signal buffered through Opamp0 +* of the CTB. This can be an external signal through a GPIO or from the internal +* AREF. The CTDAC is closely integrated with the CTB block, +* which provides easy buffering of the DAC output voltage, +* buffered input reference voltage, and sample and hold for the DAC output. +* The CTDAC control interface provides control of the DAC output through CPU or DMA. +* This includes a double-buffered DAC voltage control register, clock input for programmable +* update rate, interrupt on DAC buffer empty, and trigger to DMA. +* +* \image html ctdac_block_diagram.png +* \image latex ctdac_block_diagram.png +* +* The CTDAC has two switches, CO6 for configuring the output path and +* CVD for the reference source. +* +* \image html ctdac_switches.png +* \image latex ctdac_switches.png +* +* \section group_ctdac_init Initialization +* +* Configure the CTDAC hardware block by calling \ref Cy_CTDAC_Init. +* The base address of the CTDAC hardware can be found in the device-specific header file. +* If the buffers in the CTB are used for the reference source or the output, +* initialize the CTB hardware block. After both blocks are initialized, +* enable the CTB block before enabling the CTDAC block. +* +* The driver also provides a \ref Cy_CTDAC_FastInit function for fast and easy initialization of the CTDAC. +* The driver has pre-defined configuration structures for the four combinations of the reference and output buffers. +* +* - \ref Cy_CTDAC_Fast_VddaRef_UnbufferedOut +* - \ref Cy_CTDAC_Fast_VddaRef_BufferedOut +* - \ref Cy_CTDAC_Fast_OA1Ref_UnbufferedOut +* - \ref Cy_CTDAC_Fast_OA1Ref_BufferedOut +* +* After initialization, call \ref Cy_CTDAC_Enable to enable the hardware. +* +* \section group_ctdac_updatemode Update Modes +* The CTDAC contains two registers: +* -# CTDAC_VAL +* +* For direct firmware writes to update the current DAC value immediately. +* This register is written with \ref Cy_CTDAC_SetValue. +* -# CTDAC_VAL_NXT +* +* For buffered writes to update the DAC value at a +* periodic rate or with a strobe trigger input. +* This register is written with \ref Cy_CTDAC_SetValueBuffered. +* +* The update mode is +* selected during initialization with the \ref cy_stc_ctdac_config_t.updateMode. +* Four of these modes require a dedicated clock resource and the driver +* can configure the clock during initialization (see \ref cy_stc_ctdac_config_t). +* +* Three of these modes use a strobe signal through the digital signal interface (DSI). +* This allows control of the buffered update timing from an external source, for example, by another +* chip peripheral or from an off-chip source. +* +* \subsection group_ctdac_updatemode_direct_write Direct write +* +* In this mode, the user writes directly into the CTDAC_VAL register +* using \ref Cy_CTDAC_SetValue. The action of writing to this register +* will update the DAC output. This mode does not generate an interrupt +* or trigger signal. +* In this mode, a clock must not be configured. Additionally, calling \ref +* Cy_CTDAC_SetValueBuffered does not update the DAC output. +* +* \image html ctdac_update_mode_direct_write.png +* \image latex ctdac_update_mode_direct_write.png +* +* \subsection group_ctdac_updatemode_buffered_write Buffered write +* +* In this mode, the user writes to the CTDAC_VAL_NXT register using +* \ref Cy_CTDAC_SetValueBuffered. The rising edge of the clock +* will update the DAC output and generate the interrupt and trigger signals. +* +* Whenever data is transferred from the CTDAC_VAL_NXT register, +* an interrupt is asserted the same time as the trigger. But while +* the trigger is automatically cleared after two PeriClk cycles, the +* user must clear the interrupt with \ref Cy_CTDAC_ClearInterrupt. +* +* \image html ctdac_update_mode_buffered_write.png +* \image latex ctdac_update_mode_buffered_write.png +* +* \subsection group_ctdac_updatemode_strobe_edge_sync Strobe edge sync +* +* In this mode, the user writes to the CTDAC_VAL_NXT register using +* \ref Cy_CTDAC_SetValueBuffered. +* Each rising edge of the DSI strobe input enables +* one subsequent update from the next rising edge of the clock. The DSI +* input must remain high for two PeriClk cycles and go low for +* another two PeriClk cycles to allow for the next update. +* This restricts the DSI strobe input frequency to the PeriClk frequency divided by four. +* +* \image html ctdac_update_mode_strobe_edge_sync.png +* \image latex ctdac_update_mode_strobe_edge_sync.png +* +* \subsection group_ctdac_updatemode_strobe_edge_immediate Strobe edge immediate +* +* In this mode, the user writes to the CTDAC_VAL_NXT register using +* \ref Cy_CTDAC_SetValueBuffered. +* The clock resource is used but set to a logic high. +* Therefore, each rising edge of the DSI strobe input immediately +* updates the DAC output. +* +* \image html ctdac_update_mode_strobe_edge_immediate.png +* \image latex ctdac_update_mode_strobe_edge_immediate.png +* +* \subsection group_ctdac_updatemode_strobe_level Strobe level +* +* In this mode, the user writes to the CTDAC_VAL_NXT register using +* \ref Cy_CTDAC_SetValueBuffered. +* The DSI strobe input acts as a hardware enable signal. +* While the DSI strobe input is high, the mode behaves +* like the Buffered write mode. When the DSI strobe input is low, +* updates are disabled. +* +* \image html ctdac_update_mode_strobe_level.png +* \image latex ctdac_update_mode_strobe_level.png +* +* \section group_ctdac_dacmode DAC Modes +* +* The format of code stored in the CTDAC_VAL register can either be unsigned +* or signed two's complemented. +* Only the first 12 bits of the register are used by the DAC so there is +* no need for sign extension. With the signed format, the DAC decodes +* the code in the register by adding 0x800. +* The DAC can output the register value or the register value plus 1 (see \ref Cy_CTDAC_SetOutputMode). +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
12-bit unsigned code12-bit two's complement signed codeVout (for \ref CY_CTDAC_OUTPUT_VALUE )Vout (for \ref CY_CTDAC_OUTPUT_VALUE_PLUS1 )
0x0000x8000Vref/4096
0x8000x0000.5 * VrefVref * 2049 / 4096
0xFFF0x7FFVref * 4095 / 4096Vref
+* +* The expressions in the above table are based on an unbuffered DAC output. +* When the output is buffered, the input and output range of the buffer will affect the +* output voltage. See \ref group_ctb_opamp_range in the CTB driver for more information. +* +* \section group_ctdac_trigger Interrupts and Trigger +* +* When data from the CTDAC_VAL_NXT is transferred to the CTDAC_VAL register, +* an interrupt and trigger output are generated. The trigger output can be +* used with a DMA block to update the CTDAC value register at high speeds without any CPU intervention. +* Alternatively, the interrupt output can be used when DMA is not available +* to update the CTDAC value register, but at a slower speed. +* +* Recall with the \ref group_ctdac_updatemode, the interrupt and trigger output are available in all modes except +* \ref group_ctdac_updatemode_direct_write. +* +* \subsection group_ctdac_dma_trigger DMA Trigger +* +* The CTDAC trigger output signal can be routed to a DMA block using the \ref group_trigmux +* to trigger an update to the CTDAC_VAL_NXT register. +* When making the required \ref Cy_TrigMux_Connect calls, use the pre-defined enums, TRIG14_IN_PASS_TR_CTDAC_EMPTY +* and TRIGGER_TYPE_PASS_TR_CTDAC_EMPTY. +* +* \subsection group_ctdac_handling_interrupts Handling Interrupts +* +* The following code snippet demonstrates how to implement a routine to handle the interrupt. +* The routine gets called when any CTDAC on the device generates an interrupt. +* +* \snippet ctdac_sut_01.cydsn/main_cm0p.c SNIPPET_CTDAC_ISR +* +* The following code snippet demonstrates how to configure and enable the interrupt. +* +* \snippet ctdac_sut_01.cydsn/main_cm0p.c SNIPPET_CTDAC_INTR_SETUP +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_DMA_TRIGGER +* +* \section group_ctdac_deglitch Deglitch +* +* The hardware has the ability to deglitch the output value every time it is updated. +* This prevents small glitches in the DAC output during an update to propagate to +* the pin or opamp input. When deglitch is enabled, a switch on the output path +* is forced open for a configurable number of PeriClk cycles. This deglitch time +* is calculated as: +* +* (DEGLITCH_CNT + 1) / PERI_CLOCK_FREQ +* +* The optimal and recommended deglitch time is 700 ns. Call \ref Cy_CTDAC_SetDeglitchCycles to set DEGLITCH_CNT. +* +* There are two switches used for deglitching. +* - Switch COS in the CTB between the DAC output and the Opamp0 input +* - Switch CO6 in the CTDAC between the DAC output and external pin +* +* Call \ref Cy_CTDAC_SetDeglitchMode to set the deglitch path. Match this with the output buffer selection. +* If the output is buffered through the CTB, select \ref CY_CTDAC_DEGLITCHMODE_BUFFERED. +* If the output is unbuffered to a direct pin, select \ref CY_CTDAC_DEGLITCHMODE_UNBUFFERED. +* +* \note +* If deglitching is enabled, the hardware does not force the deglitch switches into a closed +* state during Deep Sleep mode. Therefore, there is a chance that the device enters +* Deep Sleep mode while the hardware is deglitching and the switches on the output path remain open. +* To ensure the DAC will operate properly in Deep Sleep when enabled, make sure to +* register the \ref Cy_CTDAC_DeepSleepCallback before entering Deep Sleep mode. +* +* \section group_ctdac_sample_hold Sample and Hold +* +* When buffering the DAC output, the CTB has a Sample and Hold (SH) feature that can be used for saving power. +* The DAC output voltage is retained on an internal capacitor for a duration of time while the +* DAC output can be turned off. The DAC hardware needs to be turned on in a periodic fashion +* to recharge the hold capacitor. This feature is firmware controlled using a sequence of function calls. +* See \ref Cy_CTB_DACSampleAndHold in the \ref group_ctb_sample_hold "CTB" driver. +* +* The hold time depends on the supply and reference voltages. The following hold times are based on the +* time it takes for the buffered output to change by 1 LSB. +* +* - Hold time = 750 us @ Vref = VDDA , VDDA = 1.7 V +* - Hold time = 525 us @ Vref = VDDA , VDDA = 3.6 V +* - Hold time = 200 us @ Vref = 1.2 V, VDDA = 3.6 V +* +* \section group_ctdac_low_power Low Power Support +* +* The CTDAC driver provides a callback function to handle power mode transitions. +* If the CTDAC is configured for Deep Sleep operation and \ref group_ctdac_deglitch "deglitching" is enabled, +* the callback \ref Cy_CTDAC_DeepSleepCallback must be registered before calling +* \ref Cy_SysPm_DeepSleep. +* Refer to \ref group_syspm driver for more information about power mode transitions and +* callback registration. +* +* \section group_ctdac_more_information More Information +* +* Refer to the technical reference manual (TRM) and the device datasheet. +* +* \section group_ctdac_MISRA MISRA-C Compliance] +* +* This driver has the following specific deviations: +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
MISRA RuleRule Class (Required/Advisory)Rule DescriptionDescription of Deviation(s)
11.4AdvisoryA cast should not be performed between a pointer to object type and a different pointer to object type.The cy_syspm driver defines the pointer to void in the \ref cy_stc_syspm_callback_params_t.base field. +* This CTDAC driver implements a Deep Sleep callback conforming to the cy_syspm driver requirements. +* When the callback is called, the base is cast to a pointer to CTDAC_Type. +*
+* +* \section group_ctdac_changelog Changelog +* +* +* +* +* +* +* +* +* +* +* +* +*
VersionChangesReason for Change
1.0.1Added low power support section. Minor documentation edits.Documentation update and clarification
1.0Initial version
+* +* \defgroup group_ctdac_macros Macros +* \defgroup group_ctdac_functions Functions +* \{ +* \defgroup group_ctdac_functions_init Initialization Functions +* \defgroup group_ctdac_functions_basic Basic Configuration Functions +* \defgroup group_ctdac_functions_switches Switch Control Functions +* \defgroup group_ctdac_functions_interrupts Interrupt Functions +* \defgroup group_ctdac_functions_syspm_callback Low Power Callback +* \} +* \defgroup group_ctdac_globals Global Variables +* \defgroup group_ctdac_data_structures Data Structures +* \defgroup group_ctdac_enums Enumerated Types +*/ + +#if !defined(CY_CTDAC_H) +#define CY_CTDAC_H + +#include +#include +#include +#include "cy_device_headers.h" +#include "syspm/cy_syspm.h" +#include "syslib/cy_syslib.h" +#include "sysclk/cy_sysclk.h" + +#ifndef CY_IP_MXS40PASS_CTDAC + #error "The CTDAC driver is not supported on this device" +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \addtogroup group_ctdac_macros +* \{ +*/ + +/** Driver major version */ +#define CY_CTDAC_DRV_VERSION_MAJOR 1 + +/** Driver minor version */ +#define CY_CTDAC_DRV_VERSION_MINOR 0 + +/** CTDAC driver identifier */ +#define CY_CTDAC_ID CY_PDL_DRV_ID(0x19u) + +#define CY_CTDAC_DEINIT (0uL) /**< De-init value for CTDAC registers */ +#define CY_CTDAC_UNSIGNED_MID_CODE_VALUE (0x800uL) /**< Middle code value for unsigned values */ +#define CY_CTDAC_UNSIGNED_MAX_CODE_VALUE (0xFFFuL) /**< Maximum code value for unsigned values */ +#define CY_CTDAC_FAST_CLKCFG_TYPE CY_SYSCLK_DIV_8_BIT /**< Clock divider type for quick clock setup */ +#define CY_CTDAC_FAST_CLKCFG_NUM (0uL) /**< Clock divider number for quick clock setup */ +#define CY_CTDAC_FAST_CLKCFG_DIV (99uL) /**< Clock divider integer value for quick clock setup. Divides PERI clock by 100. */ + +/** \cond INTERNAL */ +#define CY_CTDAC_DEINT_CTDAC_SW (CTDAC_CTDAC_SW_CLEAR_CTDD_CVD_Msk | CTDAC_CTDAC_SW_CLEAR_CTDO_CO6_Msk) /**< Mask for de-initializing the CTDAC switch control register */ +#define CY_CTDAC_STROBE_EDGE_IMMEDIATE_DIV (0uL) /**< Clock divider value for the Strobe Edge Immediate update mode */ +#define CY_CTDAC_STROBE_EDGE_IMMEDIATE_DIV_FRAC (0uL) /**< Clock fractional divider value for the Strobe Edge Immediate update mode */ +#define CY_CTDAC_DEGLITCH_CYCLES_MAX (63uL) + +/**< Macros for conditions used by CY_ASSERT calls */ +#define CY_CTDAC_REFSOURCE(source) (((source) == CY_CTDAC_REFSOURCE_EXTERNAL) || ((source) == CY_CTDAC_REFSOURCE_VDDA)) +#define CY_CTDAC_FORMAT(mode) (((mode) == CY_CTDAC_FORMAT_UNSIGNED) || ((mode) == CY_CTDAC_FORMAT_SIGNED)) +#define CY_CTDAC_UPDATE(mode) ((mode) <= CY_CTDAC_UPDATE_STROBE_LEVEL) +#define CY_CTDAC_DEGLITCH(mode) (((mode) == CY_CTDAC_DEGLITCHMODE_NONE) \ + || ((mode) == CY_CTDAC_DEGLITCHMODE_UNBUFFERED) \ + || ((mode) == CY_CTDAC_DEGLITCHMODE_BUFFERED) \ + || ((mode) == CY_CTDAC_DEGLITCHMODE_BOTH)) +#define CY_CTDAC_OUTPUTMODE(mode) (((mode) == CY_CTDAC_OUTPUT_HIGHZ) \ + || ((mode) == CY_CTDAC_OUTPUT_VALUE) \ + || ((mode) == CY_CTDAC_OUTPUT_VALUE_PLUS1) \ + || ((mode) == CY_CTDAC_OUTPUT_VSSA) \ + || ((mode) == CY_CTDAC_OUTPUT_VREF)) +#define CY_CTDAC_OUTPUTBUFFER(buffer) (((buffer) == CY_CTDAC_OUTPUT_UNBUFFERED) || ((buffer) == CY_CTDAC_OUTPUT_BUFFERED)) +#define CY_CTDAC_DEEPSLEEP(deepSleep) (((deepSleep) == CY_CTDAC_DEEPSLEEP_DISABLE) || ((deepSleep) == CY_CTDAC_DEEPSLEEP_ENABLE)) +#define CY_CTDAC_DEGLITCHCYCLES(cycles) ((cycles) <= CY_CTDAC_DEGLITCH_CYCLES_MAX) +#define CY_CTDAC_SWITCHMASK(mask) ((mask) <= (uint32_t) (CY_CTDAC_SWITCH_CVD_MASK | CY_CTDAC_SWITCH_CO6_MASK)) +#define CY_CTDAC_SWITCHSTATE(state) (((state) == CY_CTDAC_SWITCH_OPEN) || ((state) == CY_CTDAC_SWITCH_CLOSE)) +#define CY_CTDAC_INTRMASK(mask) (((mask) == 0uL) || ((mask) == 1uL)) +/** \endcond */ + +/** \} group_ctdac_macros */ + +/*************************************** +* Enumerated Types +***************************************/ + +/** +* \addtogroup group_ctdac_enums +* \{ +*/ + +/** +* Configure the mode for how the DAC value is updated. +* All the modes require a CTDAC clock except for \ref group_ctdac_updatemode_direct_write. +*/ +typedef enum { + CY_CTDAC_UPDATE_DIRECT_WRITE = 0uL, /**< DAC value is updated with a direct write by calling to \ref Cy_CTDAC_SetValue */ + CY_CTDAC_UPDATE_BUFFERED_WRITE = 1uL, /**< DAC value stored with \ref Cy_CTDAC_SetValueBuffered is updated on the next CTDAC clock edge */ + CY_CTDAC_UPDATE_STROBE_EDGE_SYNC = 2uL, /**< DAC value stored with \ref Cy_CTDAC_SetValueBuffered is updated on the next CTDAC clock edge after a rising edge of the strobe */ + CY_CTDAC_UPDATE_STROBE_EDGE_IMMEDIATE = 3uL, /**< DAC value stored with \ref Cy_CTDAC_SetValueBuffered is updated on the rising edge of the strobe input */ + CY_CTDAC_UPDATE_STROBE_LEVEL = 4uL /**< DAC value stored with \ref Cy_CTDAC_SetValueBuffered is updated on every CTDAC clock edge while the strobe line is high */ +}cy_en_ctdac_update_t; + +/** +* Configure the format in which the DAC value register is decoded. +*/ +typedef enum { + CY_CTDAC_FORMAT_UNSIGNED = 0uL, /**< Unsigned 12-bit DAC. No value decoding */ + CY_CTDAC_FORMAT_SIGNED = 1uL << CTDAC_CTDAC_CTRL_CTDAC_MODE_Pos /**< Virtual signed. Add 0x800 to the 12-bit DAC value */ +}cy_en_ctdac_format_t; + +/** +* Enable or disable the CTDAC hardware during Deep Sleep. +*/ +typedef enum { + CY_CTDAC_DEEPSLEEP_DISABLE = 0uL, /**< DAC is disabled during Deep Sleep power mode */ + CY_CTDAC_DEEPSLEEP_ENABLE = CTDAC_CTDAC_CTRL_DEEPSLEEP_ON_Msk /**< DAC remains enabled during Deep Sleep power mode */ +}cy_en_ctdac_deep_sleep_t; + +/** +* Configure the output state of the CTDAC. +*/ +typedef enum { + CY_CTDAC_OUTPUT_HIGHZ = 0uL, /**< DAC output is tri-state */ + CY_CTDAC_OUTPUT_VALUE = CTDAC_CTDAC_CTRL_OUT_EN_Msk, /**< DAC Output is enabled and drives the programmed value */ + CY_CTDAC_OUTPUT_VALUE_PLUS1 = CTDAC_CTDAC_CTRL_OUT_EN_Msk \ + | CTDAC_CTDAC_CTRL_CTDAC_RANGE_Msk, /**< DAC Output enabled and drives the programmed value plus 1 */ + CY_CTDAC_OUTPUT_VSSA = CTDAC_CTDAC_CTRL_DISABLED_MODE_Msk, /**< Output is pulled to Vssa through a 1.1 MOhm (typ) resistor */ + CY_CTDAC_OUTPUT_VREF = CTDAC_CTDAC_CTRL_DISABLED_MODE_Msk \ + | CTDAC_CTDAC_CTRL_CTDAC_RANGE_Msk /**< Output is pulled to Vref through a 1.1 MOhm (typ) resistor */ +}cy_en_ctdac_output_mode_t; + +/** +* Configure the deglitch mode. See the \ref group_ctdac_deglitch section for +* more information on how deglitching works. +*/ +typedef enum { + CY_CTDAC_DEGLITCHMODE_NONE = 0uL, /**< Disable deglitch */ + CY_CTDAC_DEGLITCHMODE_UNBUFFERED = CTDAC_CTDAC_CTRL_DEGLITCH_CO6_Msk, /**< Deglitch through the CO6 switch */ + CY_CTDAC_DEGLITCHMODE_BUFFERED = CTDAC_CTDAC_CTRL_DEGLITCH_COS_Msk, /**< Deglitch through the CTB COS switch */ + CY_CTDAC_DEGLITCHMODE_BOTH = CTDAC_CTDAC_CTRL_DEGLITCH_COS_Msk \ + | CTDAC_CTDAC_CTRL_DEGLITCH_CO6_Msk /**< Deglitch through both CO6 and CTB COS switches */ +}cy_en_ctdac_deglitch_t; + +/** +* Configure the reference source for the CTDAC +* +* The CVD switch is closed when Vdda is the reference source. +*/ +typedef enum { + CY_CTDAC_REFSOURCE_EXTERNAL = 0uL, /**< Use an external source from Opamp1 of the CTB as the reference. CVD switch is open. */ + CY_CTDAC_REFSOURCE_VDDA = 1uL /**< Use Vdda as the reference. CVD switch is closed. */ +}cy_en_ctdac_ref_source_t; + +/** Configure the output to be buffered or unbuffered +* +* The CO6 switch is closed when the output is unbuffered to Pin 6 of the CTDAC port. +* See the device datasheet for the CTDAC port. +*/ +typedef enum { + CY_CTDAC_OUTPUT_BUFFERED = 0uL, /**< Buffer the output through the CTB OA0 */ + CY_CTDAC_OUTPUT_UNBUFFERED = 1uL /**< Send output to a direct pin */ +}cy_en_ctdac_output_buffer_t; + +/** Switch state, either open or closed, to be used in \ref Cy_CTDAC_SetAnalogSwitch. */ +typedef enum +{ + CY_CTDAC_SWITCH_OPEN = 0uL, /**< Open the switch */ + CY_CTDAC_SWITCH_CLOSE = 1uL /**< Close the switch */ +}cy_en_ctdac_switch_state_t; + +/** Switch mask to be used in \ref Cy_CTDAC_SetAnalogSwitch */ +typedef enum +{ + CY_CTDAC_SWITCH_CVD_MASK = CTDAC_CTDAC_SW_CTDD_CVD_Msk, /**< Switch for the reference source, Vdda or external */ + CY_CTDAC_SWITCH_CO6_MASK = CTDAC_CTDAC_SW_CTDO_CO6_Msk /**< Switch for the output, buffered or direct */ +}cy_en_ctdac_switches_t; + +/** Return states for \ref Cy_CTDAC_Init, \ref Cy_CTDAC_DeInit, and \ref Cy_CTDAC_FastInit */ +typedef enum { + CY_CTDAC_SUCCESS = 0x00uL, /**< Initialization completed successfully */ + CY_CTDAC_BAD_PARAM = CY_CTDAC_ID | CY_PDL_STATUS_ERROR | 0x01uL /**< Input pointers were NULL and Initialization could not be completed */ +}cy_en_ctdac_status_t; + +/** \} group_ctdac_enums */ + +/*************************************** +* Configuration Structures +***************************************/ + +/** +* \addtogroup group_ctdac_data_structures +* \{ +*/ + +/** Configuration structure to set up the entire CTDAC block to be used with \ref Cy_CTDAC_Init +*/ +typedef struct +{ + cy_en_ctdac_ref_source_t refSource; /**< Reference source: Vdda or externally through Opamp1 of CTB */ + cy_en_ctdac_format_t formatMode; /**< Format of DAC value: signed or unsigned */ + cy_en_ctdac_update_t updateMode; /**< Update mode: direct or buffered writes or hardware, edge or level */ + cy_en_ctdac_deglitch_t deglitchMode; /**< Deglitch mode: disabled, buffered, unbuffered, or both */ + cy_en_ctdac_output_mode_t outputMode; /**< Output mode: enabled (value or value + 1), high-z, Vssa, or Vdda */ + cy_en_ctdac_output_buffer_t outputBuffer; /**< Output path: Buffered through Opamp0 of CTB or connected directly to Pin 6 */ + cy_en_ctdac_deep_sleep_t deepSleep; /**< Enable or disable the CTDAC during Deep Sleep */ + uint32_t deglitchCycles; /**< Number of deglitch cycles from 0 to 63 */ + int32_t value; /**< Current DAC value */ + int32_t nextValue; /**< Next DAC value for double buffering */ + bool enableInterrupt; /**< If true, enable interrupt when next value register is transferred to value register */ + + /* Configuring the clock */ + bool configClock; /**< Configure or ignore clock information */ + cy_en_divider_types_t dividerType; /**< Specifies which type of divider to use. Can be integer or fractional divider. Not used if updateMode is \ref CY_CTDAC_UPDATE_DIRECT_WRITE */ + uint32_t dividerNum; /**< Specifies which divider of the selected type to configure. Not used if updateMode is \ref CY_CTDAC_UPDATE_DIRECT_WRITE */ + uint32_t dividerIntValue; /**< The integer divider value. The divider value causes integer division of (divider value + 1). Not used if updateMode is \ref CY_CTDAC_UPDATE_DIRECT_WRITE or \ref CY_CTDAC_UPDATE_STROBE_EDGE_IMMEDIATE */ + uint32_t dividerFracValue; /**< The fractional divider value if using a fractional clock. Not used if updateMode is \ref CY_CTDAC_UPDATE_DIRECT_WRITE or \ref CY_CTDAC_UPDATE_STROBE_EDGE_IMMEDIATE */ +}cy_stc_ctdac_config_t; + +/** Configuration structure to quickly set up the CTDAC to be used with \ref Cy_CTDAC_FastInit +* This structure provides a selection for the CTDAC reference source and output path. +* +* The other configuration options are set to: +* - .formatMode = \ref CY_CTDAC_FORMAT_UNSIGNED +* - .updateMode = \ref CY_CTDAC_UPDATE_BUFFERED_WRITE +* - .deglitchMode = \ref CY_CTDAC_DEGLITCHMODE_NONE +* - .outputMode = \ref CY_CTDAC_OUTPUT_VALUE +* - .deepSleep = \ref CY_CTDAC_DEEPSLEEP_DISABLE +* - .deglitchCycles = \ref CY_CTDAC_DEINIT +* - .value = \ref CY_CTDAC_UNSIGNED_MID_CODE_VALUE +* - .nextValue = \ref CY_CTDAC_UNSIGNED_MID_CODE_VALUE +* - .enableInterrupt = true +* - .configClock = true +* - .dividerType = \ref CY_CTDAC_FAST_CLKCFG_TYPE +* - .dividerNum = \ref CY_CTDAC_FAST_CLKCFG_NUM +* - .dividerInitValue = \ref CY_CTDAC_FAST_CLKCFG_DIV +* - .dividerFracValue = \ref CY_CTDAC_DEINIT +*/ +typedef struct +{ + cy_en_ctdac_ref_source_t refSource; /**< Reference source: Vdda or externally through Opamp1 of CTB */ + cy_en_ctdac_output_buffer_t outputBuffer; /**< Output path: Buffered through Opamp0 of CTB or connected directly to Pin 6 */ +}cy_stc_ctdac_fast_config_t; + +/** \} group_ctdac_data_structures */ + +/** \addtogroup group_ctdac_globals +* \{ +*/ +/*************************************** +* Global Variables +***************************************/ + +/** Configure CTDAC to use Vdda reference and output unbuffered. See \ref Cy_CTDAC_FastInit. */ +extern const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_VddaRef_UnbufferedOut; + +/** Configure CTDAC to use Vdda reference and output buffered through Opamp0 of CTB. See \ref Cy_CTDAC_FastInit. +* +* To quickly configure Opamp0, call with \ref Cy_CTB_FastInit +* with \ref Cy_CTB_Fast_Opamp0_Vdac_Out or \ref Cy_CTB_Fast_Opamp0_Vdac_Out_SH. +*/ +extern const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_VddaRef_BufferedOut; + +/** Configure CTDAC to use a buffered reference from Opamp1 of CTB +* and output unbuffered. See \ref Cy_CTDAC_FastInit. +* +* To use the reference from the Analog Reference (AREF), +* call \ref Cy_CTB_FastInit with \ref Cy_CTB_Fast_Opamp1_Vdac_Ref_Aref. +* +* To use an external reference from a GPIO, +* call \ref Cy_CTB_FastInit with \ref Cy_CTB_Fast_Opamp1_Vdac_Ref_Pin5 +* for Pin 5 on the CTB port. +*/ +extern const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_OA1Ref_UnbufferedOut; + +/** Configure CTDAC to use a buffered reference from Opamp1 of CTB +* and output buffered through Opamp0 of CTB. See \ref Cy_CTDAC_FastInit. +* +* To quickly configure Opamp0, call with \ref Cy_CTB_FastInit +* with \ref Cy_CTB_Fast_Opamp0_Vdac_Out or \ref Cy_CTB_Fast_Opamp0_Vdac_Out_SH. +* +* To use the reference from the Analog Reference (AREF), +* call \ref Cy_CTB_FastInit with \ref Cy_CTB_Fast_Opamp1_Vdac_Ref_Aref. +* +* To use an external reference from a GPIO, +* call \ref Cy_CTB_FastInit with \ref Cy_CTB_Fast_Opamp1_Vdac_Ref_Pin5 +* for Pins 5 on the CTB port. +*/ +extern const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_OA1Ref_BufferedOut; + +/** \} group_ctdac_globals */ + +/*************************************** +* Function Prototypes +***************************************/ + +/** +* \addtogroup group_ctdac_functions +* \{ +*/ + +/** +* \addtogroup group_ctdac_functions_init +* This set of functions are for initializing, enabling, and disabling the CTDAC. +* \{ +*/ +cy_en_ctdac_status_t Cy_CTDAC_Init(CTDAC_Type *base, const cy_stc_ctdac_config_t *config); +cy_en_ctdac_status_t Cy_CTDAC_DeInit(CTDAC_Type *base, bool deInitRouting); +cy_en_ctdac_status_t Cy_CTDAC_FastInit(CTDAC_Type *base, const cy_stc_ctdac_fast_config_t *config); +__STATIC_INLINE void Cy_CTDAC_Enable(CTDAC_Type *base); +__STATIC_INLINE void Cy_CTDAC_Disable(CTDAC_Type *base); +/** \} */ + +/** +* \addtogroup group_ctdac_functions_basic +* This set of functions are for configuring basic usage of the CTDAC. +* \{ +*/ +__STATIC_INLINE void Cy_CTDAC_SetValue(CTDAC_Type *base, int32_t value); +__STATIC_INLINE void Cy_CTDAC_SetValueBuffered(CTDAC_Type *base, int32_t value); +void Cy_CTDAC_SetSignMode(CTDAC_Type *base, cy_en_ctdac_format_t formatMode); +void Cy_CTDAC_SetDeepSleepMode(CTDAC_Type *base, cy_en_ctdac_deep_sleep_t deepSleep); +void Cy_CTDAC_SetOutputMode(CTDAC_Type *base, cy_en_ctdac_output_mode_t outputMode); +void Cy_CTDAC_SetDeglitchMode(CTDAC_Type *base, cy_en_ctdac_deglitch_t deglitchMode); +void Cy_CTDAC_SetDeglitchCycles(CTDAC_Type *base, uint32_t deglitchCycles); +void Cy_CTDAC_SetRef(CTDAC_Type *base, cy_en_ctdac_ref_source_t refSource); +/** \} */ + +/** \addtogroup group_ctdac_functions_switches +* +* This set of functions is for controlling the two CTDAC analog switches, CVD, and CO6. +* These are advanced functions. The switches will be managed by the reference +* source and output mode selections when initializing the hardware. +* \{ +*/ +void Cy_CTDAC_SetAnalogSwitch(CTDAC_Type *base, uint32_t switchMask, cy_en_ctdac_switch_state_t state); +__STATIC_INLINE uint32_t Cy_CTDAC_GetAnalogSwitch(const CTDAC_Type *base); +__STATIC_INLINE void Cy_CTDAC_SetSwitchCO6(CTDAC_Type *base, cy_en_ctdac_switch_state_t state); +__STATIC_INLINE void Cy_CTDAC_OpenAllSwitches(CTDAC_Type *base); +/** \} */ + +/** \addtogroup group_ctdac_functions_interrupts +* This set of functions is related to the CTDAC interrupt +* \{ +*/ +__STATIC_INLINE uint32_t Cy_CTDAC_GetInterruptStatus(const CTDAC_Type *base); +__STATIC_INLINE void Cy_CTDAC_ClearInterrupt(CTDAC_Type *base); +__STATIC_INLINE void Cy_CTDAC_SetInterrupt(CTDAC_Type *base); +__STATIC_INLINE void Cy_CTDAC_SetInterruptMask(CTDAC_Type *base, uint32_t mask); +__STATIC_INLINE uint32_t Cy_CTDAC_GetInterruptMask(const CTDAC_Type *base); +__STATIC_INLINE uint32_t Cy_CTDAC_GetInterruptStatusMasked(const CTDAC_Type *base); +/** \} */ + +/** \addtogroup group_ctdac_functions_syspm_callback +* This driver supports one SysPm callback for Deep Sleep transition. +* \{ +*/ +cy_en_syspm_status_t Cy_CTDAC_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams); +/** \} */ + +/** +* \addtogroup group_ctdac_functions_init +* \{ +*/ +/******************************************************************************* +* Function Name: Cy_CTDAC_Enable +****************************************************************************//** +* +* Power up the CTDAC hardware block. +* +* \param base +* Pointer to structure describing registers +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTDAC_Enable(CTDAC_Type *base) +{ + base->CTDAC_CTRL |= CTDAC_CTDAC_CTRL_ENABLED_Msk; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_Disable +****************************************************************************//** +* +* Turn off the hardware block. +* +* \param base +* Pointer to structure describing registers +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTDAC_Disable(CTDAC_Type *base) +{ + base->CTDAC_CTRL &= ~CTDAC_CTDAC_CTRL_ENABLED_Msk; +} +/** \} */ + +/** +* \addtogroup group_ctdac_functions_basic +* \{ +*/ +/******************************************************************************* +* Function Name: Cy_CTDAC_SetValue +****************************************************************************//** +* +* Set the CTDAC_VAL register (DAC hardware is +* updated on the next PeriClk cycle). Only the least significant 12 bits +* have an effect. Sign extension of negative values is unnecessary and is +* ignored by the hardware. The way in which the CTDAC interprets the 12-bit +* data is controlled by \ref Cy_CTDAC_SetSignMode. +* +* \note +* Call this function only when the update mode is set to \ref group_ctdac_updatemode_direct_write. +* Calling this function for any other update mode will not have the intended effect. +* +* \param base +* Pointer to structure describing registers +* +* \param value +* Value to write into the CTDAC_VAL register +* +* \return None +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_SET_VALUE +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTDAC_SetValue(CTDAC_Type *base, int32_t value) +{ + base->CTDAC_VAL = (((uint32_t)value) << CTDAC_CTDAC_VAL_VALUE_Pos) & CTDAC_CTDAC_VAL_VALUE_Msk; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_SetValueBuffered +****************************************************************************//** +* +* Set the CTDAC_VAL_NEXT register. The value is transferred +* to the CTDAC_VAL register on the next edge of the CTDAC clock. +* Only the least significant 12 bits +* have an effect. Sign extension of negative values is unnecessary and is +* ignored by the hardware. The way in which the CTDAC interprets the 12-bit +* data is controlled by \ref Cy_CTDAC_SetSignMode. +* +* \note +* Calling this function in \ref group_ctdac_updatemode_direct_write mode will not update the DAC output. +* Call this function for all modes that use buffered values (i.e. uses a clock). +* +* \param base +* Pointer to structure describing registers +* +* \param value +* Value to write into the CTDAC_VAL_NEXT register +* +* \return None +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_SET_VALUE_BUFFERED +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTDAC_SetValueBuffered(CTDAC_Type *base, int32_t value) +{ + base->CTDAC_VAL_NXT = (((uint32_t)value) << CTDAC_CTDAC_VAL_NXT_VALUE_Pos) & CTDAC_CTDAC_VAL_NXT_VALUE_Msk; +} +/** \} */ + +/** +* \addtogroup group_ctdac_functions_switches +* \{ +*/ +/******************************************************************************* +* Function Name: Cy_CTDAC_GetAnalogSwitch +****************************************************************************//** +* +* Return the state (open or close) of the CTDAC switches. +* +* \note +* The switches will be managed by the reference +* source and output mode selections when initializing the hardware. +* +* \param base +* Pointer to structure describing registers +* +* \return +* Switch state. Compare this value to the masks found in \ref cy_en_ctdac_switches_t. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_CTDAC_GetAnalogSwitch(const CTDAC_Type *base) +{ + return base->CTDAC_SW; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_SetSwitchCO6 +****************************************************************************//** +* +* Open or close switch CO6 that controls whether the output gets routed +* directly to a pin or through Opamp0 of the CTB. This function calls +* \ref Cy_CTDAC_SetAnalogSwitch with the switchMask set to \ref CY_CTDAC_SWITCH_CO6_MASK. +* +* \note +* The switches is configured by the output mode selections during initialization. +* +* \note +* This switch will temporarily +* be opened for deglitching if the degitch mode is \ref CY_CTDAC_DEGLITCHMODE_UNBUFFERED or +* \ref CY_CTDAC_DEGLITCHMODE_BOTH. +* +* \param base +* Pointer to structure describing registers +* +* \param state +* State of the switch, open or close. +* +* \return None +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_SET_SWITCH_CO6 +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTDAC_SetSwitchCO6(CTDAC_Type *base, cy_en_ctdac_switch_state_t state) +{ + Cy_CTDAC_SetAnalogSwitch(base, (uint32_t) CY_CTDAC_SWITCH_CO6_MASK, state); +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_OpenAllSwitches +****************************************************************************//** +* +* Open all switches in the CTDAC (CO6 and CVD). +* +* \param base +* Pointer to structure describing registers +* +* \return None +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm4.c CTDAC_SNIPPET_OPEN_ALL_SWITCHES +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTDAC_OpenAllSwitches(CTDAC_Type *base) +{ + base->CTDAC_SW_CLEAR = CY_CTDAC_DEINT_CTDAC_SW; +} + +/** \} */ + +/** +* \addtogroup group_ctdac_functions_interrupts +* \{ +*/ +/******************************************************************************* +* Function Name: Cy_CTDAC_GetInterruptStatus +****************************************************************************//** +* +* Return the interrupt status which gets set by the hardware +* when the CTDAC_VAL_NXT register value is transferred to the CTDAC_VAL register. +* Once set, the CTDAC_VAL_NXT register is ready to accept a new value. +* +* \note +* Interrupts are available in all update modes except \ref group_ctdac_updatemode_direct_write. +* +* \param base +* Pointer to structure describing registers +* +* \return +* - 0: Value not moved from CTDAC_VAL_NXT to CTDAC_VAL +* - 1: Value moved from CTDAC_VAL_NXT to CTDAC_VAL +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm0p.c SNIPPET_CTDAC_GET_INTERRUPT_STATUS +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_CTDAC_GetInterruptStatus(const CTDAC_Type *base) +{ + return (base->INTR & CTDAC_INTR_VDAC_EMPTY_Msk) >> CTDAC_INTR_VDAC_EMPTY_Pos; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_ClearInterrupt +****************************************************************************//** +* +* Clear the interrupt that was set by the hardware when the +* CTDAC_VAL_NXT register value is transferred to the CTDAC_VAL register. +* The interrupt must be cleared with this function so that +* the hardware can set subsequent interrupts and those interrupts +* can be forwarded to the interrupt controller, if enabled. +* +* \note +* Interrupts are available in all update modes except \ref group_ctdac_updatemode_direct_write. +* +* \param base +* Pointer to structure describing registers +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTDAC_ClearInterrupt(CTDAC_Type *base) +{ + base->INTR = CTDAC_INTR_VDAC_EMPTY_Msk; + + /* Dummy read for buffered writes. */ + (void) base->INTR; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_SetInterrupt +****************************************************************************//** +* +* Force the CTDAC interrupt to trigger using software. +* +* \note +* Interrupts are available in all update modes except \ref group_ctdac_updatemode_direct_write. +* +* \param base +* Pointer to structure describing registers +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTDAC_SetInterrupt(CTDAC_Type *base) +{ + base->INTR_SET = CTDAC_INTR_SET_VDAC_EMPTY_SET_Msk; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_SetInterruptMask +****************************************************************************//** +* +* Configure the CTDAC interrupt to be forwarded to the CPU interrupt +* controller. +* +* \note +* Interrupts are available in all update modes except \ref group_ctdac_updatemode_direct_write. +* +* \param base +* Pointer to structure describing registers +* +* \param mask +* The CTDAC only has one interrupt so the mask is one bit. +* - 0: Disable CTDAC interrupt request (will not be forwarded to CPU interrupt controller) +* - 1: Enable CTDAC interrupt request (will be forwarded to CPU interrupt controller) +* +* \return None +* +* \funcusage +* +* \snippet ctdac_sut_01.cydsn/main_cm0p.c SNIPPET_CTDAC_SET_INTERRUPT_MASK +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CTDAC_SetInterruptMask(CTDAC_Type *base, uint32_t mask) +{ + CY_ASSERT_L2(CY_CTDAC_INTRMASK(mask)); + + base->INTR_MASK = mask & CTDAC_INTR_MASK_VDAC_EMPTY_MASK_Msk; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_GetInterruptMask +****************************************************************************//** +* +* Return whether the CTDAC interrupt is +* forwarded to the CPU interrupt controller +* as configured by \ref Cy_CTDAC_SetInterruptMask. +* +* \note +* Interrupts are available in all update modes except \ref group_ctdac_updatemode_direct_write. +* +* \param base +* Pointer to structure describing registers +* +* \return +* The CTDAC only has one interrupt so the return value is either 0 or 1. +* - 0: Interrupt output not forwarded to CPU interrupt controller +* - 1: Interrupt output forwarded to CPU interrupt controller +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_CTDAC_GetInterruptMask(const CTDAC_Type *base) +{ + return (base->INTR_MASK & CTDAC_INTR_MASK_VDAC_EMPTY_MASK_Msk) >> CTDAC_INTR_MASK_VDAC_EMPTY_MASK_Pos; +} + +/******************************************************************************* +* Function Name: Cy_CTDAC_GetInterruptStatusMasked +****************************************************************************//** +* +* Return the bitwise AND of \ref Cy_CTDAC_GetInterruptStatus and +* \ref Cy_CTDAC_SetInterruptMask. When high, the DAC interrupt is +* asserted and the interrupt is forwarded to the CPU interrupt +* controller. +* +* \note +* Interrupts are available in all update modes except \ref group_ctdac_updatemode_direct_write. +* +* \param base +* Pointer to structure describing registers +* +* \return +* - 0: Value not moved from CTDAC_VAL_NXT to CTDAC_VAL or not masked +* - 1: Value moved from CTDAC_VAL_NXT to CTDAC_VAL and masked +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_CTDAC_GetInterruptStatusMasked(const CTDAC_Type *base){ + return (base->INTR_MASKED & CTDAC_INTR_MASKED_VDAC_EMPTY_MASKED_Msk) >> CTDAC_INTR_MASKED_VDAC_EMPTY_MASKED_Pos; +} + +/** \} */ + +/** \} group_ctdac_functions */ + +#if defined(__cplusplus) +} +#endif + +#endif /** !defined(CY_CTDAC_H) */ + +/** \} group_ctdac */ + +/* [] END OF FILE */ + diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/dma/cy_dma.c b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/dma/cy_dma.c new file mode 100644 index 0000000000..5f9bd8164b --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/dma/cy_dma.c @@ -0,0 +1,353 @@ +/***************************************************************************//** +* \file cy_dma.c +* \version 2.0.1 +* +* \brief +* The source code file for the DMA driver. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include "cy_dma.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_Init +****************************************************************************//** +* +* Initializes the descriptor structure in SRAM from a pre-initialized +* configuration structure. +* This function initializes only the descriptor and not the channel. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param config +* This is a configuration structure that has all initialization information for +* the descriptor. +* +* \return +* The status /ref cy_en_dma_status_t. +* +*******************************************************************************/ +cy_en_dma_status_t Cy_DMA_Descriptor_Init(cy_stc_dma_descriptor_t * descriptor, const cy_stc_dma_descriptor_config_t * config) +{ + cy_en_dma_status_t retVal = CY_DMA_BAD_PARAM; + + if ((NULL != descriptor) && (NULL != config)) + { + CY_ASSERT_L3(CY_DMA_IS_RETRIGGER_VALID(config->retrigger)); + CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->interruptType)); + CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->triggerOutType)); + CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->triggerInType)); + CY_ASSERT_L3(CY_DMA_IS_XFER_SIZE_VALID(config->srcTransferSize)); + CY_ASSERT_L3(CY_DMA_IS_XFER_SIZE_VALID(config->dstTransferSize)); + CY_ASSERT_L3(CY_DMA_IS_CHANNEL_STATE_VALID(config->channelState)); + CY_ASSERT_L3(CY_DMA_IS_DATA_SIZE_VALID(config->dataSize)); + CY_ASSERT_L3(CY_DMA_IS_TYPE_VALID(config->descriptorType)); + + descriptor->ctl = + _VAL2FLD(CY_DMA_CTL_RETRIG, config->retrigger) | + _VAL2FLD(CY_DMA_CTL_INTR_TYPE, config->interruptType) | + _VAL2FLD(CY_DMA_CTL_TR_OUT_TYPE, config->triggerOutType) | + _VAL2FLD(CY_DMA_CTL_TR_IN_TYPE, config->triggerInType) | + _VAL2FLD(CY_DMA_CTL_SRC_SIZE, config->srcTransferSize) | + _VAL2FLD(CY_DMA_CTL_DST_SIZE, config->dstTransferSize) | + _VAL2FLD(CY_DMA_CTL_CH_DISABLE, config->channelState) | + _VAL2FLD(CY_DMA_CTL_DATA_SIZE, config->dataSize) | + _VAL2FLD(CY_DMA_CTL_TYPE, config->descriptorType); + + descriptor->src = (uint32_t)config->srcAddress; + + descriptor->dst = (uint32_t)config->dstAddress; + + switch(config->descriptorType) + { + case CY_DMA_SINGLE_TRANSFER: + { + descriptor->xCtl = (uint32_t)config->nextDescriptor; + break; + } + case CY_DMA_1D_TRANSFER: + { + CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(config->srcXincrement)); + CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(config->dstXincrement)); + CY_ASSERT_L2(CY_DMA_IS_COUNT_VALID(config->xCount)); + + descriptor->xCtl = + _VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) | + _VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstXincrement) | + /* Convert the data count from the user's range (1-256) into the machine range (0-255). */ + _VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL); + + descriptor->yCtl = (uint32_t)config->nextDescriptor; + break; + } + case CY_DMA_2D_TRANSFER: + { + CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(config->srcXincrement)); + CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(config->dstXincrement)); + CY_ASSERT_L2(CY_DMA_IS_COUNT_VALID(config->xCount)); + CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(config->srcYincrement)); + CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(config->dstYincrement)); + CY_ASSERT_L2(CY_DMA_IS_COUNT_VALID(config->yCount)); + + descriptor->xCtl = + _VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) | + _VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstXincrement) | + /* Convert the data count from the user's range (1-256) into the machine range (0-255). */ + _VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL); + + descriptor->yCtl = + _VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcYincrement) | + _VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstYincrement) | + /* Convert the data count from the user's range (1-256) into the machine range (0-255). */ + _VAL2FLD(CY_DMA_CTL_COUNT, config->yCount - 1UL); + + descriptor->nextPtr = (uint32_t)config->nextDescriptor; + break; + } + default: + { + /* An unsupported type of a descriptor */ + break; + } + } + + retVal = CY_DMA_SUCCESS; + } + + return retVal; +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_DeInit +****************************************************************************//** +* +* Clears the content of the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +*******************************************************************************/ +void Cy_DMA_Descriptor_DeInit(cy_stc_dma_descriptor_t * descriptor) +{ + descriptor->ctl = 0UL; + descriptor->src = 0UL; + descriptor->dst = 0UL; + descriptor->xCtl = 0UL; + descriptor->yCtl = 0UL; + descriptor->nextPtr = 0UL; +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_Init +****************************************************************************//** +* +* Initializes the DMA channel with a descriptor and other parameters. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* A channel number. +* +* \param channelConfig +* The structure that has the initialization information for the +* channel. +* +* \return +* The status /ref cy_en_dma_status_t. +* +*******************************************************************************/ +cy_en_dma_status_t Cy_DMA_Channel_Init(DW_Type * base, uint32_t channel, cy_stc_dma_channel_config_t const * channelConfig) +{ + cy_en_dma_status_t retVal = CY_DMA_BAD_PARAM; + + if (((CY_DMA_IS_DW_CH_NR_VALID(base, channel)) && (NULL != channelConfig) && (NULL != channelConfig->descriptor))) + { + CY_ASSERT_L2(CY_DMA_IS_PRIORITY_VALID(channelConfig->priority)); + + /* Set the current descriptor */ + base->CH_STRUCT[channel].CH_CURR_PTR = (uint32_t)channelConfig->descriptor; + + /* Set the channel configuration */ + base->CH_STRUCT[channel].CH_CTL = _BOOL2FLD(DW_CH_STRUCT_CH_CTL_PREEMPTABLE, channelConfig->preemptable) | + _VAL2FLD(DW_CH_STRUCT_CH_CTL_PRIO, channelConfig->priority) | + _BOOL2FLD(DW_CH_STRUCT_CH_CTL_ENABLED, channelConfig->enable) | + _BOOL2FLD(DW_CH_STRUCT_CH_CTL_B, channelConfig->bufferable); + retVal = CY_DMA_SUCCESS; + } + + return (retVal); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_DeInit +****************************************************************************//** +* +* Clears the content of registers corresponding to the channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* A channel number. +* +*******************************************************************************/ +void Cy_DMA_Channel_DeInit(DW_Type * base, uint32_t channel) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + + base->CH_STRUCT[channel].CH_CTL = 0UL; + base->CH_STRUCT[channel].CH_IDX = 0UL; + base->CH_STRUCT[channel].CH_CURR_PTR = 0UL; + base->CH_STRUCT[channel].INTR_MASK = 0UL; +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetNextDescriptor +****************************************************************************//** +* +* Sets a Next Descriptor parameter for the specified descriptor. +* +* Based on the descriptor type, the offset of the address for the next descriptor may +* vary. For the single-transfer descriptor type, this register is at offset 0x0c. +* For the 1D-transfer descriptor type, this register is at offset 0x10. +* For the 2D-transfer descriptor type, this register is at offset 0x14. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param nextDescriptor +* The pointer to the next descriptor. +* +*******************************************************************************/ +void Cy_DMA_Descriptor_SetNextDescriptor(cy_stc_dma_descriptor_t * descriptor, cy_stc_dma_descriptor_t const * nextDescriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + + switch((cy_en_dma_descriptor_type_t) _FLD2VAL(CY_DMA_CTL_TYPE, descriptor->ctl)) + { + case CY_DMA_SINGLE_TRANSFER: + descriptor->xCtl = (uint32_t)nextDescriptor; + break; + + case CY_DMA_1D_TRANSFER: + descriptor->yCtl = (uint32_t)nextDescriptor; + break; + + case CY_DMA_2D_TRANSFER: + descriptor->nextPtr = (uint32_t)nextDescriptor; + break; + + default: + /* Unsupported type of descriptor */ + break; + } +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetNextDescriptor +****************************************************************************//** +* +* Returns a next descriptor address of the specified descriptor. +* +* Based on the descriptor type, the offset of the address for the next descriptor may +* vary. For a single-transfer descriptor type, this register is at offset 0x0c. +* For the 1D-transfer descriptor type, this register is at offset 0x10. +* For the 2D-transfer descriptor type, this register is at offset 0x14. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The pointer to the next descriptor. +* +*******************************************************************************/ +cy_stc_dma_descriptor_t * Cy_DMA_Descriptor_GetNextDescriptor(cy_stc_dma_descriptor_t const * descriptor) +{ + cy_stc_dma_descriptor_t * retVal = NULL; + + CY_ASSERT_L1(NULL != descriptor); + + switch((cy_en_dma_descriptor_type_t) _FLD2VAL(CY_DMA_CTL_TYPE, descriptor->ctl)) + { + case CY_DMA_SINGLE_TRANSFER: + retVal = (cy_stc_dma_descriptor_t*) descriptor->xCtl; + break; + + case CY_DMA_1D_TRANSFER: + retVal = (cy_stc_dma_descriptor_t*) descriptor->yCtl; + break; + + case CY_DMA_2D_TRANSFER: + retVal = (cy_stc_dma_descriptor_t*) descriptor->nextPtr; + break; + + default: + /* An unsupported type of the descriptor */ + break; + } + + return (retVal); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetDescriptorType +****************************************************************************//** +* +* Sets the descriptor's type for the specified descriptor. +* Moves the next descriptor register value into the proper place in accordance +* to the actual descriptor type. +* During the descriptor's type changing, the Xloop and Yloop settings, such as +* data count and source/destination increment (i.e. the content of the +* xCtl and yCtl descriptor registers) might be lost (overriden by the +* next descriptor value) because of the different descriptor registers structures +* for different descriptor types. Set up carefully the Xloop +* (and Yloop, if used) data count and source/destination increment if the +* descriptor type is changed from a simpler to a more complicated type +* ("single transfer" -> "1D", "1D" -> "2D", etc.). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param descriptorType +* The descriptor type \ref cy_en_dma_descriptor_type_t. +* +*******************************************************************************/ +void Cy_DMA_Descriptor_SetDescriptorType(cy_stc_dma_descriptor_t * descriptor, cy_en_dma_descriptor_type_t descriptorType) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L3(CY_DMA_IS_TYPE_VALID(descriptorType)); + + if (descriptorType != Cy_DMA_Descriptor_GetDescriptorType(descriptor)) /* Don't perform if the type is not changed */ + { + /* Store the current nextDescriptor pointer. */ + cy_stc_dma_descriptor_t * locNextDescriptor = Cy_DMA_Descriptor_GetNextDescriptor(descriptor); + /* Change the descriptor type. */ + descriptor->ctl = _CLR_SET_FLD32U(descriptor->ctl, CY_DMA_CTL_TYPE, descriptorType); + /* Restore the nextDescriptor pointer into the proper place. */ + Cy_DMA_Descriptor_SetNextDescriptor(descriptor, locNextDescriptor); + } +} + + +#if defined(__cplusplus) +} +#endif + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/dma/cy_dma.h b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/dma/cy_dma.h new file mode 100644 index 0000000000..85b1857aaa --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/dma/cy_dma.h @@ -0,0 +1,1810 @@ +/***************************************************************************//** +* \file cy_dma.h +* \version 2.0.1 +* +* \brief +* The header file of the DMA driver. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +/** +* \defgroup group_dma Direct Memory Access (DMA) +* \{ +* Configures a DMA channel and its descriptor(s). +* +* The DMA channel can be used in any project to transfer data +* without CPU intervention basing on a hardware trigger signal from another component. +* +* A device may support more than one DMA hardware block. Each block has a set of +* registers, a base hardware address, and supports multiple channels. +* Many API functions for the DMA driver require a base hardware address and +* channel number. Ensure that you use the correct hardware address for the DMA block in use. +* +* Features: +* * Devices support up to two DMA hardware blocks +* * Each DMA block supports up to 16 DMA channels +* * Supports channel descriptors in SRAM +* * Four priority levels for each channel +* * Byte, half-word (2-byte), and word (4-byte) transfers +* * Configurable source and destination addresses +* +* \section group_dma_configuration Configuration Considerations +* +* To set up a DMA driver, initialize a descriptor, +* intialize and enable a channel, and enable the DMA block. +* +* To set up a descriptor, provide the configuration parameters for the +* descriptor in the \ref cy_stc_dma_descriptor_config_t structure. Then call the +* \ref Cy_DMA_Descriptor_Init function to initialize the descriptor in SRAM. You can +* modify the source and destination addresses dynamically by calling +* \ref Cy_DMA_Descriptor_SetSrcAddress and \ref Cy_DMA_Descriptor_SetDstAddress. +* +* To set up a DMA channel, provide a filled \ref cy_stc_dma_channel_config_t +* structure. Call the \ref Cy_DMA_Channel_Init function, specifying the channel +* number. Use \ref Cy_DMA_Channel_Enable to enable the configured DMA channel. +* +* Call \ref Cy_DMA_Channel_Enable for each DMA channel in use. +* +* When configured, another peripheral typically triggers the DMA. The trigger is +* connected to the DMA using the trigger multiplexer. The trigger multiplexer +* driver has a software trigger you can use in firmware to trigger the DMA. See the +* Trigger Multiplexer documentation. +* +* The following is a simplified structure of the DMA driver API interdependencies +* in a typical user application: +* \image html dma.png +* +* NOTE: Even if a DMA channel is enabled, it is not operational until +* the DMA block is enabled using function \ref Cy_DMA_Enable.\n +* NOTE: if the DMA descriptor is configured to generate an interrupt, +* the interrupt must be enabled using the \ref Cy_DMA_Channel_SetInterruptMask +* function for each DMA channel. +* +* For example: +* \snippet dma/dma_v2_0_sut_00.cydsn/main_cm4.c Cy_DMA_Snippet +* +* \section group_dma_more_information More Information. +* See: the DMA chapter of the device technical reference manual (TRM); +* the DMA Component datasheet; +* CE219940 - PSoC 6 MCU Multiple DMA Concatenation. +* +* \section group_dma_MISRA MISRA-C Compliance +* The DMA driver has the following specific deviations: +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
MISRA RuleRule Class (Required/Advisory)Rule DescriptionDescription of Deviation(s)
10.3RA composite expression of the "essentially unsigned" type is being +* cast to a different type category.The value got from the bitfield physically cannot exceed the enumeration +* that describes this bitfield. So, the code is safe by design.
14.2RAll non-null statements will either: +* a) have at least one-side effect however executed; +* b) cause the control flow to changeA Read operation result is ignored when this read is just intended +* to ensure the previous Write operation is flushed out to the hardware.
+* +* \section group_dma_changelog Changelog +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
VersionChangesReason for Change
2.0.1Changed \ref CY_DMA_BWC macro values from Boolean to numericImprovements made based on usability feedback
2.0* All the API is refactored to be consistent within itself and with the +* rest of the PDL content. +* * The descriptor API is updated as follows: +* The \ref Cy_DMA_Descriptor_Init function sets a full bunch of descriptor +* settings, and the rest of the descriptor API is a get/set interface +* to each of the descriptor settings. +* * There is a group of macros to support the backward compatibility with most +* of the driver version 1.0 API. But, it is strongly recommended to use +* the new v2.0 interface in new designs (do not just copy-paste from old +* projects). To enable the backward compatibility support, the CY_DMA_BWC +* definition should be changed to "1".
1.0Initial version
+* + +* \defgroup group_dma_macros Macros +* \defgroup group_dma_functions Functions +* \{ +* \defgroup group_dma_block_functions Block Functions +* \defgroup group_dma_descriptor_functions Descriptor Functions +* \defgroup group_dma_channel_functions Channel Functions +* \} +* \defgroup group_dma_data_structures Data Structures +* \defgroup group_dma_enums Enumerated Types +*/ + +#if !defined(CY_DMA_H) +#define CY_DMA_H + +#include +#include +#include +#include "syslib/cy_syslib.h" +#include "cy_device_headers.h" + +#ifndef CY_IP_M4CPUSS_DMA + #error "The DMA driver is not supported on this device" +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +/****************************************************************************** + * Macro definitions * + ******************************************************************************/ + +/** +* \addtogroup group_dma_macros +* \{ +*/ + +/** The driver major version */ +#define CY_DMA_DRV_VERSION_MAJOR 2 + +/** The driver minor version */ +#define CY_DMA_DRV_VERSION_MINOR 0 + +/** The DMA driver identifier */ +#define CY_DMA_ID (CY_PDL_DRV_ID(0x13U)) + +/** The DMA channel interrupt mask */ +#define CY_DMA_INTR_MASK (0x01UL) + +/** The backward compatibility flag. Enables a group of macros which provide +* the backward compatibility with most of the DMA driver version 1.0 interface. */ +#ifndef CY_DMA_BWC + #define CY_DMA_BWC (0U) +#endif + +/** \} group_dma_macros */ + + +/** +* \addtogroup group_dma_enums +* \{ +*/ + +/** Contains the possible interrupt cause values */ +typedef enum +{ + CY_DMA_INTR_CAUSE_NO_INTR = 0U, /**< No interrupt */ + CY_DMA_INTR_CAUSE_COMPLETION = 1U, /**< Completion */ + CY_DMA_INTR_CAUSE_SRC_BUS_ERROR = 2U, /**< Source bus error */ + CY_DMA_INTR_CAUSE_DST_BUS_ERROR = 3U, /**< Destination bus error */ + CY_DMA_INTR_CAUSE_SRC_MISAL = 4U, /**< Source address is not aligned */ + CY_DMA_INTR_CAUSE_DST_MISAL = 5U, /**< Destination address is not aligned */ + CY_DMA_INTR_CAUSE_CURR_PTR_NULL = 6U, /**< Current descripror pointer is NULL */ + CY_DMA_INTR_CAUSE_ACTIVE_CH_DISABLED = 7U, /**< Active channel is disabled */ + CY_DMA_INTR_CAUSE_DESCR_BUS_ERROR = 8U /**< Descriptor bus error */ +} cy_en_dma_intr_cause_t; + +/** Contains the options for the descriptor type */ +typedef enum +{ + CY_DMA_SINGLE_TRANSFER = 0UL, /**< Single transfer. */ + CY_DMA_1D_TRANSFER = 1UL, /**< 1D transfer. */ + CY_DMA_2D_TRANSFER = 2UL /**< 2D transfer. */ +} cy_en_dma_descriptor_type_t; + +/** Contains the options for the interrupt, trig-in and trig-out type parameters of the descriptor */ +typedef enum +{ + CY_DMA_1ELEMENT = 0UL, /**< One element transfer. */ + CY_DMA_X_LOOP = 1UL, /**< One X loop transfer. */ + CY_DMA_DESCR = 2UL, /**< One descriptor transfer. */ + CY_DMA_DESCR_CHAIN = 3UL /**< Entire descriptor chain transfer. */ +} cy_en_dma_trigger_type_t; + +/** This enum has the options for the data size */ +typedef enum +{ + CY_DMA_BYTE = 0UL, /**< One byte */ + CY_DMA_HALFWORD = 1UL, /**< Half word (two bytes) */ + CY_DMA_WORD = 2UL /**< Full word (four bytes) */ +} cy_en_dma_data_size_t; + +/** This enum has the options for descriptor retriggering */ +typedef enum +{ + CY_DMA_RETRIG_IM = 0UL, /**< Retrigger immediatelly */ + CY_DMA_RETRIG_4CYC = 1UL, /**< Retrigger after 4 Clk_Slow cycles */ + CY_DMA_RETRIG_16CYC = 2UL, /**< Retrigger after 16 Clk_Slow cycles */ + CY_DMA_WAIT_FOR_REACT = 3UL /**< Wait for trigger reactivation */ +} cy_en_dma_retrigger_t; + +/** This enum has the options for the transfer size */ +typedef enum +{ + CY_DMA_TRANSFER_SIZE_DATA = 0UL, /**< As specified by dataSize. */ + CY_DMA_TRANSFER_SIZE_WORD = 1UL, /**< A full word (four bytes). */ +} cy_en_dma_transfer_size_t; + +/** This enum has the options for the state of the channel when the descriptor is completed */ +typedef enum +{ + CY_DMA_CHANNEL_ENABLED = 0UL, /**< Channel stays enabled */ + CY_DMA_CHANNEL_DISABLED = 1UL /**< Channel is disabled */ +} cy_en_dma_channel_state_t; + +/** This enum has the return values of the DMA driver */ +typedef enum +{ + CY_DMA_SUCCESS = 0x00UL, /**< Success. */ + CY_DMA_BAD_PARAM = CY_DMA_ID | CY_PDL_STATUS_ERROR | 0x01UL /**< The input parameters passed to the DMA API are not valid. */ +} cy_en_dma_status_t; + +/** \} group_dma_enums */ + + +/** \cond Macros for the conditions used by CY_ASSERT calls */ + +#define CY_DMA_IS_COUNT_VALID(count) (((count) >= 1UL) && ((count) <= 256UL)) +#define CY_DMA_IS_INCR_VALID(incr) (((incr) >= -2048L) && ((incr) <= 2047L)) +#define CY_DMA_IS_PRIORITY_VALID(prio) ((prio) <= 3UL) +#define CY_DMA_IS_INTR_MASK_VALID(interrupt) (0UL == ((interrupt) & ((uint32_t) ~CY_DMA_INTR_MASK))) + +#define CY_DMA_IS_RETRIGGER_VALID(retrigger) ((CY_DMA_RETRIG_IM == (retrigger)) || \ + (CY_DMA_RETRIG_4CYC == (retrigger)) || \ + (CY_DMA_RETRIG_16CYC == (retrigger)) || \ + (CY_DMA_WAIT_FOR_REACT == (retrigger))) + +#define CY_DMA_IS_TRIG_TYPE_VALID(trigType) ((CY_DMA_1ELEMENT == (trigType)) || \ + (CY_DMA_X_LOOP == (trigType)) || \ + (CY_DMA_DESCR == (trigType)) || \ + (CY_DMA_DESCR_CHAIN == (trigType))) + +#define CY_DMA_IS_XFER_SIZE_VALID(xferSize) ((CY_DMA_TRANSFER_SIZE_DATA == (xferSize)) || \ + (CY_DMA_TRANSFER_SIZE_WORD == (xferSize))) + +#define CY_DMA_IS_CHANNEL_STATE_VALID(state) ((CY_DMA_CHANNEL_ENABLED == (state)) || \ + (CY_DMA_CHANNEL_DISABLED == (state))) + +#define CY_DMA_IS_DATA_SIZE_VALID(dataSize) ((CY_DMA_BYTE == (dataSize)) || \ + (CY_DMA_HALFWORD == (dataSize)) || \ + (CY_DMA_WORD == (dataSize))) + +#define CY_DMA_IS_TYPE_VALID(descrType) ((CY_DMA_SINGLE_TRANSFER == (descrType)) || \ + (CY_DMA_1D_TRANSFER == (descrType)) || \ + (CY_DMA_2D_TRANSFER == (descrType))) + +#define CY_DMA_IS_DW_CH_NR_VALID(dwNr, chNr) (((0U != CPUSS_DW0_PRESENT) && (DW0 == (dwNr)) && ((chNr) < CPUSS_DW0_CH_NR)) || \ + ((0U != CPUSS_DW1_PRESENT) && (DW1 == (dwNr)) && ((chNr) < CPUSS_DW1_CH_NR))) + +/* The descriptor structure bit-filed definitions */ +#define CY_DMA_CTL_RETRIG_Pos 0UL +#define CY_DMA_CTL_RETRIG_Msk 0x3UL +#define CY_DMA_CTL_INTR_TYPE_Pos 2UL +#define CY_DMA_CTL_INTR_TYPE_Msk 0xCUL +#define CY_DMA_CTL_TR_OUT_TYPE_Pos 4UL +#define CY_DMA_CTL_TR_OUT_TYPE_Msk 0x30UL +#define CY_DMA_CTL_TR_IN_TYPE_Pos 6UL +#define CY_DMA_CTL_TR_IN_TYPE_Msk 0xC0UL +#define CY_DMA_CTL_CH_DISABLE_Pos 24UL +#define CY_DMA_CTL_CH_DISABLE_Msk 0x1000000UL +#define CY_DMA_CTL_SRC_SIZE_Pos 26UL +#define CY_DMA_CTL_SRC_SIZE_Msk 0x4000000UL +#define CY_DMA_CTL_DST_SIZE_Pos 27UL +#define CY_DMA_CTL_DST_SIZE_Msk 0x8000000UL +#define CY_DMA_CTL_DATA_SIZE_Pos 28UL +#define CY_DMA_CTL_DATA_SIZE_Msk 0x30000000UL +#define CY_DMA_CTL_TYPE_Pos 30UL +#define CY_DMA_CTL_TYPE_Msk 0xC0000000UL + +#define CY_DMA_CTL_SRC_INCR_Pos 0UL +#define CY_DMA_CTL_SRC_INCR_Msk 0xFFFUL +#define CY_DMA_CTL_DST_INCR_Pos 12UL +#define CY_DMA_CTL_DST_INCR_Msk 0xFFF000UL +#define CY_DMA_CTL_COUNT_Pos 24UL +#define CY_DMA_CTL_COUNT_Msk 0xFF000000UL + +/** \endcond */ + + +/** +* \addtogroup group_dma_data_structures +* \{ +*/ + +/** +* DMA descriptor structure type. It is a user/component-declared structure +* allocated in RAM. The DMA HW requires a pointer to this structure to work with it. +* +* For advanced users: the descriptor can be allocated even in Flash, then the user +* manually predefines all the structure items with constants, +* bacause most of the driver's API (especially functions modifying +* descriptors, including \ref Cy_DMA_Descriptor_Init()) can't work with +* read-only descriptors. +*/ +typedef struct +{ + uint32_t ctl; /*!< 0x00000000 Descriptor control */ + uint32_t src; /*!< 0x00000004 Descriptor source */ + uint32_t dst; /*!< 0x00000008 Descriptor destination */ + uint32_t xCtl; /*!< 0x0000000C Descriptor X loop control */ + uint32_t yCtl; /*!< 0x00000010 Descriptor Y loop control */ + uint32_t nextPtr; /*!< 0x00000014 Descriptor next pointer */ +} cy_stc_dma_descriptor_t; + +/** +* This structure is a configuration structure pre-initialized by the user and +* passed as a parameter to the \ref Cy_DMA_Descriptor_Init(). +* It can be allocated in RAM/Flash (on user's choice). +* In case of Flash allocation there is a possibility to reinitialize the descriptor in runtime. +* This structure has all the parameters of the descriptor as separate parameters. +* Most of these parameters are represented in the \ref cy_stc_dma_descriptor_t structure as bit fields. +*/ +typedef struct +{ + cy_en_dma_retrigger_t retrigger; /**< Specifies whether the DW controller should wait for the input trigger to be deactivated. */ + cy_en_dma_trigger_type_t interruptType; /**< Sets the event that triggers an interrupt, see \ref cy_en_dma_trigger_type_t. */ + cy_en_dma_trigger_type_t triggerOutType; /**< Sets the event that triggers an output, see \ref cy_en_dma_trigger_type_t. */ + cy_en_dma_channel_state_t channelState; /**< Specifies if the channel is enabled or disabled on completion of descriptor see \ref cy_en_dma_channel_state_t. */ + cy_en_dma_trigger_type_t triggerInType; /**< Sets what type of transfer is triggered, see \ref cy_en_dma_trigger_type_t. */ + cy_en_dma_data_size_t dataSize; /**< The size of the data bus for transfer, see \ref cy_en_dma_data_size_t. */ + cy_en_dma_transfer_size_t srcTransferSize; /**< The source transfer size. */ + cy_en_dma_transfer_size_t dstTransferSize; /**< The destination transfer size. */ + cy_en_dma_descriptor_type_t descriptorType; /**< The type of the descriptor see \ref cy_en_dma_descriptor_type_t. */ + void * srcAddress; /**< The source address of the transfer. */ + void * dstAddress; /**< The destination address of the transfer. */ + int32_t srcXincrement; /**< The address increment of the source after each X-loop transfer. Valid range is -2048...2047. */ + int32_t dstXincrement; /**< The address increment of the destination after each X-loop transfer. Valid range is -2048...2047. */ + uint32_t xCount; /**< The number of transfers in an X-loop. Valid range is 1...256. */ + int32_t srcYincrement; /**< The address increment of the source after each Y-loop transfer. Valid range is -2048...2047. */ + int32_t dstYincrement; /**< The address increment of the destination after each Y-loop transfer. Valid range is -2048...2047. */ + uint32_t yCount; /**< The number of X-loops in the Y-loop. Valid range is 1...256. */ + cy_stc_dma_descriptor_t * nextDescriptor; /**< The next descriptor to chain after completion, a NULL value will signify no chaining. */ +} cy_stc_dma_descriptor_config_t; + +/** This structure holds the initialization values for the DMA channel */ +typedef struct +{ + cy_stc_dma_descriptor_t * descriptor; /**< The DMA descriptor associated with the channel being initialized */ + bool preemptable; /**< Specifies if the channel is preemptable by another higher-priority channel */ + uint32_t priority; /**< This parameter specifies the channel's priority */ + bool enable; /**< This parameter specifies if the channel is enabled after initializing */ + bool bufferable; /**< This parameter specifies whether a write transaction can complete + without waiting for the destination to accept the write transaction data. */ +} cy_stc_dma_channel_config_t; + +/** \} group_dma_data_structures */ + + +/** +* \addtogroup group_dma_functions +* \{ +*/ + +__STATIC_INLINE void Cy_DMA_Enable (DW_Type * base); +__STATIC_INLINE void Cy_DMA_Disable (DW_Type * base); +__STATIC_INLINE uint32_t Cy_DMA_GetActiveChannel (DW_Type const * base); +__STATIC_INLINE void * Cy_DMA_GetActiveSrcAddress(DW_Type const * base); +__STATIC_INLINE void * Cy_DMA_GetActiveDstAddress(DW_Type const * base); + + +/** +* \addtogroup group_dma_descriptor_functions +* \{ +*/ + + cy_en_dma_status_t Cy_DMA_Descriptor_Init (cy_stc_dma_descriptor_t * descriptor, cy_stc_dma_descriptor_config_t const * config); + void Cy_DMA_Descriptor_DeInit(cy_stc_dma_descriptor_t * descriptor); + + void Cy_DMA_Descriptor_SetNextDescriptor (cy_stc_dma_descriptor_t * descriptor, cy_stc_dma_descriptor_t const * nextDescriptor); + void Cy_DMA_Descriptor_SetDescriptorType (cy_stc_dma_descriptor_t * descriptor, cy_en_dma_descriptor_type_t descriptorType); +__STATIC_INLINE void Cy_DMA_Descriptor_SetSrcAddress (cy_stc_dma_descriptor_t * descriptor, void const * srcAddress); +__STATIC_INLINE void Cy_DMA_Descriptor_SetDstAddress (cy_stc_dma_descriptor_t * descriptor, void const * dstAddress); +__STATIC_INLINE void Cy_DMA_Descriptor_SetXloopDataCount (cy_stc_dma_descriptor_t * descriptor, uint32_t xCount); +__STATIC_INLINE void Cy_DMA_Descriptor_SetYloopDataCount (cy_stc_dma_descriptor_t * descriptor, uint32_t yCount); +__STATIC_INLINE void Cy_DMA_Descriptor_SetXloopSrcIncrement(cy_stc_dma_descriptor_t * descriptor, int32_t srcXincrement); +__STATIC_INLINE void Cy_DMA_Descriptor_SetXloopDstIncrement(cy_stc_dma_descriptor_t * descriptor, int32_t dstXincrement); +__STATIC_INLINE void Cy_DMA_Descriptor_SetYloopSrcIncrement(cy_stc_dma_descriptor_t * descriptor, int32_t srcYincrement); +__STATIC_INLINE void Cy_DMA_Descriptor_SetYloopDstIncrement(cy_stc_dma_descriptor_t * descriptor, int32_t dstYincrement); +__STATIC_INLINE void Cy_DMA_Descriptor_SetInterruptType (cy_stc_dma_descriptor_t * descriptor, cy_en_dma_trigger_type_t interruptType); +__STATIC_INLINE void Cy_DMA_Descriptor_SetTriggerInType (cy_stc_dma_descriptor_t * descriptor, cy_en_dma_trigger_type_t triggerInType); +__STATIC_INLINE void Cy_DMA_Descriptor_SetTriggerOutType (cy_stc_dma_descriptor_t * descriptor, cy_en_dma_trigger_type_t triggerOutType); +__STATIC_INLINE void Cy_DMA_Descriptor_SetDataSize (cy_stc_dma_descriptor_t * descriptor, cy_en_dma_data_size_t dataSize); +__STATIC_INLINE void Cy_DMA_Descriptor_SetSrcTransferSize (cy_stc_dma_descriptor_t * descriptor, cy_en_dma_transfer_size_t srcTransferSize); +__STATIC_INLINE void Cy_DMA_Descriptor_SetDstTransferSize (cy_stc_dma_descriptor_t * descriptor, cy_en_dma_transfer_size_t dstTransferSize); +__STATIC_INLINE void Cy_DMA_Descriptor_SetRetrigger (cy_stc_dma_descriptor_t * descriptor, cy_en_dma_retrigger_t retrigger); +__STATIC_INLINE void Cy_DMA_Descriptor_SetChannelState (cy_stc_dma_descriptor_t * descriptor, cy_en_dma_channel_state_t channelState); + + cy_stc_dma_descriptor_t * Cy_DMA_Descriptor_GetNextDescriptor (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE cy_en_dma_descriptor_type_t Cy_DMA_Descriptor_GetDescriptorType (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE void * Cy_DMA_Descriptor_GetSrcAddress (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE void * Cy_DMA_Descriptor_GetDstAddress (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE uint32_t Cy_DMA_Descriptor_GetXloopDataCount (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE uint32_t Cy_DMA_Descriptor_GetYloopDataCount (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE int32_t Cy_DMA_Descriptor_GetXloopSrcIncrement(cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE int32_t Cy_DMA_Descriptor_GetXloopDstIncrement(cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE int32_t Cy_DMA_Descriptor_GetYloopSrcIncrement(cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE int32_t Cy_DMA_Descriptor_GetYloopDstIncrement(cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE cy_en_dma_trigger_type_t Cy_DMA_Descriptor_GetInterruptType (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE cy_en_dma_trigger_type_t Cy_DMA_Descriptor_GetTriggerInType (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE cy_en_dma_trigger_type_t Cy_DMA_Descriptor_GetTriggerOutType (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE cy_en_dma_data_size_t Cy_DMA_Descriptor_GetDataSize (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE cy_en_dma_transfer_size_t Cy_DMA_Descriptor_GetSrcTransferSize (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE cy_en_dma_transfer_size_t Cy_DMA_Descriptor_GetDstTransferSize (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE cy_en_dma_retrigger_t Cy_DMA_Descriptor_GetRetrigger (cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE cy_en_dma_channel_state_t Cy_DMA_Descriptor_GetChannelState (cy_stc_dma_descriptor_t const * descriptor); + +/** \} group_dma_descriptor_functions */ + + +/** +* \addtogroup group_dma_channel_functions +* \{ +*/ + + cy_en_dma_status_t Cy_DMA_Channel_Init (DW_Type * base, uint32_t channel, cy_stc_dma_channel_config_t const * channelConfig); + void Cy_DMA_Channel_DeInit (DW_Type * base, uint32_t channel); +__STATIC_INLINE void Cy_DMA_Channel_SetDescriptor(DW_Type * base, uint32_t channel, cy_stc_dma_descriptor_t const * descriptor); +__STATIC_INLINE void Cy_DMA_Channel_Enable (DW_Type * base, uint32_t channel); +__STATIC_INLINE void Cy_DMA_Channel_Disable (DW_Type * base, uint32_t channel); +__STATIC_INLINE void Cy_DMA_Channel_SetPriority (DW_Type * base, uint32_t channel, uint32_t priority); +__STATIC_INLINE uint32_t Cy_DMA_Channel_GetPriority (DW_Type const * base, uint32_t channel); +__STATIC_INLINE cy_en_dma_intr_cause_t Cy_DMA_Channel_GetStatus(DW_Type const * base, uint32_t channel); +__STATIC_INLINE cy_stc_dma_descriptor_t * Cy_DMA_Channel_GetCurrentDescriptor(DW_Type const * base, uint32_t channel); + +__STATIC_INLINE uint32_t Cy_DMA_Channel_GetInterruptStatus (DW_Type const * base, uint32_t channel); +__STATIC_INLINE void Cy_DMA_Channel_ClearInterrupt (DW_Type * base, uint32_t channel); +__STATIC_INLINE void Cy_DMA_Channel_SetInterrupt (DW_Type * base, uint32_t channel); +__STATIC_INLINE uint32_t Cy_DMA_Channel_GetInterruptMask (DW_Type const * base, uint32_t channel); +__STATIC_INLINE void Cy_DMA_Channel_SetInterruptMask (DW_Type * base, uint32_t channel, uint32_t interrupt); +__STATIC_INLINE uint32_t Cy_DMA_Channel_GetInterruptStatusMasked(DW_Type const * base, uint32_t channel); + +/** \} group_dma_channel_functions */ + + +/*************************************** +* In-line Function Implementation +***************************************/ + + +/** +* \addtogroup group_dma_block_functions +* \{ +*/ + + +/******************************************************************************* +* Function Name: Cy_DMA_Enable +****************************************************************************//** +* +* Enables the DMA block. +* +* \param base +* The pointer to the hardware DMA block. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Enable(DW_Type * base) +{ + base->CTL |= DW_CTL_ENABLED_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Disable +****************************************************************************//** +* +* Disables the DMA block. +* +* \param base +* The pointer to the hardware DMA block. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Disable(DW_Type * base) +{ + base->CTL &= (uint32_t) ~DW_CTL_ENABLED_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_DMA_GetActiveChannel +****************************************************************************//** +* +* Returns the status of the active/pending channels. +* the DMA block. +* +* \param base +* The pointer to the hardware DMA block. +* +* \return +* Returns a bit-field with all of the currently active/pending channels in the +* DMA block. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_DMA_GetActiveChannel(DW_Type const * base) +{ + return(_FLD2VAL(DW_STATUS_CH_IDX, base->STATUS)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_GetActiveSrcAddress +****************************************************************************//** +* +* Returns the source address being used for the current transfer. +* +* \param base +* The pointer to the hardware DMA block. +* +* \return +* Returns the pointer to the source of transfer. +* +*******************************************************************************/ +__STATIC_INLINE void * Cy_DMA_GetActiveSrcAddress(DW_Type const * base) +{ + return ((void *)base->ACT_DESCR_SRC); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_GetActiveDstAddress +****************************************************************************//** +* +* Returns the destination address being used for the current transfer. +* +* \param base +* The pointer to the hardware DMA block. +* +* \return +* Returns the pointer to the destination of transfer. +* +*******************************************************************************/ +__STATIC_INLINE void * Cy_DMA_GetActiveDstAddress(DW_Type const * base) +{ + return ((void *) base->ACT_DESCR_DST); +} + +/** \} group_dma_block_functions */ + + +/** +* \addtogroup group_dma_descriptor_functions +* \{ +*/ + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetSrcAddress +****************************************************************************//** +* +* Sets the source address parameter for the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param srcAddress +* The source address value for the descriptor. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetSrcAddress(cy_stc_dma_descriptor_t * descriptor, void const * srcAddress) +{ + descriptor->src = (uint32_t) srcAddress; +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetSrcAddress +****************************************************************************//** +* +* Returns the source address parameter of the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The source address value of the descriptor. +* +*******************************************************************************/ +__STATIC_INLINE void * Cy_DMA_Descriptor_GetSrcAddress(cy_stc_dma_descriptor_t const * descriptor) +{ + return ((void *) descriptor->src); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetDstAddress +****************************************************************************//** +* +* Sets the destination address parameter for the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param dstAddress +* The destination address value for the descriptor. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetDstAddress(cy_stc_dma_descriptor_t * descriptor, void const * dstAddress) +{ + descriptor->dst = (uint32_t) dstAddress; +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetDstAddress +****************************************************************************//** +* +* Returns the destination address parameter of the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The destination address value of the descriptor. +* +*******************************************************************************/ +__STATIC_INLINE void * Cy_DMA_Descriptor_GetDstAddress(cy_stc_dma_descriptor_t const * descriptor) +{ + return ((void *) descriptor->dst); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetInterruptType +****************************************************************************//** +* +* Sets the interrupt type parameter for the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param interruptType +* The interrupt type set for the descriptor. \ref cy_en_dma_trigger_type_t +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetInterruptType(cy_stc_dma_descriptor_t * descriptor, cy_en_dma_trigger_type_t interruptType) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(interruptType)); + + descriptor->ctl = _CLR_SET_FLD32U(descriptor->ctl, CY_DMA_CTL_INTR_TYPE, interruptType); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetInterruptType +****************************************************************************//** +* +* Returns the Interrupt-Type of the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The Interrupt-Type \ref cy_en_dma_trigger_type_t. +* +*******************************************************************************/ +__STATIC_INLINE cy_en_dma_trigger_type_t Cy_DMA_Descriptor_GetInterruptType(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + + return((cy_en_dma_trigger_type_t) _FLD2VAL(CY_DMA_CTL_INTR_TYPE, descriptor->ctl)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetTriggerInType +****************************************************************************//** +* +* Sets the Trigger-In-Type parameter for the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param triggerInType +* The Trigger In Type parameter \ref cy_en_dma_trigger_type_t +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetTriggerInType(cy_stc_dma_descriptor_t * descriptor, cy_en_dma_trigger_type_t triggerInType) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(triggerInType)); + + descriptor->ctl = _CLR_SET_FLD32U(descriptor->ctl, CY_DMA_CTL_TR_IN_TYPE, triggerInType); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetTriggerInType +****************************************************************************//** +* +* Returns the Trigger-In-Type parameter of the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The Trigger-In-Type \ref cy_en_dma_trigger_type_t +* +*******************************************************************************/ +__STATIC_INLINE cy_en_dma_trigger_type_t Cy_DMA_Descriptor_GetTriggerInType(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + + return((cy_en_dma_trigger_type_t) _FLD2VAL(CY_DMA_CTL_TR_IN_TYPE, descriptor->ctl)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetTriggerOutType +****************************************************************************//** +* +* Sets the Trigger-Out-Type parameter for the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param triggerOutType +* The Trigger-Out-Type set for the descriptor. \ref cy_en_dma_trigger_type_t +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetTriggerOutType(cy_stc_dma_descriptor_t * descriptor, cy_en_dma_trigger_type_t triggerOutType) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(triggerOutType)); + + descriptor->ctl = _CLR_SET_FLD32U(descriptor->ctl, CY_DMA_CTL_TR_OUT_TYPE, triggerOutType); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetTriggerOutType +****************************************************************************//** +* +* Returns the Trigger-Out-Type parameter of the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The Trigger-Out-Type parameter \ref cy_en_dma_trigger_type_t. +* +*******************************************************************************/ +__STATIC_INLINE cy_en_dma_trigger_type_t Cy_DMA_Descriptor_GetTriggerOutType(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + + return((cy_en_dma_trigger_type_t) _FLD2VAL(CY_DMA_CTL_TR_OUT_TYPE, descriptor->ctl)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetDataSize +****************************************************************************//** +* +* Sets the Data Element Size parameter for the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param dataSize +* The Data Element Size \ref cy_en_dma_data_size_t +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetDataSize(cy_stc_dma_descriptor_t * descriptor, cy_en_dma_data_size_t dataSize) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L3(CY_DMA_IS_DATA_SIZE_VALID(dataSize)); + + descriptor->ctl = _CLR_SET_FLD32U(descriptor->ctl, CY_DMA_CTL_DATA_SIZE, dataSize); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetDataSize +****************************************************************************//** +* +* Returns the Data Element Size parameter of the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The Data Element Size \ref cy_en_dma_data_size_t. +* +*******************************************************************************/ +__STATIC_INLINE cy_en_dma_data_size_t Cy_DMA_Descriptor_GetDataSize(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + + return((cy_en_dma_data_size_t) _FLD2VAL(CY_DMA_CTL_DATA_SIZE, descriptor->ctl)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetSrcTransferSize +****************************************************************************//** +* +* Sets the Source Transfer Size parameter for the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param srcTransferSize +* The Source Transfer Size \ref cy_en_dma_transfer_size_t. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetSrcTransferSize(cy_stc_dma_descriptor_t * descriptor, cy_en_dma_transfer_size_t srcTransferSize) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L3(CY_DMA_IS_XFER_SIZE_VALID(srcTransferSize)); + + descriptor->ctl = _CLR_SET_FLD32U(descriptor->ctl, CY_DMA_CTL_SRC_SIZE, srcTransferSize); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetSrcTransferSize +****************************************************************************//** +* +* Returns the Source Transfer Size parameter of the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The Source Transfer Size \ref cy_en_dma_transfer_size_t. +* +*******************************************************************************/ +__STATIC_INLINE cy_en_dma_transfer_size_t Cy_DMA_Descriptor_GetSrcTransferSize(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + + return((cy_en_dma_transfer_size_t) _FLD2VAL(CY_DMA_CTL_SRC_SIZE, descriptor->ctl)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetDstTransferSize +****************************************************************************//** +* +* Sets the Destination Transfer Size parameter for the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param dstTransferSize +* The Destination Transfer Size \ref cy_en_dma_transfer_size_t. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetDstTransferSize(cy_stc_dma_descriptor_t * descriptor, cy_en_dma_transfer_size_t dstTransferSize) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L3(CY_DMA_IS_XFER_SIZE_VALID(dstTransferSize)); + + descriptor->ctl = _CLR_SET_FLD32U(descriptor->ctl, CY_DMA_CTL_DST_SIZE, dstTransferSize); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetDstTransferSize +****************************************************************************//** +* +* Returns the Destination Transfer Size parameter of the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The Destination Transfer Size \ref cy_en_dma_transfer_size_t +* +*******************************************************************************/ +__STATIC_INLINE cy_en_dma_transfer_size_t Cy_DMA_Descriptor_GetDstTransferSize(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + + return((cy_en_dma_transfer_size_t) _FLD2VAL(CY_DMA_CTL_DST_SIZE, descriptor->ctl)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetRetrigger +****************************************************************************//** +* +* Sets the retrigger value which specifies whether the controller should +* wait for the input trigger to be deactivated. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param retrigger +* The \ref cy_en_dma_retrigger_t parameter specifies whether the controller +* should wait for the input trigger to be deactivated. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetRetrigger(cy_stc_dma_descriptor_t * descriptor, cy_en_dma_retrigger_t retrigger) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L3(CY_DMA_IS_RETRIGGER_VALID(retrigger)); + + descriptor->ctl = _CLR_SET_FLD32U(descriptor->ctl, CY_DMA_CTL_RETRIG, retrigger); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetRetrigger +****************************************************************************//** +* +* Returns a value which specifies whether the controller should +* wait for the input trigger to be deactivated. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The Retrigger setting \ref cy_en_dma_retrigger_t. +* +*******************************************************************************/ +__STATIC_INLINE cy_en_dma_retrigger_t Cy_DMA_Descriptor_GetRetrigger(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + + return((cy_en_dma_retrigger_t) _FLD2VAL(CY_DMA_CTL_RETRIG, descriptor->ctl)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetDescriptorType +****************************************************************************//** +* +* Returns the descriptor's type of the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The descriptor type \ref cy_en_dma_descriptor_type_t +* +*******************************************************************************/ +__STATIC_INLINE cy_en_dma_descriptor_type_t Cy_DMA_Descriptor_GetDescriptorType(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + + return((cy_en_dma_descriptor_type_t) _FLD2VAL(CY_DMA_CTL_TYPE, descriptor->ctl)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetChannelState +****************************************************************************//** +* +* Sets the channel state on completion of the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param channelState +* The channel state \ref cy_en_dma_channel_state_t. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetChannelState(cy_stc_dma_descriptor_t * descriptor, cy_en_dma_channel_state_t channelState) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L3(CY_DMA_IS_CHANNEL_STATE_VALID(channelState)); + + descriptor->ctl = _CLR_SET_FLD32U(descriptor->ctl, CY_DMA_CTL_CH_DISABLE, channelState); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetChannelState +****************************************************************************//** +* +* Returns the channel state on completion of the specified descriptor. +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The Channel State setting \ref cy_en_dma_channel_state_t +* +*******************************************************************************/ +__STATIC_INLINE cy_en_dma_channel_state_t Cy_DMA_Descriptor_GetChannelState(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + + return((cy_en_dma_channel_state_t) _FLD2VAL(CY_DMA_CTL_CH_DISABLE, descriptor->ctl)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetXloopDataCount +****************************************************************************//** +* +* Sets the number of data elements to transfer in the X loop +* for the specified descriptor (for 1D or 2D descriptors only). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param xCount +* The number of data elements to transfer in the X loop. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetXloopDataCount(cy_stc_dma_descriptor_t * descriptor, uint32_t xCount) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L1(CY_DMA_SINGLE_TRANSFER != Cy_DMA_Descriptor_GetDescriptorType(descriptor)); + CY_ASSERT_L2(CY_DMA_IS_COUNT_VALID(xCount)); + /* Convert the data count from the user's range (1-256) into the machine range (0-255). */ + descriptor->xCtl = _CLR_SET_FLD32U(descriptor->xCtl, CY_DMA_CTL_COUNT, xCount - 1UL); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetXloopDataCount +****************************************************************************//** +* +* Returns the number of data elements for the X loop of the specified +* descriptor (for 1D or 2D descriptors only). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The number of data elements to transfer in the X loop. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_DMA_Descriptor_GetXloopDataCount(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L1(CY_DMA_SINGLE_TRANSFER != Cy_DMA_Descriptor_GetDescriptorType(descriptor)); + /* Convert the data count from the machine range (0-255) into the user's range (1-256). */ + return (_FLD2VAL(CY_DMA_CTL_COUNT, descriptor->xCtl) + 1UL); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetXloopSrcIncrement +****************************************************************************//** +* +* Sets the source increment parameter for the X loop of the specified +* descriptor (for 1D or 2D descriptors only). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param srcXincrement +* The value of the source increment. The valid range is -2048 ... 2047. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetXloopSrcIncrement(cy_stc_dma_descriptor_t * descriptor, int32_t srcXincrement) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L1(CY_DMA_SINGLE_TRANSFER != Cy_DMA_Descriptor_GetDescriptorType(descriptor)); + CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(srcXincrement)); + + descriptor->xCtl = _CLR_SET_FLD32U(descriptor->xCtl, CY_DMA_CTL_SRC_INCR, srcXincrement); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetXloopSrcIncrement +****************************************************************************//** +* +* Returns the source increment parameter for the X loop of the specified +* descriptor (for 1D or 2D descriptors only). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The value of the source increment. +* +*******************************************************************************/ +__STATIC_INLINE int32_t Cy_DMA_Descriptor_GetXloopSrcIncrement(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L1(CY_DMA_SINGLE_TRANSFER != Cy_DMA_Descriptor_GetDescriptorType(descriptor)); + + return ((int32_t) _FLD2VAL(CY_DMA_CTL_SRC_INCR, descriptor->xCtl)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetXloopDstIncrement +****************************************************************************//** +* +* Sets the destination increment parameter for the X loop for the specified +* descriptor (for 1D or 2D descriptors only). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param dstXincrement +* The value of the destination increment. The valid range is -2048 ... 2047. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetXloopDstIncrement(cy_stc_dma_descriptor_t * descriptor, int32_t dstXincrement) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L1(CY_DMA_SINGLE_TRANSFER != Cy_DMA_Descriptor_GetDescriptorType(descriptor)); + CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(dstXincrement)); + + descriptor->xCtl = _CLR_SET_FLD32U(descriptor->xCtl, CY_DMA_CTL_DST_INCR, dstXincrement); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetXloopDstIncrement +****************************************************************************//** +* +* Returns the destination increment parameter for the X loop of the specified +* descriptor (for 1D or 2D descriptors only). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The value of the destination increment. +* +*******************************************************************************/ +__STATIC_INLINE int32_t Cy_DMA_Descriptor_GetXloopDstIncrement(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L1(CY_DMA_SINGLE_TRANSFER != Cy_DMA_Descriptor_GetDescriptorType(descriptor)); + + return ((int32_t) _FLD2VAL(CY_DMA_CTL_DST_INCR, descriptor->xCtl)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetYloopDataCount +****************************************************************************//** +* +* Sets the number of data elements for the Y loop of the specified descriptor +* (for 2D descriptors only). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param yCount +* The number of X loops to execute in the Y loop. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetYloopDataCount(cy_stc_dma_descriptor_t * descriptor, uint32_t yCount) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L1(CY_DMA_2D_TRANSFER == Cy_DMA_Descriptor_GetDescriptorType(descriptor)); + CY_ASSERT_L2(CY_DMA_IS_COUNT_VALID(yCount)); + /* Convert the data count from the user's range (1-256) into the machine range (0-255). */ + descriptor->yCtl = _CLR_SET_FLD32U(descriptor->yCtl, CY_DMA_CTL_COUNT, yCount - 1UL); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetYloopDataCount +****************************************************************************//** +* +* Returns the number of X loops to execute in the Y loop of the specified +* descriptor (for 2D descriptors only). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The number of X loops to execute in the Y loop. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_DMA_Descriptor_GetYloopDataCount(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L1(CY_DMA_2D_TRANSFER == Cy_DMA_Descriptor_GetDescriptorType(descriptor)); + /* Convert the data count from the machine range (0-255) into the user's range (1-256). */ + return (_FLD2VAL(CY_DMA_CTL_COUNT, descriptor->yCtl) + 1UL); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetYloopSrcIncrement +****************************************************************************//** +* +* Sets the source increment parameter for the Y loop for the specified +* descriptor (for 2D descriptors only). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param srcYincrement +* The value of the source increment. The valid range is -2048 ... 2047. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetYloopSrcIncrement(cy_stc_dma_descriptor_t * descriptor, int32_t srcYincrement) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L1(CY_DMA_2D_TRANSFER == Cy_DMA_Descriptor_GetDescriptorType(descriptor)); + CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(srcYincrement)); + + descriptor->yCtl = _CLR_SET_FLD32U(descriptor->yCtl, CY_DMA_CTL_SRC_INCR, srcYincrement); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetYloopSrcIncrement +****************************************************************************//** +* +* Returns the source increment parameter for the outer Y of the specified +* descriptor (for 2D descriptors only). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The value of source increment. +* +*******************************************************************************/ +__STATIC_INLINE int32_t Cy_DMA_Descriptor_GetYloopSrcIncrement(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L1(CY_DMA_2D_TRANSFER == Cy_DMA_Descriptor_GetDescriptorType(descriptor)); + + return ((int32_t) _FLD2VAL(CY_DMA_CTL_SRC_INCR, descriptor->yCtl)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_SetYloopDstIncrement +****************************************************************************//** +* +* Sets the destination increment parameter for the Y loop of the specified +* descriptor (for 2D descriptors only). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \param dstYincrement +* The value of the destination increment. Valid range is -2048 ... 2047. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Descriptor_SetYloopDstIncrement(cy_stc_dma_descriptor_t * descriptor, int32_t dstYincrement) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L1(CY_DMA_2D_TRANSFER == Cy_DMA_Descriptor_GetDescriptorType(descriptor)); + CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(dstYincrement)); + + descriptor->yCtl = _CLR_SET_FLD32U(descriptor->yCtl, CY_DMA_CTL_DST_INCR, dstYincrement); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Descriptor_GetYloopDstIncrement +****************************************************************************//** +* +* Returns the destination increment parameter for the Y loop of the specified +* descriptor (for 2D descriptors only). +* +* \param descriptor +* The descriptor structure instance declared by the user/component. +* +* \return +* The value of the destination increment. +* +*******************************************************************************/ +__STATIC_INLINE int32_t Cy_DMA_Descriptor_GetYloopDstIncrement(cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(NULL != descriptor); + CY_ASSERT_L1(CY_DMA_2D_TRANSFER == Cy_DMA_Descriptor_GetDescriptorType(descriptor)); + + return ((int32_t) _FLD2VAL(CY_DMA_CTL_DST_INCR, descriptor->yCtl)); +} + + +/** \} group_dma_descriptor_functions */ + + +/** +* \addtogroup group_dma_channel_functions +* \{ +*/ + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_SetDescriptor +****************************************************************************//** +* +* Sets a descriptor as current for the specified DMA channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +* \param descriptor +* This is the descriptor to be associated with the channel. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Channel_SetDescriptor(DW_Type * base, uint32_t channel, cy_stc_dma_descriptor_t const * descriptor) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + CY_ASSERT_L1(NULL != descriptor); + + base->CH_STRUCT[channel].CH_CURR_PTR = (uint32_t)descriptor; + base->CH_STRUCT[channel].CH_IDX &= (uint32_t) ~(DW_CH_STRUCT_CH_IDX_X_IDX_Msk | DW_CH_STRUCT_CH_IDX_Y_IDX_Msk); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_Enable +****************************************************************************//** +* +* The function is used to enable a DMA channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Channel_Enable(DW_Type * base, uint32_t channel) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + + base->CH_STRUCT[channel].CH_CTL |= DW_CH_STRUCT_CH_CTL_ENABLED_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_Disable +****************************************************************************//** +* +* The function is used to disable a DMA channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Channel_Disable(DW_Type * base, uint32_t channel) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + + base->CH_STRUCT[channel].CH_CTL &= (uint32_t) ~DW_CH_STRUCT_CH_CTL_ENABLED_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_SetPriority +****************************************************************************//** +* +* The function is used to set a priority for the DMA channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +* \param priority +* The priority to be set for the DMA channel. The allowed values are 0,1,2,3. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Channel_SetPriority(DW_Type * base, uint32_t channel, uint32_t priority) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + CY_ASSERT_L2(CY_DMA_IS_PRIORITY_VALID(priority)); + + base->CH_STRUCT[channel].CH_CTL = _CLR_SET_FLD32U(base->CH_STRUCT[channel].CH_CTL, DW_CH_STRUCT_CH_CTL_PRIO, priority); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_GetPriority +****************************************************************************//** +* +* Returns the priority of the DMA channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +* \return +* The priority of the channel. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_DMA_Channel_GetPriority(DW_Type const * base, uint32_t channel) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + + return ((uint32_t) _FLD2VAL(DW_CH_STRUCT_CH_CTL_PRIO, base->CH_STRUCT[channel].CH_CTL)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_GetCurrentDescriptor +****************************************************************************//** +* +* Returns the descriptor that is active in the channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +* \return +* The pointer to the descriptor assocaited with the channel. +* +*******************************************************************************/ +__STATIC_INLINE cy_stc_dma_descriptor_t * Cy_DMA_Channel_GetCurrentDescriptor(DW_Type const * base, uint32_t channel) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + + return ((cy_stc_dma_descriptor_t*)(base->CH_STRUCT[channel].CH_CURR_PTR)); +} + + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_GetInterruptStatus +****************************************************************************//** +* +* Returns the interrupt status of the specified channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +* \return +* The status of an interrupt for the specified channel. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_DMA_Channel_GetInterruptStatus(DW_Type const * base, uint32_t channel) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + + return (base->CH_STRUCT[channel].INTR); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_GetStatus +****************************************************************************//** +* +* Returns the interrupt reason of the specified channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +* \return +* The cause \ref cy_en_dma_intr_cause_t of the interrupt. +* +*******************************************************************************/ +__STATIC_INLINE cy_en_dma_intr_cause_t Cy_DMA_Channel_GetStatus(DW_Type const * base, uint32_t channel) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + + return ((cy_en_dma_intr_cause_t) _FLD2VAL(DW_CH_STRUCT_CH_STATUS_INTR_CAUSE, base->CH_STRUCT[channel].CH_STATUS)); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_ClearInterrupt +****************************************************************************//** +* +* Clears the interrupt status of the specified channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Channel_ClearInterrupt(DW_Type * base, uint32_t channel) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + + base->CH_STRUCT[channel].INTR = CY_DMA_INTR_MASK; + (void) base->CH_STRUCT[channel].INTR; +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_SetInterrupt +****************************************************************************//** +* +* Sets the interrupt for the specified channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Channel_SetInterrupt(DW_Type * base, uint32_t channel) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + + base->CH_STRUCT[channel].INTR_SET = CY_DMA_INTR_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_GetInterruptMask +****************************************************************************//** +* +* Returns the interrupt mask value of the specified channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +* \return +* The interrupt mask value. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_DMA_Channel_GetInterruptMask(DW_Type const * base, uint32_t channel) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + + return (base->CH_STRUCT[channel].INTR_MASK); +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_SetInterruptMask +****************************************************************************//** +* +* Sets an interrupt mask value for the specified channel. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +* \param interrupt +* The interrupt mask: +* CY_DMA_INTR_MASK to enable the interrupt or 0UL to disable the interrupt. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_DMA_Channel_SetInterruptMask(DW_Type * base, uint32_t channel, uint32_t interrupt) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + CY_ASSERT_L2(CY_DMA_IS_INTR_MASK_VALID(interrupt)); + base->CH_STRUCT[channel].INTR_MASK = interrupt; +} + + +/******************************************************************************* +* Function Name: Cy_DMA_Channel_GetInterruptStatusMasked +****************************************************************************//** +* +* Returns the logical AND of the corresponding INTR and INTR_MASK fields +* in a single-load operation. +* +* \param base +* The pointer to the hardware DMA block. +* +* \param channel +* The channel number. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_DMA_Channel_GetInterruptStatusMasked(DW_Type const * base, uint32_t channel) +{ + CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel)); + + return (base->CH_STRUCT[channel].INTR_MASKED); +} + +/** \} group_dma_channel_functions */ + +/** \} group_dma_functions */ + + +/** \cond The definitions to support the backward compatibility, do not use them in new designs */ + +#if(CY_DMA_BWC) + + /* Type definitions */ + #define cy_stc_dma_chnl_config_t cy_stc_dma_channel_config_t + #define cy_stc_dma_descr_t cy_stc_dma_descriptor_t + #define cy_stc_dma_descr_config_t cy_stc_dma_descriptor_config_t + #define cy_en_dma_trig_type_t cy_en_dma_trigger_type_t + + /* Structure items */ + #define DMA_Descriptor descriptor + #define deact retrigger + #define intrType interruptType + #define chStateAtCmplt channelState + #define srcTxfrSize srcTransferSize + #define destTxfrSize dstTransferSize + #define trigoutType triggerOutType + #define triginType triggerInType + #define descrType descriptorType + #define srcAddr srcAddress + #define destAddr dstAddress + #define srcXincr srcXincrement + #define srcYincr srcYincrement + #define destXincr dstXincrement + #define destYincr dstYincrement + #define descrNext nextDescriptor + + /* Constants */ + #define CY_DMA_CH_DISABLED (CY_DMA_CHANNEL_DISABLED) + #define CY_DMA_CH_ENABLED (CY_DMA_CHANNEL_ENABLED) + + #define CY_DMA_TXFR_SIZE_DATA_SIZE (CY_DMA_TRANSFER_SIZE_DATA) + #define CY_DMA_TXFR_SIZE_WORD (CY_DMA_TRANSFER_SIZE_WORD) + + #define CY_DMA_INTR_1ELEMENT_CMPLT (CY_DMA_1ELEMENT) + #define CY_DMA_INTR_X_LOOP_CMPLT (CY_DMA_X_LOOP) + #define CY_DMA_INTR_DESCR_CMPLT (CY_DMA_DESCR) + #define CY_DMA_INTR_DESCRCHAIN_CMPLT (CY_DMA_DESCR_CHAIN) + + #define CY_DMA_TRIGOUT_1ELEMENT_CMPLT (CY_DMA_1ELEMENT) + #define CY_DMA_TRIGOUT_X_LOOP_CMPLT (CY_DMA_X_LOOP) + #define CY_DMA_TRIGOUT_DESCR_CMPLT (CY_DMA_DESCR) + #define CY_DMA_TRIGOUT_DESCRCHAIN_CMPLT (CY_DMA_DESCR_CHAIN) + + #define CY_DMA_TRIGIN_1ELEMENT (CY_DMA_1ELEMENT) + #define CY_DMA_TRIGIN_XLOOP (CY_DMA_X_LOOP) + #define CY_DMA_TRIGIN_DESCR (CY_DMA_DESCR) + #define CY_DMA_TRIGIN_DESCRCHAIN (CY_DMA_DESCR_CHAIN) + + #define CY_DMA_INVALID_INPUT_PARAMETERS (CY_DMA_BAD_PARAM) + + #define CY_DMA_RETDIG_IM (CY_DMA_RETRIG_IM) + #define CY_DMA_RETDIG_4CYC (CY_DMA_RETRIG_4CYC) + #define CY_DMA_RETDIG_16CYC (CY_DMA_RETRIG_16CYC) + + /* Descriptor structure items */ + #define DESCR_CTL ctl + #define DESCR_SRC src + #define DESCR_DST dst + #define DESCR_X_CTL xCtl + #define DESCR_Y_CTL yCtl + #define DESCR_NEXT_PTR nextPtr + + /* Descriptor structure bit-fields */ + #define DW_DESCR_STRUCT_DESCR_CTL_WAIT_FOR_DEACT_Pos 0UL + #define DW_DESCR_STRUCT_DESCR_CTL_WAIT_FOR_DEACT_Msk 0x3UL + #define DW_DESCR_STRUCT_DESCR_CTL_INTR_TYPE_Pos 2UL + #define DW_DESCR_STRUCT_DESCR_CTL_INTR_TYPE_Msk 0xCUL + #define DW_DESCR_STRUCT_DESCR_CTL_TR_OUT_TYPE_Pos 4UL + #define DW_DESCR_STRUCT_DESCR_CTL_TR_OUT_TYPE_Msk 0x30UL + #define DW_DESCR_STRUCT_DESCR_CTL_TR_IN_TYPE_Pos 6UL + #define DW_DESCR_STRUCT_DESCR_CTL_TR_IN_TYPE_Msk 0xC0UL + #define DW_DESCR_STRUCT_DESCR_CTL_CH_DISABLE_Pos 24UL + #define DW_DESCR_STRUCT_DESCR_CTL_CH_DISABLE_Msk 0x1000000UL + #define DW_DESCR_STRUCT_DESCR_CTL_SRC_TRANSFER_SIZE_Pos 26UL + #define DW_DESCR_STRUCT_DESCR_CTL_SRC_TRANSFER_SIZE_Msk 0x4000000UL + #define DW_DESCR_STRUCT_DESCR_CTL_DST_TRANSFER_SIZE_Pos 27UL + #define DW_DESCR_STRUCT_DESCR_CTL_DST_TRANSFER_SIZE_Msk 0x8000000UL + #define DW_DESCR_STRUCT_DESCR_CTL_DATA_SIZE_Pos 28UL + #define DW_DESCR_STRUCT_DESCR_CTL_DATA_SIZE_Msk 0x30000000UL + #define DW_DESCR_STRUCT_DESCR_CTL_DESCR_TYPE_Pos 30UL + #define DW_DESCR_STRUCT_DESCR_CTL_DESCR_TYPE_Msk 0xC0000000UL + #define DW_DESCR_STRUCT_DESCR_SRC_SRC_ADDR_Pos 0UL + #define DW_DESCR_STRUCT_DESCR_SRC_SRC_ADDR_Msk 0xFFFFFFFFUL + #define DW_DESCR_STRUCT_DESCR_DST_DST_ADDR_Pos 0UL + #define DW_DESCR_STRUCT_DESCR_DST_DST_ADDR_Msk 0xFFFFFFFFUL + #define DW_DESCR_STRUCT_DESCR_X_CTL_SRC_X_INCR_Pos 0UL + #define DW_DESCR_STRUCT_DESCR_X_CTL_SRC_X_INCR_Msk 0xFFFUL + #define DW_DESCR_STRUCT_DESCR_X_CTL_DST_X_INCR_Pos 12UL + #define DW_DESCR_STRUCT_DESCR_X_CTL_DST_X_INCR_Msk 0xFFF000UL + #define DW_DESCR_STRUCT_DESCR_X_CTL_X_COUNT_Pos 24UL + #define DW_DESCR_STRUCT_DESCR_X_CTL_X_COUNT_Msk 0xFF000000UL + #define DW_DESCR_STRUCT_DESCR_Y_CTL_SRC_Y_INCR_Pos 0UL + #define DW_DESCR_STRUCT_DESCR_Y_CTL_SRC_Y_INCR_Msk 0xFFFUL + #define DW_DESCR_STRUCT_DESCR_Y_CTL_DST_Y_INCR_Pos 12UL + #define DW_DESCR_STRUCT_DESCR_Y_CTL_DST_Y_INCR_Msk 0xFFF000UL + #define DW_DESCR_STRUCT_DESCR_Y_CTL_Y_COUNT_Pos 24UL + #define DW_DESCR_STRUCT_DESCR_Y_CTL_Y_COUNT_Msk 0xFF000000UL + #define DW_DESCR_STRUCT_DESCR_NEXT_PTR_ADDR_Pos 2UL + #define DW_DESCR_STRUCT_DESCR_NEXT_PTR_ADDR_Msk 0xFFFFFFFCUL + + /* Functions */ + #define Cy_DMA_GetActiveChnl Cy_DMA_GetActiveChannel + #define Cy_DMA_GetActiveSrcAddr Cy_DMA_GetActiveSrcAddress + #define Cy_DMA_GetActiveDstAddr Cy_DMA_GetActiveDstAddress + #define Cy_DMA_Descr_Init Cy_DMA_Descriptor_Init + #define Cy_DMA_Descr_DeInit Cy_DMA_Descriptor_DeInit + #define Cy_DMA_Descr_SetSrcAddr Cy_DMA_Descriptor_SetSrcAddress + #define Cy_DMA_Descr_SetDestAddr Cy_DMA_Descriptor_SetDstAddress + #define Cy_DMA_Descr_SetNxtDescr Cy_DMA_Descriptor_SetNextDescriptor + #define Cy_DMA_Descr_SetIntrType Cy_DMA_Descriptor_SetInterruptType + #define Cy_DMA_Descr_SetTrigInType Cy_DMA_Descriptor_SetTriggerInType + #define Cy_DMA_Descr_SetTrigOutType Cy_DMA_Descriptor_SetTriggerOutType + #define Cy_DMA_Chnl_Init Cy_DMA_Channel_Init + #define Cy_DMA_Chnl_DeInit Cy_DMA_Channel_DeInit + #define Cy_DMA_Chnl_SetDescr Cy_DMA_Channel_SetDescriptor + #define Cy_DMA_Chnl_Enable Cy_DMA_Channel_Enable + #define Cy_DMA_Chnl_Disable Cy_DMA_Channel_Disable + #define Cy_DMA_Chnl_GetCurrentDescr Cy_DMA_Channel_GetCurrentDescriptor + #define Cy_DMA_Chnl_SetPriority Cy_DMA_Channel_SetPriority + #define Cy_DMA_Chnl_GetPriority Cy_DMA_Channel_GetPriority + #define Cy_DMA_Chnl_GetInterruptStatus Cy_DMA_Channel_GetInterruptStatus + #define Cy_DMA_Chnl_GetInterruptCause Cy_DMA_Channel_GetStatus + #define Cy_DMA_Chnl_ClearInterrupt Cy_DMA_Channel_ClearInterrupt + #define Cy_DMA_Chnl_SetInterrupt Cy_DMA_Channel_SetInterrupt + #define Cy_DMA_Chnl_GetInterruptMask Cy_DMA_Channel_GetInterruptMask + #define Cy_DMA_Chnl_GetInterruptStatusMasked Cy_DMA_Channel_GetInterruptStatusMasked + #define Cy_DMA_Chnl_SetInterruptMask(base, channel) (Cy_DMA_Channel_SetInterruptMask(base, channel, CY_DMA_INTR_MASK)) + + +/******************************************************************************* +* Function Name: Cy_DMA_Descr_SetTxfrWidth +****************************************************************************//** +* This is a legacy API function, it is left here just for the backward compatibility +* Do not use it in new designs. +*******************************************************************************/ + __STATIC_INLINE void Cy_DMA_Descr_SetTxfrWidth(cy_stc_dma_descr_t * descriptor, + uint32_t dataElementSize, + uint32_t srcTxfrWidth, + uint32_t dstTxfrWidth) + { + uint32_t regValue; + regValue = descriptor->ctl & ((uint32_t)(~(DW_DESCR_STRUCT_DESCR_CTL_DATA_SIZE_Msk | + DW_DESCR_STRUCT_DESCR_CTL_SRC_TRANSFER_SIZE_Msk | + DW_DESCR_STRUCT_DESCR_CTL_DST_TRANSFER_SIZE_Msk))); + + descriptor->ctl = regValue | + _VAL2FLD(DW_DESCR_STRUCT_DESCR_CTL_DATA_SIZE, dataElementSize) | + _VAL2FLD(DW_DESCR_STRUCT_DESCR_CTL_SRC_TRANSFER_SIZE, srcTxfrWidth) | + _VAL2FLD(DW_DESCR_STRUCT_DESCR_CTL_DST_TRANSFER_SIZE, dstTxfrWidth); + } + +#endif /* CY_DMA_BWC */ + +/** \endcond */ + + +#if defined(__cplusplus) +} +#endif + +#endif /* (CY_DMA_H) */ + +/** \} group_dma */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/efuse/cy_efuse.c b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/efuse/cy_efuse.c new file mode 100644 index 0000000000..0892255e78 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/efuse/cy_efuse.c @@ -0,0 +1,225 @@ +/***************************************************************************//** +* \file cy_efuse.c +* \version 1.0 +* +* \brief +* Provides API implementation of the eFuse driver. +* +******************************************************************************** +* \copyright +* Copyright 2017-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include "cy_efuse.h" +#include "ipc/cy_ipc_drv.h" + +/** \cond INTERNAL */ +#define CY_EFUSE_OPCODE_SUCCESS (0xA0000000UL) /**< The command completed with no errors */ +#define CY_EFUSE_OPCODE_STS_Msk (0xF0000000UL) /**< The status mask of the SROM API return value */ +#define CY_EFUSE_OPCODE_INV_PROT (0xF0000001UL) /**< The API is not available in the current protection state */ +#define CY_EFUSE_OPCODE_INV_ADDR (0xF0000002UL) /**< An attempt to read byte from the out-of-bond or protected eFuse region */ +#define CY_EFUSE_OPCODE_READ_FUSE_BYTE (0x03000000UL) /**< The SROM API opcode for Read fuse byte operation */ +#define CY_EFUSE_OPCODE_OFFSET_Pos (8UL) /**< A fuse byte offset position in an opcode */ +#define CY_EFUSE_OPCODE_DATA_Msk (0xFFUL) /**< The mask for extracting data from the SROM API return value */ +#define CY_EFUSE_IPC_STRUCT (Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) /**< IPC structure to be used */ +#define CY_EFUSE_IPC_NOTIFY_STRUCT0 (0x1UL << CY_IPC_INTR_SYSCALL1) /**< IPC notify bit for IPC_STRUCT0 (dedicated to System Call) */ +/** \endcond */ + +static volatile uint32_t opcode; + +static cy_en_efuse_status_t ProcessOpcode(void); + +/******************************************************************************* +* Function Name: Cy_EFUSE_GetEfuseBit +****************************************************************************//** +* +* Reports the current state of a given eFuse bit-number. Consult the device TRM +* to determine the target fuse bit number. +* +* \note An attempt to read an eFuse data from a protected memory region +* will generate a HardFault. +* +* \param bitNum +* The number of the bit to read. The valid range of the bit number is +* from 0 to EFUSE_EFUSE_NR * 32 * 8 - 1 where: +* - EFUSE_EFUSE_NR is number of efuse macros in the selected device series, +* - 32 is a number of fuse bytes in one efuse macro, +* - 8 is a number of fuse bits in the byte. +* +* The EFUSE_EFUSE_NR macro is defined in the series-specific header file, e.g +* \e \/devices/psoc6/psoc63/include/psoc63_config.\e h +* +* \param bitVal +* The pointer to the location to store the bit value. +* +* \return +* \ref cy_en_efuse_status_t +* +* \funcusage +* The example below shows how to read device life-cycle register bits in +* PSoC 6: +* \snippet eFuse_v1_0_sut_00.cydsn/main_cm0p.c SNIPPET_EFUSE_READ_BIT +* +*******************************************************************************/ +cy_en_efuse_status_t Cy_EFUSE_GetEfuseBit(uint32_t bitNum, bool *bitVal) +{ + cy_en_efuse_status_t result = CY_EFUSE_BAD_PARAM; + + if (bitVal != NULL) + { + uint32_t offset = bitNum / CY_EFUSE_BITS_PER_BYTE; + uint8_t byteVal; + *bitVal = false; + + /* Read the eFuse byte */ + result = Cy_EFUSE_GetEfuseByte(offset, &byteVal); + + if (result == CY_EFUSE_SUCCESS) + { + uint32_t bitPos = bitNum % CY_EFUSE_BITS_PER_BYTE; + /* Extract the bit from the byte */ + *bitVal = (((byteVal >> bitPos) & 0x01U) != 0U); + } + } + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_EFUSE_GetEfuseByte +****************************************************************************//** +* +* Reports the current state of the eFuse byte. +* If the offset parameter is beyond the available quantities, +* zeroes will be stored to the byteVal parameter. Consult the device TRM +* to determine the target fuse byte offset. +* +* \note An attempt to read an eFuse data from a protected memory region +* will generate a HardFault. +* +* \param offset +* The offset of the byte to read. The valid range of the byte offset is +* from 0 to EFUSE_EFUSE_NR * 32 - 1 where: +* - EFUSE_EFUSE_NR is a number of efuse macros in the selected device series, +* - 32 is a number of fuse bytes in one efuse macro. +* +* The EFUSE_EFUSE_NR macro is defined in the series-specific header file, e.g +* \e \/devices/psoc6/psoc63/include/psoc63_config.\e h +* +* \param byteVal +* The pointer to the location to store eFuse data. +* +* \return +* \ref cy_en_efuse_status_t +* +* \funcusage +* The example below shows how to read a device life-cycle stage register in +* PSoC 6: +* \snippet eFuse_v1_0_sut_00.cydsn/main_cm0p.c SNIPPET_EFUSE_READ_LIFECYCLE +* +*******************************************************************************/ +cy_en_efuse_status_t Cy_EFUSE_GetEfuseByte(uint32_t offset, uint8_t *byteVal) +{ + cy_en_efuse_status_t result = CY_EFUSE_BAD_PARAM; + + if (byteVal != NULL) + { + /* Prepare opcode before calling the SROM API */ + opcode = CY_EFUSE_OPCODE_READ_FUSE_BYTE | (offset << CY_EFUSE_OPCODE_OFFSET_Pos); + + /* Send the IPC message */ + if (Cy_IPC_Drv_SendMsgPtr(CY_EFUSE_IPC_STRUCT, CY_EFUSE_IPC_NOTIFY_STRUCT0, (void*)&opcode) == CY_IPC_DRV_SUCCESS) + { + /* Wait until the IPC structure is locked */ + while(Cy_IPC_Drv_IsLockAcquired(CY_EFUSE_IPC_STRUCT) != false) + { + } + + /* The result of the SROM API call is returned to the opcode variable */ + if ((opcode & CY_EFUSE_OPCODE_STS_Msk) == CY_EFUSE_OPCODE_SUCCESS) + { + *byteVal = (uint8_t)(opcode & CY_EFUSE_OPCODE_DATA_Msk); + result = CY_EFUSE_SUCCESS; + } + else + { + result = ProcessOpcode(); + *byteVal = 0U; + } + } + else + { + result = CY_EFUSE_IPC_BUSY; + } + } + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_EFUSE_GetExternalStatus +****************************************************************************//** +* +* This function handles the case where a module such as a security image captures +* a system call from this driver and reports its own status or error code, +* for example, protection violation. In that case, a function from this +* driver returns an unknown error (see \ref cy_en_efuse_status_t). After receipt +* of an unknown error, the user may call this function to get the status +* of the capturing module. +* +* The user is responsible for parsing the content of the returned value +* and casting it to the appropriate enumeration. +* +* \return +* The error code of the previous efuse operation. +* +*******************************************************************************/ +uint32_t Cy_EFUSE_GetExternalStatus(void) +{ + return (opcode); +} + + +/******************************************************************************* +* Function Name: ProcessOpcode +****************************************************************************//** +* +* Converts System Call returns to the eFuse driver return defines. If +* an unknown error was returned, the error code can be accessed via the +* Cy_EFUSE_GetExternalStatus() function. +* +* \param opcode The value returned by a System Call. +* +* \return +* \ref cy_en_efuse_status_t +* +*******************************************************************************/ +static cy_en_efuse_status_t ProcessOpcode(void) +{ + cy_en_efuse_status_t result; + + switch(opcode) + { + case CY_EFUSE_OPCODE_INV_PROT : + { + result = CY_EFUSE_INVALID_PROTECTION; + break; + } + case CY_EFUSE_OPCODE_INV_ADDR : + { + result = CY_EFUSE_INVALID_FUSE_ADDR; + break; + } + default : + { + result = CY_EFUSE_ERR_UNC; + break; + } + } + + return (result); +} + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/efuse/cy_efuse.h b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/efuse/cy_efuse.h new file mode 100644 index 0000000000..4c8a12763a --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/efuse/cy_efuse.h @@ -0,0 +1,178 @@ +/***************************************************************************//** +* \file cy_efuse.h +* \version 1.0 +* +* Provides the API declarations of the eFuse driver. +* +******************************************************************************** +* \copyright +* Copyright 2017-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#if !defined(CY_EFUSE_H) +#define CY_EFUSE_H + +/** +* \defgroup group_efuse Electronic Fuses (eFuse) +* \{ +* +* Electronic Fuses (eFuses) - non-volatile memory whose +* each bit is one-time programmable (OTP). One eFuse macro consists of +* 256 bits (32 * 8). The PSoC devices have up to 16 eFuse macros; consult the +* device-specific datasheet to determine how many macros for a particular device. +* These are implemented as a regular Advanced High-performance Bus (AHB) +* peripheral with the following characteristics: +* - eFuses are used to control the device life-cycle stage (NORMAL, SECURE, +* and SECURE_WITH_DEBUG) and the protection settings; +* - eFuse memory can be programmed (eFuse bit value changed from '0' to '1') +* only once; if an eFuse bit is blown, it cannot be cleared again; +* - programming fuses requires the associated I/O supply to be at a specific +* level: the VDDIO0 (or VDDIO if only one VDDIO is present in the package) +* supply of the device should be set to 2.5 V (±5%); +* - fuses are programmed via the PSoC Programmer tool that parses the hex file +* and extracts the necessary information; the fuse data must be located at the +* dedicated section in the hex file. For more details see +* [PSoC 6 Programming Specifications](http://www.cypress.com/documentation/programming-specifications/psoc-6-programming-specifications) +* +* \section group_efuse_configuration Configuration Considerations +* +* Efuse memory can have different organization depending on the selected device. +* Consult the device TRM to determine the efuse memory organization and +* registers bitmap on the selected device. +* +* To read fuse data use the driver [functions] (\ref group_efuse_functions). +* +* To blow fuses, define a data structure of \ref cy_stc_efuse_data_t type in the +* firmware. The structure must be placed in the special memory section, for +* this use a compiler attribute. +* Each byte in the structure corresponds to the one fuse bit in the +* device. It allows the PSoC Programmer tool to distinguish bytes that are +* being set from bytes we don't care about or with unknown values. Fill the +* structure with the following values: +* - 0x00 - Not blown; +* - 0x01 - Blown; +* - 0xFF - Ignore. +* +* After the structure is defined and the values are set, build the project and +* download the firmware. To blow fuses, the firmware must be downloaded by the +* PSoC Programmer tool. Before you download firmware, ensure that the +* conditions from the PSoC 6 Programming Specification are met. +* +* The code below shows an example of the efuse data structure +* definition to blow SECURE bit of the life-cycle stage register. +* The bits to blow are set to the EFUSE_STATE_SET value. +* \snippet eFuse_v1_0_sut_00.cydsn/main_cm0p.c SNIPPET_EFUSE_DATA_STC +* +* \section group_efuse_more_information More Information +* +* Refer to the technical reference manual (TRM) and the device datasheet. +* +* \section group_efuse_MISRA MISRA-C Compliance +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
MISRA RuleRule Class (Required/Advisory)Rule DescriptionDescription of Deviation(s)
2.3RThe character sequence // shall not be used within a comment.The comments provide a useful WEB link to the documentation.
11.5RDangerous pointer cast results in loss of volatile qualification.The removal of the volatile qualification inside the function has no +* side effects.
+* +* \section group_efuse_changelog Changelog +* +* +* +* +* +* +* +*
VersionChangesReason for Change
1.0Initial version
+* +* \defgroup group_efuse_macros Macros +* \defgroup group_efuse_functions Functions +* \defgroup group_efuse_data_structures Data Structures +* \defgroup group_efuse_enumerated_types Enumerated Types +*/ + +#include "cy_device_headers.h" +#include "syslib/cy_syslib.h" + +/*************************************** +* Macro Definitions +***************************************/ +/** +* \addtogroup group_efuse_macros +* \{ +*/ + +/** The driver major version */ +#define CY_EFUSE_DRV_VERSION_MAJOR 1 +/** The driver minor version */ +#define CY_EFUSE_DRV_VERSION_MINOR 0 +/** The eFuse driver identifier */ +#define CY_EFUSE_ID (CY_PDL_DRV_ID(0x1AUL)) +/** The number of bits in the byte */ +#define CY_EFUSE_BITS_PER_BYTE (8UL) +/** \} group_efuse_macros */ + +/*************************************** +* Enumerated Types +***************************************/ +/** +* \addtogroup group_efuse_enumerated_types +* \{ +*/ +/** This enum has the return values of the eFuse driver */ +typedef enum +{ + CY_EFUSE_SUCCESS = 0x00UL, /**< Success */ + CY_EFUSE_INVALID_PROTECTION = CY_EFUSE_ID | CY_PDL_STATUS_ERROR | 0x01UL, /**< Invalid access in the current protection state */ + CY_EFUSE_INVALID_FUSE_ADDR = CY_EFUSE_ID | CY_PDL_STATUS_ERROR | 0x02UL, /**< Invalid eFuse address */ + CY_EFUSE_BAD_PARAM = CY_EFUSE_ID | CY_PDL_STATUS_ERROR | 0x03UL, /**< One or more invalid parameters */ + CY_EFUSE_IPC_BUSY = CY_EFUSE_ID | CY_PDL_STATUS_ERROR | 0x04UL, /**< The IPC structure is already locked by another process */ + CY_EFUSE_ERR_UNC = CY_EFUSE_ID | CY_PDL_STATUS_ERROR | 0xFFUL /**< Unknown error code. See Cy_EFUSE_GetExternalStatus() */ +} cy_en_efuse_status_t; + +/** \} group_efuse_data_structure */ + +#if defined(__cplusplus) +extern "C" { +#endif +/*************************************** +* Function Prototypes +***************************************/ + +/** +* \addtogroup group_efuse_functions +* \{ +*/ +cy_en_efuse_status_t Cy_EFUSE_GetEfuseBit(uint32_t bitNum, bool *bitVal); +cy_en_efuse_status_t Cy_EFUSE_GetEfuseByte(uint32_t offset, uint8_t *byteVal); +uint32_t Cy_EFUSE_GetExternalStatus(void); +/** \} group_efuse_functions */ + +#if defined(__cplusplus) +} +#endif + + +#endif /* #if !defined(CY_EFUSE_H) */ + +/** \} group_efuse */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/flash/cy_flash.c b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/flash/cy_flash.c new file mode 100644 index 0000000000..84434d6ded --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/flash/cy_flash.c @@ -0,0 +1,1271 @@ +/***************************************************************************//** +* \file cy_flash.c +* \version 3.0 +* +* \brief +* Provides the public functions for the API for the PSoC 6 Flash Driver. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ +#include "flash/cy_flash.h" +#include "sysclk/cy_sysclk.h" +#include "sysint/cy_sysint.h" +#include "ipc/cy_ipc_drv.h" +#include "ipc/cy_ipc_sema.h" +#include "ipc/cy_ipc_pipe.h" + +/*************************************** +* Data Structure definitions +***************************************/ + +/* Flash driver context */ +typedef struct +{ + uint32_t opcode; /**< Specifies the code of flash operation */ + uint32_t arg1; /**< Specifies the configuration of flash operation */ + uint32_t arg2; /**< Specifies the configuration of flash operation */ + uint32_t arg3; /**< Specifies the configuration of flash operation */ +} cy_stc_flash_context_t; + + +/*************************************** +* Macro definitions +***************************************/ + +/** \cond INTERNAL */ +/** Set SROM API in blocking mode */ +#define CY_FLASH_BLOCKING_MODE ((0x01UL) << 8UL) +/** Set SROM API in non blocking mode */ +#define CY_FLASH_NON_BLOCKING_MODE (0UL) + +/** SROM API flash region ID shift for flash row information */ +#define CY_FLASH_REGION_ID_SHIFT (16U) +#define CY_FLASH_REGION_ID_MASK (3U) +#define CY_FLASH_ROW_ID_MASK (0xFFFFU) +/** SROM API flash region IDs */ +#define CY_FLASH_REGION_ID_MAIN (0UL) +#define CY_FLASH_REGION_ID_EM_EEPROM (1UL) +#define CY_FLASH_REGION_ID_SFLASH (2UL) + +/** SROM API opcode mask */ +#define CY_FLASH_OPCODE_Msk ((0xFFUL) << 24UL) +/** SROM API opcode for flash write operation */ +#define CY_FLASH_OPCODE_WRITE_ROW ((0x05UL) << 24UL) +/** SROM API opcode for flash program operation */ +#define CY_FLASH_OPCODE_PROGRAM_ROW ((0x06UL) << 24UL) +/** SROM API opcode for row erase operation */ +#define CY_FLASH_OPCODE_ERASE_ROW ((0x1CUL) << 24UL) +/** SROM API opcode for flash checksum operation */ +#define CY_FLASH_OPCODE_CHECKSUM ((0x0BUL) << 24UL) +/** SROM API opcode for flash hash operation */ +#define CY_FLASH_OPCODE_HASH ((0x0DUL) << 24UL) +/** SROM API flash row shift for flash checksum operation */ +#define CY_FLASH_OPCODE_CHECKSUM_ROW_SHIFT (8UL) +/** SROM API flash row shift for flash checksum operation */ +#define CY_FLASH_OPCODE_CHECKSUM_REGION_SHIFT (22UL) +/** SROM API flash data size parameter for flash write operation */ +#define CY_FLASH_CONFIG_DATASIZE (CPUSS_FLASHC_PA_SIZE_LOG2 - 1UL) +/** Data to be programmed to flash is located in SRAM memory region */ +#define CY_FLASH_DATA_LOC_SRAM (0x100UL) +/** SROM API flash verification option for flash write operation */ +#define CY_FLASH_CONFIG_VERIFICATION_EN ((0x01UL) << 16u) + +/** Command completed with no errors */ +#define CY_FLASH_ROMCODE_SUCCESS (0xA0000000UL) +/** Invalid device protection state */ +#define CY_FLASH_ROMCODE_INVALID_PROTECTION (0xF0000001UL) +/** Invalid flash page latch address */ +#define CY_FLASH_ROMCODE_INVALID_FM_PL (0xF0000003UL) +/** Invalid flash address */ +#define CY_FLASH_ROMCODE_INVALID_FLASH_ADDR (0xF0000004UL) +/** Row is write protected */ +#define CY_FLASH_ROMCODE_ROW_PROTECTED (0xF0000005UL) +/** Comparison between Page Latches and FM row failed */ +#define CY_FLASH_ROMCODE_PL_ROW_COMP_FA (0xF0000022UL) +/** Command in progress; no error */ +#define CY_FLASH_ROMCODE_IN_PROGRESS_NO_ERROR (0xA0000009UL) +/** Flash operation is successfully initiated */ +#define CY_FLASH_IS_OPERATION_STARTED (0x00000010UL) +/** Flash is under operation */ +#define CY_FLASH_IS_BUSY (0x00000040UL) +/** IPC structure is already locked by another process */ +#define CY_FLASH_IS_IPC_BUSY (0x00000080UL) +/** Input parameters passed to Flash API are not valid */ +#define CY_FLASH_IS_INVALID_INPUT_PARAMETERS (0x00000100UL) + +/** Result mask */ +#define CY_FLASH_RESULT_MASK (0x0FFFFFFFUL) +/** Error shift */ +#define CY_FLASH_ERROR_SHIFT (28UL) +/** No error */ +#define CY_FLASH_ERROR_NO_ERROR (0xAUL) + +/** CM4 Flash Proxy address */ +#define CY_FLASH_CM4_FLASH_PROXY_ADDR (*(Cy_Flash_Proxy *)(0x00000D1CUL)) +typedef cy_en_flashdrv_status_t (*Cy_Flash_Proxy)(cy_stc_flash_context_t *context); + +/** IPC notify bit for IPC_STRUCT0 (dedicated to flash operation) */ +#define CY_FLASH_IPC_NOTIFY_STRUCT0 (0x1UL << CY_IPC_INTR_SYSCALL1) + +/** Disable delay */ +#define CY_FLASH_NO_DELAY (0U) + +#if !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) + /** Number of ticks to wait 1 uS */ + #define CY_FLASH_TICKS_FOR_1US (8U) + /** Slow control register */ + #define CY_FLASH_TST_DDFT_SLOW_CTL_REG (*(reg32 *) 0x40260108U) + /** Slow control register */ + #define CY_FLASH_TST_DDFT_FAST_CTL_REG (*(reg32 *) 0x40260104U) + /** Define to set the IMO to perform a delay after the flash operation started */ + #define CY_FLASH_TST_DDFT_SLOW_CTL_MASK (0x00001F1EUL) + /** Fast control register */ + #define CY_FLASH_TST_DDFT_FAST_CTL_MASK (62U) + /** Slow output register - output disabled */ + #define CY_FLASH_CLK_OUTPUT_DISABLED (0U) + + /* The default delay time value */ + #define CY_FLASH_DEFAULT_DELAY (150UL) + /* Calculates the time in microseconds to wait for the number of the CM0P ticks */ + #define CY_FLASH_DELAY_CORRECTIVE(ticks) ((((uint32)Cy_SysClk_ClkPeriGetDivider() + 1UL) * \ + (Cy_SysClk_ClkSlowGetDivider() + 1UL) * (ticks) * 1000UL)\ + / ((uint32_t)cy_Hfclk0FreqHz / 1000UL)) + + /* Number of the CM0P ticks for StartProgram function delay corrective time */ + #define CY_FLASH_START_PROGRAM_DELAY_TICKS (6000UL) + /* Delay time for StartProgram function in us */ + #define CY_FLASH_START_PROGRAM_DELAY_TIME (900UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_PROGRAM_DELAY_TICKS)) + /* Number of the CM0P ticks for StartErase function delay corrective time */ + #define CY_FLASH_START_ERASE_DELAY_TICKS (9500UL) + /* Delay time for StartErase function in us */ + #define CY_FLASH_START_ERASE_DELAY_TIME (2200UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_ERASE_DELAY_TICKS)) + /* Number of the CM0P ticks for StartWrite function delay corrective time */ + #define CY_FLASH_START_WRITE_DELAY_TICKS (19000UL) + /* Delay time for StartWrite function in us */ + #define CY_FLASH_START_WRITE_DELAY_TIME (9800UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_WRITE_DELAY_TICKS)) + + /** Delay time for Start Write function in us with corrective time */ + #define CY_FLASH_START_WRITE_DELAY (CY_FLASH_START_WRITE_DELAY_TIME) + /** Delay time for Start Program function in us with corrective time */ + #define CY_FLASH_START_PROGRAM_DELAY (CY_FLASH_START_PROGRAM_DELAY_TIME) + /** Delay time for Start Erase function in uS with corrective time */ + #define CY_FLASH_START_ERASE_DELAY (CY_FLASH_START_ERASE_DELAY_TIME) + + #define CY_FLASH_ENTER_WAIT_LOOP (0xFFU) + #define CY_FLASH_IPC_CLIENT_ID (2U) + + /** Semaphore number reserved for flash driver */ + #define CY_FLASH_WAIT_SEMA (0UL) + /* Semaphore check timeout (in tries) */ + #define CY_FLASH_SEMA_WAIT_MAX_TRIES (150000UL) + + typedef struct + { + uint8_t clientID; + uint8_t pktType; + uint16_t intrRelMask; + } cy_flash_notify_t; + + static void Cy_Flash_NotifyHandler(uint32_t * msgPtr); + static void Cy_Flash_RAMDelay(uint32_t microseconds); + + #if (CY_CPU_CORTEX_M0P) + #define IS_CY_PIPE_FREE(...) (!Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_CYPIPE_EP1))) + #define NOTIFY_PEER_CORE(a) Cy_IPC_Pipe_SendMessage(CY_IPC_EP_CYPIPE_CM4_ADDR, CY_IPC_EP_CYPIPE_CM0_ADDR, (a), NULL) + #else + #define IS_CY_PIPE_FREE(...) (!Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_CYPIPE_EP0))) + #define NOTIFY_PEER_CORE(a) Cy_IPC_Pipe_SendMessage(CY_IPC_EP_CYPIPE_CM0_ADDR, CY_IPC_EP_CYPIPE_CM4_ADDR, (a), NULL) + #endif + + #if (CY_CPU_CORTEX_M4) + static void Cy_Flash_ResumeIrqHandler(void); + #endif +#else /* !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */ + /** Delay time for Start Write function in us with corrective time */ + #define CY_FLASH_START_WRITE_DELAY (CY_FLASH_NO_DELAY) + /** Delay time for Start Program function in us with corrective time */ + #define CY_FLASH_START_PROGRAM_DELAY (CY_FLASH_NO_DELAY) + /** Delay time fot Start Erase function in uS with corrective time */ + #define CY_FLASH_START_ERASE_DELAY (CY_FLASH_NO_DELAY) +#endif /* !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */ +/** \endcond */ + + +/* Static functions */ +static bool Cy_Flash_BoundsCheck(uint32_t flashAddr); +static uint32_t Cy_Flash_GetRowNum(uint32_t flashAddr); +static cy_en_flashdrv_status_t Cy_Flash_ProcessOpcode(uint32_t opcode); +static cy_en_flashdrv_status_t Cy_Flash_OperationStatus(void); +static cy_en_flashdrv_status_t Cy_Flash_SendCmd(uint32_t mode, uint32_t microseconds); + +static volatile cy_stc_flash_context_t flashContext; + +#if !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) + /******************************************************************************* + * Function Name: Cy_Flash_NotifyHandler + ****************************************************************************//** + * + * This is the interrupt service routine for the pipe notifications. + * + *******************************************************************************/ + typedef struct + { + uint32_t maxSema; /* Maximum semaphores in system */ + uint32_t *arrayPtr; /* Pointer to semaphores array */ + } cy_stc_ipc_sema_t; + + #if defined (__ICCARM__) + #pragma diag_suppress=Ta023 + __ramfunc + #else + CY_SECTION(".cy_ramfunc") + #endif + static void Cy_Flash_NotifyHandler(uint32_t * msgPtr) + { + uint32_t intr; + static uint32_t semaIndex; + static uint32_t semaMask; + static volatile uint32_t *semaPtr; + static cy_stc_ipc_sema_t *semaStruct; + + cy_flash_notify_t *ipcMsgPtr = (cy_flash_notify_t *)msgPtr; + + if (CY_FLASH_ENTER_WAIT_LOOP == ipcMsgPtr->pktType) + { + intr = Cy_SysLib_EnterCriticalSection(); + + /* Get pointer to structure */ + semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(Cy_IPC_Drv_GetIpcBaseAddress( CY_IPC_CHAN_SEMA)); + + /* Get the index into the semaphore array and calculate the mask */ + semaIndex = CY_FLASH_WAIT_SEMA / CY_IPC_SEMA_PER_WORD; + semaMask = (uint32_t)(1ul << (CY_FLASH_WAIT_SEMA - (semaIndex * CY_IPC_SEMA_PER_WORD) )); + semaPtr = &semaStruct->arrayPtr[semaIndex]; + + /* Notification to the Flash driver to start the current operation */ + *semaPtr |= semaMask; + + /* Check a notification from other core to end of waiting */ + while (((*semaPtr) & semaMask) != 0ul) + { + } + + Cy_SysLib_ExitCriticalSection(intr); + } + } + #if defined (__ICCARM__) + #pragma diag_default=Ta023 + #endif +#endif + +/******************************************************************************* +* Function Name: Cy_Flash_Init +****************************************************************************//** +* +* Initiates all needed prerequisites to support flash erase/write. +* Should be called from each core. +* +* Requires a call to Cy_IPC_SystemSemaInit() and Cy_IPC_SystemPipeInit() functions +* before use. +* +* This function is called in the SystemInit() function, for proper flash write +* and erase operations. If the default startup file is not used, or the function +* SystemInit() is not called in your project, call the following three functions +* prior to executing any flash or EmEEPROM write or erase operations: +* -# Cy_IPC_SystemSemaInit() +* -# Cy_IPC_SystemPipeInit() +* -# Cy_Flash_Init() +* +*******************************************************************************/ +void Cy_Flash_Init(void) +{ + #if !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) + #if (CY_CPU_CORTEX_M4) + cy_stc_sysint_t flashIntConfig = + { + cpuss_interrupt_fm_IRQn, /* .intrSrc */ + 0 /* .intrPriority */ + }; + + (void)Cy_SysInt_Init(&flashIntConfig, &Cy_Flash_ResumeIrqHandler); + NVIC_EnableIRQ(flashIntConfig.intrSrc); + #endif + + (void)Cy_IPC_Pipe_RegisterCallback(CY_IPC_EP_CYPIPE_ADDR, &Cy_Flash_NotifyHandler, + (uint32_t)CY_FLASH_IPC_CLIENT_ID); + #endif +} + +/******************************************************************************* +* Function Name: Cy_Flash_SendCmd +****************************************************************************//** +* +* Sends a command to the SROM via the IPC channel. The function is placed to the +* SRAM memory to guarantee successful operation. After an IPC message is sent, +* the function waits for a defined time before exiting the function. +* +* \param mode +* Sets the blocking or non-blocking Flash operation. +* +* \param microseconds +* The number of microseconds to wait before exiting the functions +* in range 0-65535 us. +* +* \return Returns the status of the Flash operation, +* see \ref cy_en_flashdrv_status_t. +* +*******************************************************************************/ +#if defined(CY_DEVICE_PSOC6ABLE2) \ + && !defined(CY_PSOC6ABLE2_REV_0A_SUPPORT_DISABLE) \ + && !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) + #if defined (__ICCARM__) + #pragma diag_suppress=Ta023 + __ramfunc + #else + CY_SECTION(".cy_ramfunc") + #endif +#endif +static cy_en_flashdrv_status_t Cy_Flash_SendCmd(uint32_t mode, uint32_t microseconds) +{ + cy_en_flashdrv_status_t result = CY_FLASH_DRV_IPC_BUSY; + IPC_STRUCT_Type *ipcBase = Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL); + +#if !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) + + uint32_t semaTryCount = 0uL; + uint32_t intr; + + CY_ALIGN(4) static cy_flash_notify_t ipcWaitMessage = + { + /* .clientID */ CY_FLASH_IPC_CLIENT_ID, + /* .pktType */ CY_FLASH_ENTER_WAIT_LOOP, + /* .intrRelMask */ 0 + }; + + #if (CY_CPU_CORTEX_M0P) + bool isCM4Powered = (CY_SYS_CM4_STATUS_ENABLED == Cy_SysGetCM4Status()); + + if (!isCM4Powered) + { + result = CY_FLASH_DRV_SUCCESS; + } + else + { + #endif + if (IS_CY_PIPE_FREE()) + { + if (CY_IPC_SEMA_STATUS_LOCKED != Cy_IPC_Sema_Status(CY_FLASH_WAIT_SEMA)) + { + if (CY_IPC_PIPE_SUCCESS == NOTIFY_PEER_CORE(&ipcWaitMessage)) + { + /* Wait for SEMA lock by peer core */ + while ((CY_IPC_SEMA_STATUS_LOCKED != Cy_IPC_Sema_Status(CY_FLASH_WAIT_SEMA)) && ((semaTryCount < CY_FLASH_SEMA_WAIT_MAX_TRIES))) + { + /* check for timeout (as maximum tries count) */ + ++semaTryCount; + } + + if (semaTryCount < CY_FLASH_SEMA_WAIT_MAX_TRIES) + { + result = CY_FLASH_DRV_SUCCESS; + } + } + } + } + #if (CY_CPU_CORTEX_M0P) + } + #endif + + if (CY_FLASH_DRV_SUCCESS == result) + { + /* Notifier is ready, start of the operation */ + intr = Cy_SysLib_EnterCriticalSection(); + +#endif /* !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */ + + /* Tries to acquire the IPC structure and pass the arguments to SROM API */ + if (Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL), CY_FLASH_IPC_NOTIFY_STRUCT0, + (void*)&flashContext) == CY_IPC_DRV_SUCCESS) + { + if (mode == CY_FLASH_NON_BLOCKING_MODE) + { + #if !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) + Cy_Flash_RAMDelay(microseconds); + #endif + + /* The Flash operation is successfully initiated */ + result = CY_FLASH_DRV_OPERATION_STARTED; + } + else + { + while (0u != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, ipcBase->LOCK_STATUS)) + { + /* Polls whether the IPC is released and the Flash operation is performed */ + } + + result = Cy_Flash_OperationStatus(); + } + } + else + { + /* The IPC structure is already locked by another process */ + result = CY_FLASH_DRV_IPC_BUSY; + } + +#if !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) + #if (CY_CPU_CORTEX_M0P) + if (isCM4Powered) + { + #endif + while (CY_IPC_SEMA_SUCCESS != Cy_IPC_Sema_Clear(CY_FLASH_WAIT_SEMA, true)) + { + /* Clear SEMA lock */ + } + #if (CY_CPU_CORTEX_M0P) + } + #endif + + Cy_SysLib_ExitCriticalSection(intr); + /* End of the flash operation */ + } +#endif /* !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */ + + return (result); +} +#if defined (__ICCARM__) + #pragma diag_default=Ta023 +#endif + + +#if !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) + /******************************************************************************* + * Function Name: Cy_Flash_RAMDelay + ****************************************************************************//** + * + * Wait for a defined time in the SRAM memory region. + * + * \param microseconds + * Delay time in microseconds in range 0-65535 us. + * + *******************************************************************************/ + #if defined (__ICCARM__) + #pragma diag_suppress=Ta023 + __ramfunc + #else + CY_SECTION(".cy_ramfunc") + #endif + static void Cy_Flash_RAMDelay(uint32_t microseconds) + { + uint32_t ticks = (microseconds & 0xFFFFUL) * CY_FLASH_TICKS_FOR_1US; + if (ticks != CY_FLASH_NO_DELAY) + { + CY_FLASH_TST_DDFT_FAST_CTL_REG = CY_FLASH_TST_DDFT_FAST_CTL_MASK; + CY_FLASH_TST_DDFT_SLOW_CTL_REG = CY_FLASH_TST_DDFT_SLOW_CTL_MASK; + + SRSS->CLK_OUTPUT_SLOW = _VAL2FLD(SRSS_CLK_OUTPUT_SLOW_SLOW_SEL0, CY_SYSCLK_MEAS_CLK_IMO) | + _VAL2FLD(SRSS_CLK_OUTPUT_SLOW_SLOW_SEL1, CY_FLASH_CLK_OUTPUT_DISABLED); + + /* Load the down-counter without status bit value */ + SRSS->CLK_CAL_CNT1 = _VAL2FLD(SRSS_CLK_CAL_CNT1_CAL_COUNTER1, ticks); + + /* Make sure that the counter is started */ + ticks = _FLD2VAL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS->CLK_CAL_CNT1); + + while (0UL == _FLD2VAL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS->CLK_CAL_CNT1)) + { + /* Wait until the counter stops counting */ + } + } + } + #if defined (__ICCARM__) + #pragma diag_default=Ta023 + #endif + + #if (CY_CPU_CORTEX_M4) + + /* Based on bookmark codes of mxs40srompsoc BROS,002-03298 */ + #define CY_FLASH_PROGRAM_ROW_BOOKMARK (0x00000001UL) + #define CY_FLASH_ERASE_ROW_BOOKMARK (0x00000002UL) + #define CY_FLASH_WRITE_ROW_ERASE_BOOKMARK (0x00000003UL) + #define CY_FLASH_WRITE_ROW_PROGRAM_BOOKMARK (0x00000004UL) + + /* Number of the CM0P ticks for function delay corrective time at final stage */ + #define CY_FLASH_START_PROGRAM_FINAL_DELAY_TICKS (1000UL) + #define CY_FLASH_PROGRAM_ROW_DELAY (130UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_PROGRAM_FINAL_DELAY_TICKS)) + #define CY_FLASH_ERASE_ROW_DELAY (130UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_PROGRAM_FINAL_DELAY_TICKS)) + #define CY_FLASH_WRITE_ROW_ERASE_DELAY (130UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_PROGRAM_FINAL_DELAY_TICKS)) + #define CY_FLASH_WRITE_ROW_PROGRAM_DELAY (130UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_PROGRAM_FINAL_DELAY_TICKS)) + + + /******************************************************************************* + * Function Name: Cy_Flash_ResumeIrqHandler + ****************************************************************************//** + * + * This is the interrupt service routine to make additional processing of the + * flash operations resume phase. + * + *******************************************************************************/ + #if defined (__ICCARM__) + #pragma diag_suppress=Ta023 + __ramfunc + #else + CY_SECTION(".cy_ramfunc") + #endif + static void Cy_Flash_ResumeIrqHandler(void) + { + IPC_STRUCT_Type *ipcBase = Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_CYPIPE_EP0); + + uint32_t bookmark; + bookmark = FLASHC->FM_CTL.BOOKMARK & 0xffffUL; + + uint32_t cm0s = CPUSS->CM0_STATUS; + + switch (bookmark) + { + case CY_FLASH_PROGRAM_ROW_BOOKMARK: + if (cm0s == (CPUSS_CM0_STATUS_SLEEPING_Msk | CPUSS_CM0_STATUS_SLEEPDEEP_Msk)) + { + ipcBase->NOTIFY = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, (1UL << CY_IPC_INTR_CYPIPE_EP0)); + } + Cy_Flash_RAMDelay(CY_FLASH_PROGRAM_ROW_DELAY); + break; + case CY_FLASH_ERASE_ROW_BOOKMARK: + if (cm0s == (CPUSS_CM0_STATUS_SLEEPING_Msk | CPUSS_CM0_STATUS_SLEEPDEEP_Msk)) + { + ipcBase->NOTIFY = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, (1UL << CY_IPC_INTR_CYPIPE_EP0)); + } + Cy_Flash_RAMDelay(CY_FLASH_ERASE_ROW_DELAY); /* Delay when erase row is finished */ + break; + case CY_FLASH_WRITE_ROW_ERASE_BOOKMARK: + if (cm0s == (CPUSS_CM0_STATUS_SLEEPING_Msk | CPUSS_CM0_STATUS_SLEEPDEEP_Msk)) + { + ipcBase->NOTIFY = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, (1UL << CY_IPC_INTR_CYPIPE_EP0)); + } + Cy_Flash_RAMDelay(CY_FLASH_WRITE_ROW_ERASE_DELAY); /* Delay when erase phase for row is finished */ + break; + case CY_FLASH_WRITE_ROW_PROGRAM_BOOKMARK: + if (cm0s == (CPUSS_CM0_STATUS_SLEEPING_Msk | CPUSS_CM0_STATUS_SLEEPDEEP_Msk)) + { + ipcBase->NOTIFY = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, (1UL << CY_IPC_INTR_CYPIPE_EP0)); + } + Cy_Flash_RAMDelay(CY_FLASH_WRITE_ROW_PROGRAM_DELAY); + break; + default: + break; + } + } + #if defined (__ICCARM__) + #pragma diag_default=Ta023 + #endif + #endif /* (CY_CPU_CORTEX_M4) */ +#endif /* !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */ + + +/******************************************************************************* +* Function Name: Cy_Flash_EraseRow +****************************************************************************//** +* +* This function erases a single row of flash. Reports success or +* a reason for failure. Does not return until the Write operation is +* complete. Returns immediately and reports a \ref CY_FLASH_DRV_IPC_BUSY error in +* the case when another process is writing to flash or erasing the row. +* +* User firmware should not enter the Hibernate or Deep-Sleep mode until flash +* Erase is complete. +* For all safe execution conditions see \ref group_flash_configuration +* documentation section. +* +* \param rowAddr Address of the flash row. +* Address must match row start address otherwise API returns \ref +* CY_FLASH_DRV_INVALID_INPUT_PARAMETERS status. The number of the flash rows +* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. +* The Read-while-Write violation occurs when the flash read operation is +* initiated in the same flash sector where the flash write operation is +* performing. Refer to the device datasheet for the details. +* +* \return Returns the status of the Flash operation, +* see \ref cy_en_flashdrv_status_t. +* +*******************************************************************************/ +cy_en_flashdrv_status_t Cy_Flash_EraseRow(uint32_t rowAddr) +{ + cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; + + /* Prepares arguments to be passed to SROM API */ + if (Cy_Flash_BoundsCheck(rowAddr) != false) + { + SystemCoreClockUpdate(); + + flashContext.opcode = CY_FLASH_OPCODE_ERASE_ROW | CY_FLASH_BLOCKING_MODE; + flashContext.arg1 = rowAddr; + flashContext.arg2 = 0UL; + flashContext.arg3 = 0UL; + + result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY); + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_ProgramRow +****************************************************************************//** +* +* This function writes an array of data to a single row of flash. Before calling +* this function, the target flash region must be erased by the +* Cy_Flash_StartErase() or Cy_Flash_EraseRow() function. +* +* Reports success or a reason for failure. Does not return until the Program +* operation is complete. Returns immediately and reports a +* \ref CY_FLASH_DRV_IPC_BUSY error in the case when another process is writing +* to flash. +* +* User firmware should not enter the Hibernate or Deep-sleep mode until flash +* Program is complete. +* For all safe execution conditions see \ref group_flash_configuration +* documentation section. +* +* Data to be programmed must be located in the SRAM memory region. +* \note Before reading data from previously programmed/erased flash rows, the +* user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer() +* function. +* +* \param rowAddr Address of the flash row. +* Address must match row start address otherwise API returns \ref +* CY_FLASH_DRV_INVALID_INPUT_PARAMETERS status. The number of the flash rows +* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. +* The Read-while-Write violation occurs when the flash read operation is +* initiated in the same flash sector where the flash write operation is +* performing. Refer to the device datasheet for the details. +* +* \param data The pointer to the data which has to be written to flash. The size +* of the data array must be equal to the flash row size. The flash row size for +* the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to +* the device datasheet for the details. +* +* \return Returns the status of the Flash operation, +* see \ref cy_en_flashdrv_status_t. +* +*******************************************************************************/ +cy_en_flashdrv_status_t Cy_Flash_ProgramRow(uint32_t rowAddr, const uint32_t* data) +{ + cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; + + /* Checks whether the input parameters are valid */ + if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data)) + { + SystemCoreClockUpdate(); + + /* Prepares arguments to be passed to SROM API */ + flashContext.opcode = CY_FLASH_OPCODE_PROGRAM_ROW | CY_FLASH_BLOCKING_MODE; + flashContext.arg1 = CY_FLASH_CONFIG_DATASIZE | CY_FLASH_DATA_LOC_SRAM; + flashContext.arg2 = rowAddr; + flashContext.arg3 = (uint32_t)data; + + result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_PROGRAM_DELAY); + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_WriteRow +****************************************************************************//** +* +* This function writes an array of data to a single row of flash. This is done +* in two steps - erase and then program flash row with the input data. +* Reports success or a reason for failure. Does not return until the Write +* operation is complete. +* Returns immediately and reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case +* when another process is writing to flash. +* +* User firmware should not enter the Hibernate or Deep-sleep mode until flash +* Write is complete. +* For all safe execution conditions see \ref group_flash_configuration +* documentation section. +* +* Data to be programmed must be located in the SRAM memory region. +* \note Before reading data from previously programmed/erased flash rows, the +* user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer() +* function. +* +* \param rowAddr Address of the flash row. +* Address must match row start address otherwise API returns \ref +* CY_FLASH_DRV_INVALID_INPUT_PARAMETERS status. The number of the flash rows +* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. +* The Read-while-Write violation occurs when the flash read operation is +* initiated in the same flash sector where the flash write operation is +* performing. Refer to the device datasheet for the details. +* +* \param data The pointer to the data which has to be written to flash. The size +* of the data array must be equal to the flash row size. The flash row size for +* the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to +* the device datasheet for the details. +* +* \return Returns the status of the Flash operation, +* see \ref cy_en_flashdrv_status_t. +* +*******************************************************************************/ +cy_en_flashdrv_status_t Cy_Flash_WriteRow(uint32_t rowAddr, const uint32_t* data) +{ + cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; + + /* Checks whether the input parameters are valid */ + if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data)) + { + SystemCoreClockUpdate(); + + /* Prepares arguments to be passed to SROM API */ + flashContext.opcode = CY_FLASH_OPCODE_WRITE_ROW | CY_FLASH_BLOCKING_MODE; + flashContext.arg1 = 0UL; + flashContext.arg2 = rowAddr; + flashContext.arg3 = (uint32_t)data; + + result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_WRITE_DELAY); + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_StartWrite +****************************************************************************//** +* +* Erase flash row and performs programming of the row with the input data. +* Returns immediately and reports a successful start or reason for failure. +* Reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case when another process is +* writing to flash. +* +* User firmware should not enter the Hibernate or Deep-Sleep mode until flash +* Write is complete. +* For all safe execution conditions see \ref group_flash_configuration +* documentation section. +* +* Data to be programmed must be located in the SRAM memory region. +* \note Before reading data from previously programmed/erased flash rows, the +* user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer() +* function. +* +* \param rowAddr Address of the flash row. +* Address must match row start address otherwise API returns \ref +* CY_FLASH_DRV_INVALID_INPUT_PARAMETERS status. The number of the flash rows +* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. +* The Read-while-Write violation occurs when the flash read operation is +* initiated in the same flash sector where the flash write operation is +* performing. Refer to the device datasheet for the details. +* +* \param data The pointer to the data to be written to flash. The size +* of the data array must be equal to the flash row size. The flash row size for +* the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to +* the device datasheet for the details. +* +* \return Returns the status of the Flash operation, +* see \ref cy_en_flashdrv_status_t. +* +*******************************************************************************/ +cy_en_flashdrv_status_t Cy_Flash_StartWrite(uint32_t rowAddr, const uint32_t* data) +{ + cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; + + /* Checks whether the input parameters are valid */ + if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data)) + { + result = Cy_Flash_StartErase(rowAddr); + + if (CY_FLASH_DRV_OPERATION_STARTED == result) + { + /* Polls whether the IPC is released and the Flash operation is performed */ + do + { + result = Cy_Flash_OperationStatus(); + } + while (result == CY_FLASH_DRV_OPCODE_BUSY); + + if (CY_FLASH_DRV_SUCCESS == result) + { + result = Cy_Flash_StartProgram(rowAddr, data); + } + } + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_IsOperationComplete +****************************************************************************//** +* +* Reports a successful operation result, reason of failure or busy status +* ( \ref CY_FLASH_DRV_OPCODE_BUSY ). +* +* \return Returns the status of the Flash operation (see \ref cy_en_flashdrv_status_t). +* +*******************************************************************************/ +cy_en_flashdrv_status_t Cy_Flash_IsOperationComplete(void) +{ + return (Cy_Flash_OperationStatus()); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_StartErase +****************************************************************************//** +* +* Starts erasing a single row of flash. Returns immediately and reports a +* successful start or reason for failure. Reports a \ref CY_FLASH_DRV_IPC_BUSY +* error in the case when IPC structure is locked by another process. +* +* User firmware should not enter the Hibernate or Deep-Sleep mode until +* flash Erase is complete. +* For all safe execution conditions see \ref group_flash_configuration +* documentation section. +* +* \note Before reading data from previously programmed/erased flash rows, the +* user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer() +* function. +* +* \param rowAddr Address of the flash row. +* Address must match row start address otherwise API returns \ref +* CY_FLASH_DRV_INVALID_INPUT_PARAMETERS status. The number of the flash rows +* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. +* The Read-while-Write violation occurs when the flash read operation is +* initiated in the same flash sector where the flash erase operation is +* performing. Refer to the device datasheet for the details. +* +* \return Returns the status of the Flash operation, +* see \ref cy_en_flashdrv_status_t. +* +*******************************************************************************/ +cy_en_flashdrv_status_t Cy_Flash_StartErase(uint32_t rowAddr) +{ + cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; + + if (Cy_Flash_BoundsCheck(rowAddr) != false) + { + SystemCoreClockUpdate(); + + /* Prepares arguments to be passed to SROM API */ + flashContext.opcode = CY_FLASH_OPCODE_ERASE_ROW; + flashContext.arg1 = rowAddr; + flashContext.arg2 = 0UL; + flashContext.arg3 = 0UL; + result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY); + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_StartProgram +****************************************************************************//** +* +* Starts writing an array of data to a single row of flash. Before calling this +* function, the target flash region must be erased by the Cy_Flash_StartErase() +* or Cy_Flash_EraseRow() function. +* +* Returns immediately and reports a successful start or reason for failure. +* Reports a \ref CY_FLASH_DRV_IPC_BUSY error if another process is writing +* to flash. +* +* The user firmware should not enter Hibernate or Deep-Sleep mode until flash +* Program is complete. +* For all safe execution conditions see \ref group_flash_configuration +* documentation section. +* +* Data to be programmed must be located in the SRAM memory region. +* \note Before reading data from previously programmed/erased flash rows, the +* user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer() +* function. +* +* \param rowAddr Address of the flash row. +* Address must match row start address otherwise API returns \ref +* CY_FLASH_DRV_INVALID_INPUT_PARAMETERS status. The number of the flash rows +* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. +* The Read-while-Write violation occurs when the Flash Write operation is +* performing. Refer to the device datasheet for the details. +* +* \param data The pointer to the data to be written to flash. The size +* of the data array must be equal to the flash row size. The flash row size for +* the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to +* the device datasheet for the details. +* +* \return Returns the status of the Flash operation, +* see \ref cy_en_flashdrv_status_t. +* +*******************************************************************************/ +cy_en_flashdrv_status_t Cy_Flash_StartProgram(uint32_t rowAddr, const uint32_t* data) +{ + cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; + + if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data)) + { + SystemCoreClockUpdate(); + + /* Prepares arguments to be passed to SROM API */ + flashContext.opcode = CY_FLASH_OPCODE_PROGRAM_ROW | CY_FLASH_NON_BLOCKING_MODE; + flashContext.arg1 = CY_FLASH_CONFIG_DATASIZE | CY_FLASH_DATA_LOC_SRAM; + flashContext.arg2 = rowAddr; + flashContext.arg3 = (uint32_t)data; + + result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_PROGRAM_DELAY); + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_RowChecksum +****************************************************************************//** +* +* Returns a checksum value of the specified flash row. +* +* \note Now Cy_Flash_RowChecksum() requires the row address (rowAddr) +* as a parameter. In previous versions of the driver, this function used +* the row number (rowNum) for this parameter. +* +* \param rowAddr Address of the flash row. +* Address must match row start address otherwise API returns \ref +* CY_FLASH_DRV_INVALID_INPUT_PARAMETERS status. The number of the flash rows +* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. +* +* \param checksumPtr The pointer to the address where checksum is to be stored +* +* \return Returns the status of the Flash operation. +* +*******************************************************************************/ +cy_en_flashdrv_status_t Cy_Flash_RowChecksum (uint32_t rowAddr, uint32_t* checksumPtr) +{ + cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; + uint32_t resTmp; + uint32_t rowID; + + /* Checks whether the input parameters are valid */ + if ((Cy_Flash_BoundsCheck(rowAddr)) && (NULL != checksumPtr)) + { + rowID = Cy_Flash_GetRowNum(rowAddr); + + /* Prepares arguments to be passed to SROM API */ + flashContext.opcode = CY_FLASH_OPCODE_CHECKSUM | + (((rowID >> CY_FLASH_REGION_ID_SHIFT) & CY_FLASH_REGION_ID_MASK) << CY_FLASH_OPCODE_CHECKSUM_REGION_SHIFT) | + ((rowID & CY_FLASH_ROW_ID_MASK) << CY_FLASH_OPCODE_CHECKSUM_ROW_SHIFT); + + /* Tries to acquire the IPC structure and pass the arguments to SROM API */ + if (Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL), CY_FLASH_IPC_NOTIFY_STRUCT0, + (void*)&flashContext) == CY_IPC_DRV_SUCCESS) + { + /* Polls whether IPC is released and the Flash operation is performed */ + while (Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) != false) + { + /* Wait till IPC is released */ + } + + resTmp = flashContext.opcode; + + if ((resTmp >> CY_FLASH_ERROR_SHIFT) == CY_FLASH_ERROR_NO_ERROR) + { + result = CY_FLASH_DRV_SUCCESS; + *checksumPtr = flashContext.opcode & CY_FLASH_RESULT_MASK; + } + else + { + result = Cy_Flash_ProcessOpcode(flashContext.opcode); + } + } + else + { + /* The IPC structure is already locked by another process */ + result = CY_FLASH_DRV_IPC_BUSY; + } + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_CalculateHash +****************************************************************************//** +* +* Returns a hash value of the specified region of flash. Hash calculation +* algorithm provided by SROM code. +* +* \param data Start the data address. API returns invalid address status if +* called on out of bound FLASH region. +* +* \param numberOfBytes The hash value is calculated for the number of bytes +* after the start data address (0 - 1 byte, 1- 2 bytes etc). +* +* \param hashPtr The pointer to the address where hash is to be stored +* +* \return Returns the status of the Flash operation. +* +*******************************************************************************/ +cy_en_flashdrv_status_t Cy_Flash_CalculateHash (const uint32_t* data, uint32_t numberOfBytes, uint32_t* hashPtr) +{ + cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; + volatile uint32_t resTmp; + + /* Checks whether the input parameters are valid */ + if ((data != NULL) && (0ul != numberOfBytes)) + { + /* Prepares arguments to be passed to SROM API */ + flashContext.opcode = CY_FLASH_OPCODE_HASH; + flashContext.arg1 = (uint32_t)data; + flashContext.arg2 = numberOfBytes; + + /* Tries to acquire the IPC structure and pass the arguments to SROM API */ + if (Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL), CY_FLASH_IPC_NOTIFY_STRUCT0, + (void*)&flashContext) == CY_IPC_DRV_SUCCESS) + { + /* Polls whether IPC is released and the Flash operation is performed */ + while (Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) != false) + { + /* Wait till IPC is released */ + } + + resTmp = flashContext.opcode; + + if ((resTmp >> CY_FLASH_ERROR_SHIFT) == CY_FLASH_ERROR_NO_ERROR) + { + result = CY_FLASH_DRV_SUCCESS; + *hashPtr = flashContext.opcode & CY_FLASH_RESULT_MASK; + } + else + { + result = Cy_Flash_ProcessOpcode(flashContext.opcode); + } + } + else + { + /* The IPC structure is already locked by another process */ + result = CY_FLASH_DRV_IPC_BUSY; + } + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_GetRowNum +****************************************************************************//** +* +* Returns flash region ID and row number of the Flash address. +* +* \param flashAddr Address to be checked +* +* \return +* The valid return value is encoded as follows (or 0xFFFFFFFFUL for invalid +* address) +* +*
Field Value +*
Flash row number [15:0] bits +*
Flash region ID [31:16] bits +*
+* +*******************************************************************************/ +static uint32_t Cy_Flash_GetRowNum(uint32_t flashAddr) +{ + uint32_t result; + + if ((flashAddr >= CY_FLASH_BASE) && (flashAddr < (CY_FLASH_BASE + CY_FLASH_SIZE))) + { + result = (CY_FLASH_REGION_ID_MAIN << CY_FLASH_REGION_ID_SHIFT) | + ((flashAddr - CY_FLASH_BASE) / CY_FLASH_SIZEOF_ROW); + } + else + if ((flashAddr >= CY_EM_EEPROM_BASE) && (flashAddr < (CY_EM_EEPROM_BASE + CY_EM_EEPROM_SIZE))) + { + result = (CY_FLASH_REGION_ID_EM_EEPROM << CY_FLASH_REGION_ID_SHIFT) | + ((flashAddr - CY_EM_EEPROM_BASE) / CY_FLASH_SIZEOF_ROW); + } + else + if ((flashAddr >= SFLASH_BASE) && (flashAddr < (SFLASH_BASE + SFLASH_SECTION_SIZE))) + { + result = (CY_FLASH_REGION_ID_SFLASH << CY_FLASH_REGION_ID_SHIFT) | + ((flashAddr - SFLASH_BASE) / CY_FLASH_SIZEOF_ROW); + } + else + { + result = 0xFFFFFFFFUL; + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_BoundsCheck +****************************************************************************//** +* +* Returns false if Flash address is out of boundary, otherwise returns true. +* +* \param flashAddr Address to be checked +* +* \return false - out of bound, true - in flash bounds +* +*******************************************************************************/ +static bool Cy_Flash_BoundsCheck(uint32_t flashAddr) +{ + return ((Cy_Flash_GetRowNum(flashAddr) != 0xFFFFFFFFUL) && ((flashAddr % CY_FLASH_SIZEOF_ROW) == 0UL)); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_ProcessOpcode +****************************************************************************//** +* +* Converts System Call returns to the Flash driver return defines. +* +* \param opcode The value returned by the System Call. +* +* \return Flash driver return. +* +*******************************************************************************/ +static cy_en_flashdrv_status_t Cy_Flash_ProcessOpcode(uint32_t opcode) +{ + cy_en_flashdrv_status_t result; + + switch (opcode) + { + case 0UL: + { + result = CY_FLASH_DRV_SUCCESS; + break; + } + case CY_FLASH_ROMCODE_SUCCESS: + { + result = CY_FLASH_DRV_SUCCESS; + break; + } + case CY_FLASH_ROMCODE_INVALID_PROTECTION: + { + result = CY_FLASH_DRV_INV_PROT; + break; + } + case CY_FLASH_ROMCODE_INVALID_FM_PL: + { + result = CY_FLASH_DRV_INVALID_FM_PL; + break; + } + case CY_FLASH_ROMCODE_INVALID_FLASH_ADDR: + { + result = CY_FLASH_DRV_INVALID_FLASH_ADDR; + break; + } + case CY_FLASH_ROMCODE_ROW_PROTECTED: + { + result = CY_FLASH_DRV_ROW_PROTECTED; + break; + } + case CY_FLASH_ROMCODE_IN_PROGRESS_NO_ERROR: + { + result = CY_FLASH_DRV_PROGRESS_NO_ERROR; + break; + } + case (uint32_t)CY_FLASH_DRV_INVALID_INPUT_PARAMETERS: + { + result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; + break; + } + case CY_FLASH_IS_OPERATION_STARTED : + { + result = CY_FLASH_DRV_OPERATION_STARTED; + break; + } + case CY_FLASH_IS_BUSY : + { + result = CY_FLASH_DRV_OPCODE_BUSY; + break; + } + case CY_FLASH_IS_IPC_BUSY : + { + result = CY_FLASH_DRV_IPC_BUSY; + break; + } + case CY_FLASH_IS_INVALID_INPUT_PARAMETERS : + { + result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; + break; + } + default: + { + result = CY_FLASH_DRV_ERR_UNC; + break; + } + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_OperationStatus +****************************************************************************//** +* +* Checks the status of the Flash Operation, and returns it. +* +* \return Returns the status of the Flash operation +* (see \ref cy_en_flashdrv_status_t). +* +*******************************************************************************/ +static cy_en_flashdrv_status_t Cy_Flash_OperationStatus(void) +{ + cy_en_flashdrv_status_t result = CY_FLASH_DRV_OPCODE_BUSY; + + /* Checks if the IPC structure is not locked */ + if (Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) == false) + { + /* The result of SROM API calling is returned to the driver context */ + result = Cy_Flash_ProcessOpcode(flashContext.opcode); + + /* Clear pre-fetch cache after flash operation */ +#if (CY_CPU_CORTEX_M0P) + FLASHC->CM0_CA_CMD = FLASHC_CM0_CA_CMD_INV_Msk; +#else + FLASHC->CM4_CA_CMD = FLASHC_CM4_CA_CMD_INV_Msk; +#endif /* (CY_CPU_CORTEX_M0P) */ + + while ((FLASHC->CM0_CA_CMD != 0U) || (FLASHC->CM4_CA_CMD != 0U)) + { + } + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_Flash_GetExternalStatus +****************************************************************************//** +* +* This function handles the case where a module such as security image captures +* a system call from this driver and reports its own status or error code, +* for example protection violation. In that case, a function from this +* driver returns an unknown error (see \ref cy_en_flashdrv_status_t). After receipt +* of an unknown error, the user may call this function to get the status +* of the capturing module. +* +* The user is responsible for parsing the content of the returned value +* and casting it to the appropriate enumeration. +* +* \return +* The error code that was stored in the opcode variable. +* +*******************************************************************************/ +uint32_t Cy_Flash_GetExternalStatus(void) +{ + return (flashContext.opcode); +} + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/flash/cy_flash.h b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/flash/cy_flash.h new file mode 100644 index 0000000000..cd4255a6c1 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/flash/cy_flash.h @@ -0,0 +1,405 @@ +/***************************************************************************//** +* \file cy_flash.h +* \version 3.0 +* +* Provides the API declarations of the Flash driver. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#if !defined(CY_FLASH_H) +#define CY_FLASH_H + +/** +* \defgroup group_flash Flash System Routine (Flash) +* \{ +* Internal flash memory programming +* +* Flash memory in PSoC devices provides non-volatile storage for user firmware, +* user configuration data, and bulk data storage. +* +* Flash operations are implemented as system calls. System calls are executed +* out of SROM in the privileged mode of operation. Users have no access to read +* or modify the SROM code. The driver API requests the system call by acquiring +* the Inter-processor communication (IPC) and writing the SROM function opcode +* and parameters to its input registers. As a result, an NMI interrupt is invoked +* and the requested SROM API is executed. The operation status is returned to the +* driver context and a release interrupt is triggered. +* +* Writing to flash can take up to 20 milliseconds. During this time, +* the device should not be reset (including XRES pin, software reset, and +* watchdog) or unexpected changes may be made to portions of the flash. +* Also, the low-voltage detect circuits should be configured to generate an +* interrupt instead of a reset. +* +* A Read while Write violation occurs when a flash Read operation is initiated +* in the same or neighboring flash sector where the flash Write, Erase, or +* Program operation is working. This violation may cause a HardFault exception. +* To avoid the Read while Write violation, the user must carefully split the +* Read and Write operation on flash sectors which are not neighboring, +* considering both cores in the multi-processor device. The flash is divided +* into four equal sectors. You may edit the linker script to place the code +* into neighboring sectors. For example, use sectors number 0 and 1 for code +* and sectors 2 and 3 for data storage. +* +* \section group_flash_configuration Configuration Considerations +* +* \subsection group_flash_config_intro Introduction: +* The PSoC 6 MCU user-programmable Flash consists of: +* - Up to four User Flash sectors (0 through 3) - 256KB each. +* - EEPROM emulation sector - 32KB. +* +* Write operations are performed on a per-sector basis and may be done as +* Blocking or Partially Blocking, defined as follows: +* +* \subsection group_flash_config_blocking Blocking: +* In this case, the entire Flash block is not available for the duration of the +* Write (up to 20 milliseconds). Therefore, no Flash accesses +* (from any Bus Master) can occur during that time. CPU execution can be +* performed from SRAM. All pre-fetching must be disabled. Application code +* execution from Flash is blocked for the Flash Write duration for both cores. +* +* \subsection group_flash_config_block_const Constraints for Blocking Flash operations: +* -# During write to flash, the device should not be reset (including XRES pin, +* software reset, and watchdog), or unexpected changes may be made to portions +* of the flash. +* -# The low-voltage detect circuits should be configured to generate an +* interrupt instead of a reset. +* -# Flash write operation is allowed only in one of the following CM4 states: +* -# CM4 is Active and initialized:
+* call \ref Cy_SysEnableCM4 "Cy_SysEnableCM4(CY_CORTEX_M4_APPL_ADDR)". +* Note: If desired user may put CM4 core in Deep Sleep any time +* after calling Cy_SysEnableCM4(). +* -# CM4 is Off:
+* call Cy_SysDisableCM4(). Note: In this state Debug mode is not +* supported. +* . +* -# Flash write cannot be performed in ULP (core voltage 0.9V) mode. +* -# Interrupts must be enabled on both active cores. Do not enter a critical +* section during flash operation. +* -# User must guarantee that system pipe interrupts (IPC interrupts 3 and 4) +* have the highest priority, or at least that pipe interrupts are not +* interrupted or in a pending state for more than 700 µs. +* -# User must guarantee that during flash write operation no flash read +* operations are performed by bus masters other than CM0+ and CM4 (DMA and +* Crypto). +* -# If you do not use the default startup, ensure that firmware calls the +* following functions before any flash write/erase operations: +* \snippet Flash_sut_01.cydsn/main_cm0p.c Flash Initialization +* +* \subsection group_flash_config_rww Partially Blocking: +* This method has a much shorter time window during which Flash accesses are not +* allowed. Application code execution from Flash is blocked for only a part of +* Flash Write duration, for both cores. Blocking duration depends upon the API +* sequence used. +* +* For API sequence Cy_Flash_StartErase() + Cy_Flash_StartProgram() there are +* four block-out regions during which the read is blocked using the software +* driver (PDL). See Figure 1. +* +*
+* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
Table 1 - Block-out periods
Block-outPhaseDuration
AThe beginning of the Erase operation2ms + 9500 SlowClk cycles
BThe end of the Erase operation0.13ms + 1000 SlowClk cycles
CThe beginning of the Program operation0.8ms + 6000 SlowClk cycles
DThe end of the Program operation0.13ms + 1000 SlowClk cycles
+*
+* +* This allows both cores to execute an application for about 80% of Flash Write +* operation - see Figure 1. +* This capability is important for communication protocols that rely on fast +* response. +* +* \image html flash-rww-diagram.png "Figure 1 - Blocking Intervals in Flash Write operation" width=70% +* +* For the Cy_Flash_StartWrite() function, the block-out period is different for +* the two cores. The core that initiates Cy_Flash_StartWrite() is blocked for +* two periods: +* - From start of Erase operation (start of A on Figure 1) till the start of +* Program operation (end of C on Figure 1). +* - During D period on Figure 1. +* +* The core that performs read/execute is blocked identically to the +* Cy_Flash_StartErase() + Cy_Flash_StartProgram() sequence - see Figure 1. +* +* This allows the core that initiates Cy_Flash_StartWrite() to execute an +* application for about 20% of the Flash Write operation. The other core executes +* the application for about 80% of the Flash Write operation. +* +* Some constraints must be planned for in the Partially Blocking mode which are +* described in detail below. +* +* \subsection group_flash_config_rww_const Constraints for Partially Blocking Flash operations: +* -# During write to flash, the device should not be reset (including XRES pin, +* software reset, and watchdog) or unexpected changes may be made to portions +* of the flash. +* -# The low-voltage detect circuits should be configured to generate an +* interrupt instead of a reset. +* -# During write to flash, application code should not change the clock +* settings. Use Cy_Flash_IsOperationComplete() to ensure flash write +* operation is finished. +* -# Flash write operation is allowed only in one of the following CM4 states: +* -# CM4 is Active and initialized:
+* call \ref Cy_SysEnableCM4 "Cy_SysEnableCM4(CY_CORTEX_M4_APPL_ADDR)". +* Note: If desired user may put CM4 core in Deep Sleep any time +* after calling Cy_SysEnableCM4(). +* -# CM4 is Off:
+* call Cy_SysDisableCM4(). Note: In this state Debug mode is not +* supported. +* . +* -# Use the following rules for split by sectors. (In this context, read means +* read of any bus master: CM0+, CM4, DMA, Crypto, etc.) +* -# Do not write to and read/execute from the same flash sector at the same +* time. This is true for all sectors. +* -# Writing rules in User Flash: +* -# Any bus master can read/execute from UFLASH S0 and/or S1, during +* flash write to UFLASH S2 or S3. +* -# Any bus master can read/execute from UFLASH S2 and/or S3, during +* flash write to UFLASH S0 or S1. +* +* Suggestion: in case of bootloading, it is recommended to place +* code for CM4 in either S0 or S1. CM0+ code resides in S0. Write data +* to S2 and S3 sections. +* . +* -# Flash write cannot be performed in ULP mode (core voltage 0.9V). +* -# Interrupts must be enabled on both active cores. Do not enter a critical +* section during flash operation. +* -# User must guarantee that system pipe interrupts (IPC interrupts 3 and 4) +* have the highest priority, or at least that pipe interrupts are not +* interrupted or in a pending state for more than 700 µs. +* -# User must guarantee that during flash write operation no flash read +* operations are performed by bus masters other than CM0+ and CM4 +* (DMA and Crypto). +* -# If you do not use the default startup, ensure that firmware calls the +* following functions before any flash write/erase operations: +* \snippet Flash_sut_01.cydsn/main_cm0p.c Flash Initialization +* +* \subsection group_flash_config_emeeprom EEPROM section use: +* If you plan to use "cy_em_eeprom" section for different purposes for both of +* device cores or use Em_EEPROM Middleware together with flash driver +* write operations you must modify the linker scripts.
+* For more information, refer to the Middleware/Cypress Em_EEPROM Middleware +* Library section of the PDL documentation. +* +* \section group_flash_more_information More Information +* +* See the technical reference manual (TRM) for more information about the Flash +* architecture. +* +* \section group_flash_MISRA MISRA-C Compliance +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
MISRA RuleRule Class (Required/Advisory)Rule DescriptionDescription of Deviation(s)
11.4ACasting to different object pointer type.The cast of the uint32_t pointer to pipe message structure pointer +* is used to get transmitted data via the \ref group_ipc channel. +* We cast only one pointer, so there is no way to avoid this cast.
11.5RNot performed, the cast that removes any const or volatile qualification from the type addressed by a pointer.The removal of the volatile qualification inside the function has no side effects.
+* +* \section group_flash_changelog Changelog +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
VersionChangesReason for Change
3.0New function - Cy_Flash_ProgramRow();
+* Updated Cy_Flash_RowChecksum(): changed input parameter to take the +* row address (rowAddr) instead of the row number +* (rowNum);
+* Renamed macro for disabling RWW support in driver to +* CY_FLASH_RWW_DRV_SUPPORT_DISABLED.
+* Updated \ref group_flash_configuration documentation section with +* flash usage constraints.
Improvements made based on usability feedback to use a common +* interface
2.0Added non-blocking erase function - Cy_Flash_StartErase(). +* Removed the clear cache function call.The clear cache operation is removed from the blocking Write/Erase +* function because in this case it is performed by the hardware. +* Otherwise it is documented that it is the user's responsibility to +* clear the cache after executing the non-blocking Write/Erase flash +* operation.
Added new Cy_Flash_IsOperationComplete() function to check completeness. +* Obsoleted Cy_Flash_IsWriteComplete(), Cy_Flash_IsProgramComplete(), +* and Cy_Flash_IsEraseComplete() functions.
+* Added Cy_Flash_GetExternalStatus() function to get unparsed status where +* flash driver will be used in security applications with other modules +* as SecureImage.
+* Added Cy_Flash_Init() function to initialize all needed prerequisites +* for Erase/Write operations.
Updated driver design to improve user experience.
Updated driver implementation to remove MISRA rules deviations.Driver implementation quality improvement.
1.0Initial version
+* +* \defgroup group_flash_macros Macros +* \{ +* \defgroup group_flash_general_macros Flash general parameters +* Provides general information about flash +* \} +* \defgroup group_flash_functions Functions +* \defgroup group_flash_enumerated_types Enumerated Types +*/ + +#include +#include "syslib/cy_syslib.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/*************************************** +* Macro definitions +***************************************/ +/** +* \addtogroup group_flash_macros +* \{ +*/ + +/** Driver major version */ +#define CY_FLASH_DRV_VERSION_MAJOR 3 + +/** Driver minor version */ +#define CY_FLASH_DRV_VERSION_MINOR 0 + +#define CY_FLASH_ID (CY_PDL_DRV_ID(0x14UL)) /**< FLASH PDL ID */ + +#define CY_FLASH_ID_INFO (uint32_t)( CY_FLASH_ID | CY_PDL_STATUS_INFO ) /**< Return prefix for FLASH driver function status codes */ +#define CY_FLASH_ID_WARNING (uint32_t)( CY_FLASH_ID | CY_PDL_STATUS_WARNING) /**< Return prefix for FLASH driver function warning return values */ +#define CY_FLASH_ID_ERROR (uint32_t)( CY_FLASH_ID | CY_PDL_STATUS_ERROR) /**< Return prefix for FLASH driver function error return values */ + +/** \} group_flash_macros */ + + +/** +* \addtogroup group_flash_general_macros +* \{ +*/ + +/** Flash row size */ +#define CY_FLASH_SIZEOF_ROW (CPUSS_FLASHC_PA_SIZE * 4u) +/** Number of flash rows */ +#define CY_FLASH_NUMBER_ROWS (CY_FLASH_SIZE / CY_FLASH_SIZEOF_ROW) +/** Long words flash row size */ +#define CY_FLASH_SIZEOF_ROW_LONG_UNITS (CY_FLASH_SIZEOF_ROW / sizeof(uint32_t)) + +/** \} group_flash_general_macros */ + + +/** +* \addtogroup group_flash_enumerated_types +* \{ +*/ + +/** This enum has the return values of the Flash driver */ +typedef enum cy_en_flashdrv_status +{ + CY_FLASH_DRV_SUCCESS = 0x00UL, /**< Success */ + CY_FLASH_DRV_INV_PROT = ( CY_FLASH_ID_ERROR + 0x0UL), /**< Invalid device protection state */ + CY_FLASH_DRV_INVALID_FM_PL = ( CY_FLASH_ID_ERROR + 0x1UL), /**< Invalid flash page latch address */ + CY_FLASH_DRV_INVALID_FLASH_ADDR = ( CY_FLASH_ID_ERROR + 0x2UL), /**< Invalid flash address */ + CY_FLASH_DRV_ROW_PROTECTED = ( CY_FLASH_ID_ERROR + 0x3UL), /**< Row is write protected */ + CY_FLASH_DRV_IPC_BUSY = ( CY_FLASH_ID_ERROR + 0x5UL), /**< IPC structure is already locked by another process */ + CY_FLASH_DRV_INVALID_INPUT_PARAMETERS = ( CY_FLASH_ID_ERROR + 0x6UL), /**< Input parameters passed to Flash API are not valid */ + CY_FLASH_DRV_PL_ROW_COMP_FA = ( CY_FLASH_ID_ERROR + 0x22UL), /**< Comparison between Page Latches and FM row failed */ + CY_FLASH_DRV_ERR_UNC = ( CY_FLASH_ID_ERROR + 0xFFUL), /**< Unknown error code. See \ref Cy_Flash_GetExternalStatus() */ + CY_FLASH_DRV_PROGRESS_NO_ERROR = ( CY_FLASH_ID_INFO + 0x0UL), /**< Command in progress; no error */ + CY_FLASH_DRV_OPERATION_STARTED = ( CY_FLASH_ID_INFO + 0x1UL), /**< Flash operation is successfully initiated */ + CY_FLASH_DRV_OPCODE_BUSY = ( CY_FLASH_ID_INFO + 0x2UL) /**< Flash is under operation */ +} cy_en_flashdrv_status_t; + +/** \} group_flash_enumerated_types */ + +/*************************************** +* Function Prototypes +***************************************/ + +/** +* \addtogroup group_flash_functions +* \{ +*/ +void Cy_Flash_Init(void); +cy_en_flashdrv_status_t Cy_Flash_EraseRow(uint32_t rowAddr); +cy_en_flashdrv_status_t Cy_Flash_ProgramRow(uint32_t rowAddr, const uint32_t* data); +cy_en_flashdrv_status_t Cy_Flash_WriteRow(uint32_t rowAddr, const uint32_t* data); +cy_en_flashdrv_status_t Cy_Flash_StartWrite(uint32_t rowAddr, const uint32_t* data); +cy_en_flashdrv_status_t Cy_Flash_StartProgram(uint32_t rowAddr, const uint32_t* data); +cy_en_flashdrv_status_t Cy_Flash_StartErase(uint32_t rowAddr); +cy_en_flashdrv_status_t Cy_Flash_IsOperationComplete(void); +cy_en_flashdrv_status_t Cy_Flash_RowChecksum(uint32_t rowAddr, uint32_t* checksumPtr); +cy_en_flashdrv_status_t Cy_Flash_CalculateHash(const uint32_t* data, uint32_t numberOfBytes, uint32_t* hashPtr); +uint32_t Cy_Flash_GetExternalStatus(void); +/** \} group_flash_functions */ + +/** \cond INTERNAL */ +/* Macros to backward compatibility */ +#define Cy_Flash_IsWriteComplete(...) Cy_Flash_IsOperationComplete() +#define Cy_Flash_IsProgramComplete(...) Cy_Flash_IsOperationComplete() +#define Cy_Flash_IsEraseComplete(...) Cy_Flash_IsOperationComplete() +/** \endcond */ + +#if defined(__cplusplus) +} +#endif + + +#endif /* #if !defined(CY_FLASH_H) */ + +/** \} group_flash */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/gpio/cy_gpio.c b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/gpio/cy_gpio.c new file mode 100644 index 0000000000..dc394efd93 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/gpio/cy_gpio.c @@ -0,0 +1,262 @@ +/***************************************************************************//** +* \file cy_gpio.c +* \version 1.10.1 +* +* \brief +* Provides an API implementation of the GPIO driver +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include "cy_gpio.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/******************************************************************************* +* Function Name: Cy_GPIO_Pin_Init +****************************************************************************//** +* +* \brief Initializes all pin configuration settings for the specified pin. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param config +* Pointer to the pin config structure base address +* +* \return +* Initialization status +* +* \note +* This function modifies port registers in read-modify-write operations. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_Pin_Init +* +*******************************************************************************/ +cy_en_gpio_status_t Cy_GPIO_Pin_Init(GPIO_PRT_Type *base, uint32_t pinNum, const cy_stc_gpio_pin_config_t *config) +{ + cy_en_gpio_status_t status = CY_GPIO_SUCCESS; + uint32_t maskCfgOut; + uint32_t tempReg; + + if((NULL != base) && (NULL != config)) + { + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config->outVal)); + CY_ASSERT_L2(CY_GPIO_IS_DM_VALID(config->driveMode)); + CY_ASSERT_L2(CY_GPIO_IS_HSIOM_VALID(config->hsiom)); + CY_ASSERT_L2(CY_GPIO_IS_INT_EDGE_VALID(config->intEdge)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config->intMask)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config->vtrip)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config->slewRate)); + CY_ASSERT_L2(CY_GPIO_IS_DRIVE_SEL_VALID(config->driveSel)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config->vregEn)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config->ibufMode)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(config->vtripSel)); + CY_ASSERT_L2(CY_GPIO_IS_VREF_SEL_VALID(config->vrefSel)); + CY_ASSERT_L2(CY_GPIO_IS_VOH_SEL_VALID(config->vohSel)); + + Cy_GPIO_Write(base, pinNum, config->outVal); + Cy_GPIO_SetDrivemode(base, pinNum, config->driveMode); + Cy_GPIO_SetHSIOM(base, pinNum, config->hsiom); + + Cy_GPIO_SetInterruptEdge(base, pinNum, config->intEdge); + Cy_GPIO_SetInterruptMask(base, pinNum, config->intMask); + Cy_GPIO_SetVtrip(base, pinNum, config->vtrip); + + /* Slew rate and Driver strength */ + maskCfgOut = (CY_GPIO_CFG_OUT_SLOW_MASK << pinNum) + | (CY_GPIO_CFG_OUT_DRIVE_SEL_MASK << ((uint32_t)(pinNum << 1u) + CY_GPIO_CFG_OUT_DRIVE_OFFSET)); + tempReg = base->CFG_OUT & ~(maskCfgOut); + base->CFG_OUT = tempReg | ((config->slewRate & CY_GPIO_CFG_OUT_SLOW_MASK) << pinNum) + | ((config->driveSel & CY_GPIO_CFG_OUT_DRIVE_SEL_MASK) << ((uint32_t)(pinNum << 1u) + CY_GPIO_CFG_OUT_DRIVE_OFFSET)); + + /* SIO specific configuration */ + tempReg = base->CFG_SIO & ~(CY_GPIO_SIO_PIN_MASK); + base->CFG_SIO = tempReg | (((config->vregEn & CY_GPIO_VREG_EN_MASK) + | ((config->ibufMode & CY_GPIO_IBUF_MASK) << CY_GPIO_IBUF_SHIFT) + | ((config->vtripSel & CY_GPIO_VTRIP_SEL_MASK) << CY_GPIO_VTRIP_SEL_SHIFT) + | ((config->vrefSel & CY_GPIO_VREF_SEL_MASK) << CY_GPIO_VREF_SEL_SHIFT) + | ((config->vohSel & CY_GPIO_VOH_SEL_MASK) << CY_GPIO_VOH_SEL_SHIFT)) + << ((pinNum & CY_GPIO_SIO_ODD_PIN_MASK) << CY_GPIO_CFG_SIO_OFFSET)); + } + else + { + status = CY_GPIO_BAD_PARAM; + } + + return(status); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_Port_Init +****************************************************************************//** +* +* \brief Initialize a complete port of pins from a single init structure. +* +* The configuration structure used in this function has a 1:1 mapping to the +* GPIO and HSIOM registers. Refer to the device Technical Reference Manual (TRM) +* for the register details on how to populate them. +* +* \param base +* Pointer to the pin's port register base address +* +* \param config +* Pointer to the pin config structure base address +* +* \return +* Initialization status +* +* \note +* If using the PSoC Creator IDE, there is no need to initialize the pins when +* using the GPIO component on the schematic. Ports are configured in +* Cy_SystemInit() before main() entry. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_Port_Init +* +*******************************************************************************/ +cy_en_gpio_status_t Cy_GPIO_Port_Init(GPIO_PRT_Type* base, const cy_stc_gpio_prt_config_t *config) +{ + cy_en_gpio_status_t status = CY_GPIO_SUCCESS; + uint32_t portNum; + HSIOM_PRT_Type* baseHSIOM; + + if((NULL != base) && (NULL != config)) + { + CY_ASSERT_L2(CY_GPIO_IS_PIN_BIT_VALID(config->out)); + CY_ASSERT_L2(CY_GPIO_IS_PIN_BIT_VALID(config->cfgIn)); + CY_ASSERT_L2(CY_GPIO_IS_INTR_CFG_VALID(config->intrCfg)); + CY_ASSERT_L2(CY_GPIO_IS_INTR_MASK_VALID(config->intrMask)); + CY_ASSERT_L2(CY_GPIO_IS_SEL_ACT_VALID(config->sel0Active)); + CY_ASSERT_L2(CY_GPIO_IS_SEL_ACT_VALID(config->sel1Active)); + + portNum = ((uint32_t)(base) - GPIO_BASE) / GPIO_PRT_SECTION_SIZE; + baseHSIOM = (HSIOM_PRT_Type*)(HSIOM_BASE + (HSIOM_PRT_SECTION_SIZE * portNum)); + + base->OUT = config->out; + base->CFG = config->cfg; + base->CFG_IN = config->cfgIn; + base->CFG_OUT = config->cfgOut; + base->INTR_CFG = config->intrCfg; + base->INTR_MASK = config->intrMask; + base->CFG_SIO = config->cfgSIO; + baseHSIOM->PORT_SEL0 = config->sel0Active; + baseHSIOM->PORT_SEL1 = config->sel1Active; + } + else + { + status = CY_GPIO_BAD_PARAM; + } + + return(status); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_Pin_FastInit +****************************************************************************//** +* +* \brief Initialize the most common configuration settings for all pin types. +* +* These include, drive mode, initial output value, and HSIOM connection. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param driveMode +* Pin drive mode. Options are detailed in \ref group_gpio_driveModes macros +* +* \param outVal +* Logic state of the output buffer driven to the pin (1 or 0) +* +* \param hsiom +* HSIOM input selection +* +* \return +* void +* +* \note +* This function modifies port registers in read-modify-write operations. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_Pin_FastInit +* +*******************************************************************************/ +void Cy_GPIO_Pin_FastInit(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t driveMode, + uint32_t outVal, en_hsiom_sel_t hsiom) +{ + uint32_t tempReg; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_DM_VALID(driveMode)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(outVal)); + CY_ASSERT_L2(CY_GPIO_IS_HSIOM_VALID(hsiom)); + + tempReg = (base->OUT & ~(CY_GPIO_OUT_MASK << pinNum)); + base->OUT = tempReg | ((outVal & CY_GPIO_OUT_MASK) << pinNum); + + tempReg = (base->CFG & ~(CY_GPIO_CFG_DM_MASK << (pinNum << CY_GPIO_DRIVE_MODE_OFFSET))); + base->CFG = tempReg | ((driveMode & CY_GPIO_CFG_DM_MASK) << (pinNum << CY_GPIO_DRIVE_MODE_OFFSET)); + + Cy_GPIO_SetHSIOM(base, pinNum, hsiom); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_Port_Deinit +****************************************************************************//** +* +* \brief Reset a complete port of pins back to power on reset defaults. +* +* \param base +* Pointer to the pin's port register base address +* +* \return +* void +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_Port_Deinit +* +*******************************************************************************/ +void Cy_GPIO_Port_Deinit(GPIO_PRT_Type* base) +{ + uint32_t portNum; + HSIOM_PRT_Type* portAddrHSIOM; + + portNum = ((uint32_t)(base) - GPIO_BASE) / GPIO_PRT_SECTION_SIZE; + portAddrHSIOM = (HSIOM_PRT_Type*)(HSIOM_BASE + (HSIOM_PRT_SECTION_SIZE * portNum)); + + base->OUT = CY_GPIO_PRT_DEINIT; + base->CFG = CY_GPIO_PRT_DEINIT; + base->CFG_IN = CY_GPIO_PRT_DEINIT; + base->CFG_OUT = CY_GPIO_PRT_DEINIT; + base->INTR_CFG = CY_GPIO_PRT_DEINIT; + base->INTR_MASK = CY_GPIO_PRT_DEINIT; + base->CFG_SIO = CY_GPIO_PRT_DEINIT; + portAddrHSIOM->PORT_SEL0 = CY_GPIO_PRT_DEINIT; + portAddrHSIOM->PORT_SEL1 = CY_GPIO_PRT_DEINIT; +} + +#if defined(__cplusplus) +} +#endif + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/gpio/cy_gpio.h b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/gpio/cy_gpio.h new file mode 100644 index 0000000000..6b5d97f7e4 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/gpio/cy_gpio.h @@ -0,0 +1,1958 @@ +/***************************************************************************//** +* \file cy_gpio.h +* \version 1.10.1 +* +* \brief +* Provides an API declaration of the GPIO driver +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +/** +* \defgroup group_gpio General Purpose Input Output (GPIO) +* \{ +* The GPIO driver provides an API to configure and access device Input/Output pins. +* IO pins include all general purpose types such as GPIO, SIO, HSIO, AUXIO, and +* their variants. +* +* Initialization can be performed either at the port level or by configuring the +* individual pins. For efficient use of code space, port +* configuration should be used in the field. Refer to the product device header files +* for the list of supported ports and pins. +* +* - Single pin configuration is performed by using \ref Cy_GPIO_Pin_FastInit +* (provide specific values) or \ref Cy_GPIO_Pin_Init (provide a filled +* cy_stc_gpio_pin_config_t structure). +* - An entire port can be configured using \ref Cy_GPIO_Port_Init. Provide a filled +* cy_stc_gpio_prt_config_t structure. The values in the structure are +* bitfields representing the desired value for each pin in the port. +* - Pin configuration and management is based on the port address and pin number. +* \ref Cy_GPIO_PortToAddr function can optionally be used to calculate the port +* address from the port number at run-time. +* +* Once the pin/port initialization is complete, each pin can be accessed by +* specifying the port (GPIO_PRT_Type) and the pin (0-7) in the provided API +* functions. +* +* \section group_gpio_configuration Configuration Considerations +* +* 1. Pin multiplexing is controlled through the High-Speed IO Matrix (HSIOM) selection. +* This allows the pin to connect to signal sources/sinks throughout the device, +* as defined by the pin HSIOM selection options (en_hsiom_sel_t). +* 2. All pins are initialized to High-Z drive mode with HSIOM connected to CPU (SW +* control digital pin only) at Power-On-Reset(POR). +* 3. Some API functions perform read-modify-write operations on shared port +* registers. These functions are not thread safe and care must be taken when +* called by the application. +* +* Multiple pins on a port can be updated using direct port register writes with an +* appropriate port mask. An example is shown below, highlighting the different ways of +* configuring Port 1 pins using, +* +* - Port output data register +* - Port output data set register +* - Port output data clear register +* +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c Cy_GPIO_Snippet +* +* \section group_gpio_more_information More Information +* +* Refer to the technical reference manual (TRM) and the device datasheet. +* +* \section group_gpio_MISRA MISRA-C Compliance] +* +* +* +* +* +* +* +* +* +* +* +* +* +*
MISRA RuleRule Class (Required/Advisory)Rule DescriptionDescription of Deviation(s)
16.7AA pointer parameter in a function prototype should be declared as pointer +* to const if the pointer is not used to modify the addressed object.The objects pointed to by the base addresses of the GPIO port are not always modified. +* While a const qualifier can be used in select scenarios, it brings little benefit +* in adding this to the affected functions.
+* +* \section group_gpio_changelog Changelog +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
VersionChangesReason for Change
1.10.1Updated description for the functions: \ref Cy_GPIO_GetInterruptStatus, +* \ref Cy_GPIO_GetInterruptMask, \ref Cy_GPIO_GetInterruptStatusMasked. +* Minor documentation edits. +* Documentation update and clarification
1.10Added input parameter validation to the API functions
1.0Initial version
+* +* \defgroup group_gpio_macros Macros +* \defgroup group_gpio_functions Functions +* \{ +* \defgroup group_gpio_functions_init Initialization Functions +* \defgroup group_gpio_functions_gpio GPIO Functions +* \defgroup group_gpio_functions_sio SIO Functions +* \defgroup group_gpio_functions_interrupt Port Interrupt Functions +* \} +* \defgroup group_gpio_data_structures Data Structures +* \defgroup group_gpio_enums Enumerated Types +*/ + +#if !defined(CY_GPIO_H) +#define CY_GPIO_H + +#include +#include "syslib/cy_syslib.h" +#include "cy_device_headers.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \addtogroup group_gpio_macros +* \{ +*/ + +/** Driver major version */ +#define CY_GPIO_DRV_VERSION_MAJOR 1 + +/** Driver minor version */ +#define CY_GPIO_DRV_VERSION_MINOR 10 + +/** GPIO driver ID */ +#define CY_GPIO_ID CY_PDL_DRV_ID(0x16u) + +/** \} group_gpio_macros */ + + +/*************************************** +* Enumerations +***************************************/ +/** +* \addtogroup group_gpio_enums +* \{ +*/ + +/** +* GPIO Driver error codes +*/ +typedef enum +{ + CY_GPIO_SUCCESS = 0x00u, /**< Returned successful */ + CY_GPIO_BAD_PARAM = CY_GPIO_ID | CY_PDL_STATUS_ERROR | 0x01u, /**< Bad parameter was passed */ +} cy_en_gpio_status_t; + +/** \} group_gpio_enums */ + + +/*************************************** +* Configuration Structures +***************************************/ + +/** +* \addtogroup group_gpio_data_structures +* \{ +*/ + +/** This structure is used to initialize a port of GPIO pins */ +typedef struct { + uint32_t out; /**< Initial output data for the IO pins in the port */ + uint32_t intrMask; /**< Interrupt enable mask for the port interrupt */ + uint32_t intrCfg; /**< Port pin interrupt edge detection configuration */ + uint32_t cfg; /**< Port pin drive modes and input buffer enable configuration */ + uint32_t cfgIn; /**< Port pin input buffer configuration */ + uint32_t cfgOut; /**< Port pin output buffer configuration */ + uint32_t cfgSIO; /**< Port SIO pins configuration */ + uint32_t sel0Active; /**< HSIOM selection for port pins 0,1,2,3 */ + uint32_t sel1Active; /**< HSIOM selection for port pins 4,5,6,7 */ +} cy_stc_gpio_prt_config_t; + +/** This structure is used to initialize a single GPIO pin */ +typedef struct { + uint32_t outVal; /**< Pin output state */ + uint32_t driveMode; /**< Drive mode */ + en_hsiom_sel_t hsiom; /**< HSIOM selection */ + uint32_t intEdge; /**< Interrupt Edge type */ + uint32_t intMask; /**< Interrupt enable mask */ + uint32_t vtrip; /**< Input buffer voltage trip type */ + uint32_t slewRate; /**< Output buffer slew rate */ + uint32_t driveSel; /**< Drive strength */ + uint32_t vregEn; /**< SIO pair output buffer mode */ + uint32_t ibufMode; /**< SIO pair input buffer mode */ + uint32_t vtripSel; /**< SIO pair input buffer trip point */ + uint32_t vrefSel; /**< SIO pair reference voltage for input buffer trip point */ + uint32_t vohSel; /**< SIO pair regulated voltage output level */ +} cy_stc_gpio_pin_config_t; + +/** \} group_gpio_data_structures */ + +/*************************************** +* Constants +***************************************/ + +/** \cond INTERNAL */ + +/* General Constants */ +#define CY_GPIO_PRT_HALF (4UL) /**< Half-way point of a GPIO port */ +#define CY_GPIO_PRT_DEINIT (0UL) /**< De-init value for port registers */ + +/* GPIO Masks */ +#define CY_GPIO_HSIOM_MASK (0x1FUL) /**< HSIOM selection mask */ +#define CY_GPIO_OUT_MASK (0x01UL) /**< Single pin mask for OUT register */ +#define CY_GPIO_IN_MASK (0x01UL) /**< Single pin mask for IN register */ +#define CY_GPIO_CFG_DM_MASK (0x0FUL) /**< Single pin mask for drive mode in CFG register */ +#define CY_GPIO_CFG_IN_VTRIP_SEL_MASK (0x01UL) /**< Single pin mask for VTRIP selection in CFG IN register */ +#define CY_GPIO_CFG_OUT_SLOW_MASK (0x01UL) /**< Single pin mask for slew rate in CFG OUT register */ +#define CY_GPIO_CFG_OUT_DRIVE_SEL_MASK (0x03UL) /**< Single pin mask for drive strength in CFG OUT register */ +#define CY_GPIO_INTR_STATUS_MASK (0x01UL) /**< Single pin mask for interrupt status in INTR register */ +#define CY_GPIO_INTR_EN_MASK (0x01UL) /**< Single pin mask for interrupt status in INTR register */ +#define CY_GPIO_INTR_MASKED_MASK (0x01UL) /**< Single pin mask for masked interrupt status in INTR_MASKED register */ +#define CY_GPIO_INTR_SET_MASK (0x01UL) /**< Single pin mask for setting the interrupt in INTR_MASK register */ +#define CY_GPIO_INTR_EDGE_MASK (0x03UL) /**< Single pin mask for interrupt edge type in INTR_EDGE register */ +#define CY_GPIO_INTR_FLT_EDGE_MASK (0x07UL) /**< Single pin mask for setting filtered interrupt */ + +/* SIO Masks */ +#define CY_GPIO_VREG_EN_MASK (0x01UL) /**< Single SIO pin mask for voltage regulation enable */ +#define CY_GPIO_IBUF_MASK (0x01UL) /**< Single SIO pin mask for input buffer */ +#define CY_GPIO_IBUF_SHIFT (0x01UL) /**< Single SIO pin shift for input buffer */ +#define CY_GPIO_VTRIP_SEL_MASK (0x01UL) /**< Single SIO pin mask for the input buffer trip point */ +#define CY_GPIO_VTRIP_SEL_SHIFT (0x02UL) /**< Single SIO pin shift for the input buffer trip point */ +#define CY_GPIO_VREF_SEL_MASK (0x03UL) /**< Single SIO pin mask for voltage reference */ +#define CY_GPIO_VREF_SEL_SHIFT (0x03UL) /**< Single SIO pin shift for voltage reference */ +#define CY_GPIO_VOH_SEL_MASK (0x07UL) /**< Single SIO pin mask for VOH */ +#define CY_GPIO_VOH_SEL_SHIFT (0x05UL) /**< Single SIO pin shift for VOH */ + +/* Special mask for SIO pin pair setting */ +#define CY_GPIO_SIO_ODD_PIN_MASK (0x00FEUL) /**< SIO pin pair selection mask */ +#define CY_GPIO_SIO_PIN_MASK (0x00FFUL) /**< SIO pin pair mask */ + +/* Offsets */ +#define CY_GPIO_HSIOM_OFFSET (3UL) /**< Offset for HSIOM */ +#define CY_GPIO_DRIVE_MODE_OFFSET (2UL) /**< Offset for Drive mode */ +#define CY_GPIO_INBUF_OFFSET (3UL) /**< Offset for input buffer */ +#define CY_GPIO_CFG_OUT_DRIVE_OFFSET (16UL) /**< Offset for drive strength */ +#define CY_GPIO_INTR_CFG_OFFSET (1UL) /**< Offset for interrupt config */ +#define CY_GPIO_INTR_FILT_OFFSET (18UL) /**< Offset for filtered interrupt config */ +#define CY_GPIO_CFG_SIO_OFFSET (2UL) /**< Offset for SIO config */ + +/* Parameter validation constants */ +#define CY_GPIO_PINS_MAX (8UL) /**< Number of pins in the port */ +#define CY_GPIO_PRT_PINS_MASK (0x0000000FFUL) +#define CY_GPIO_PRT_INTR_CFG_EDGE_SEL_MASK (GPIO_PRT_INTR_CFG_EDGE0_SEL_Msk | \ + GPIO_PRT_INTR_CFG_EDGE1_SEL_Msk | \ + GPIO_PRT_INTR_CFG_EDGE2_SEL_Msk | \ + GPIO_PRT_INTR_CFG_EDGE3_SEL_Msk | \ + GPIO_PRT_INTR_CFG_EDGE4_SEL_Msk | \ + GPIO_PRT_INTR_CFG_EDGE5_SEL_Msk | \ + GPIO_PRT_INTR_CFG_EDGE6_SEL_Msk | \ + GPIO_PRT_INTR_CFG_EDGE7_SEL_Msk) +#define CY_GPIO_PRT_INTR_CFG_RANGE_MASK (CY_GPIO_PRT_INTR_CFG_EDGE_SEL_MASK | \ + GPIO_PRT_INTR_CFG_FLT_EDGE_SEL_Msk | \ + GPIO_PRT_INTR_CFG_FLT_SEL_Msk) +#define CY_GPIO_PRT_INT_MASK_MASK (0x0000001FFUL) +#define CY_GPIO_PRT_SEL_ACTIVE_MASK (0x1FFFFFFFUL) + +/* Parameter validation macros */ +#define CY_GPIO_IS_PIN_VALID(pinNum) (CY_GPIO_PINS_MAX > (pinNum)) +#define CY_GPIO_IS_FILTER_PIN_VALID(pinNum) (CY_GPIO_PINS_MAX >= (pinNum)) +#define CY_GPIO_IS_VALUE_VALID(outVal) (1UL >= (outVal)) +#define CY_GPIO_IS_DM_VALID(driveMode) (0U == ((driveMode) & (uint32_t)~CY_GPIO_CFG_DM_MASK)) + +#define CY_GPIO_IS_HSIOM_VALID(hsiom) (0U == ((hsiom) & (uint32_t)~CY_GPIO_HSIOM_MASK)) + +#define CY_GPIO_IS_INT_EDGE_VALID(intEdge) ((CY_GPIO_INTR_DISABLE == (intEdge)) || \ + (CY_GPIO_INTR_RISING == (intEdge)) || \ + (CY_GPIO_INTR_FALLING == (intEdge)) || \ + (CY_GPIO_INTR_BOTH == (intEdge))) + +#define CY_GPIO_IS_DRIVE_SEL_VALID(driveSel) ((CY_GPIO_DRIVE_FULL == (driveSel)) || \ + (CY_GPIO_DRIVE_1_2 == (driveSel)) || \ + (CY_GPIO_DRIVE_1_4 == (driveSel)) || \ + (CY_GPIO_DRIVE_1_8 == (driveSel))) + +#define CY_GPIO_IS_VREF_SEL_VALID(vrefSel) ((CY_SIO_VREF_PINREF == (vrefSel)) || \ + (CY_SIO_VREF_1_2V == (vrefSel)) || \ + (CY_SIO_VREF_AMUX_A == (vrefSel)) || \ + (CY_SIO_VREF_AMUX_B == (vrefSel))) + +#define CY_GPIO_IS_VOH_SEL_VALID(vrefSel) ((CY_SIO_VOH_1_00 == (vrefSel)) || \ + (CY_SIO_VOH_1_25 == (vrefSel)) || \ + (CY_SIO_VOH_1_49 == (vrefSel)) || \ + (CY_SIO_VOH_1_67 == (vrefSel)) || \ + (CY_SIO_VOH_2_08 == (vrefSel)) || \ + (CY_SIO_VOH_2_50 == (vrefSel)) || \ + (CY_SIO_VOH_2_78 == (vrefSel)) || \ + (CY_SIO_VOH_4_16 == (vrefSel))) + +#define CY_GPIO_IS_PIN_BIT_VALID(pinBit) (0U == ((pinBit) & (uint32_t)~CY_GPIO_PRT_PINS_MASK)) +#define CY_GPIO_IS_INTR_CFG_VALID(intrCfg) (0U == ((intrCfg) & (uint32_t)~CY_GPIO_PRT_INTR_CFG_RANGE_MASK)) +#define CY_GPIO_IS_INTR_MASK_VALID(intrMask) (0U == ((intrMask) & (uint32_t)~CY_GPIO_PRT_INT_MASK_MASK)) +#define CY_GPIO_IS_SEL_ACT_VALID(selActive) (0U == ((selActive) & (uint32_t)~CY_GPIO_PRT_SEL_ACTIVE_MASK)) + +/** \endcond */ + + +/*************************************** +* Function Constants +***************************************/ + +/** +* \addtogroup group_gpio_macros +* \{ +*/ + +/** +* \defgroup group_gpio_driveModes Pin drive mode +* \{ +* Constants to be used for setting the drive mode of the pin. +*/ +#define CY_GPIO_DM_ANALOG (0x00UL) /**< \brief Analog High-Z. Input buffer off */ +#define CY_GPIO_DM_PULLUP_IN_OFF (0x02UL) /**< \brief Resistive Pull-Up. Input buffer off */ +#define CY_GPIO_DM_PULLDOWN_IN_OFF (0x03UL) /**< \brief Resistive Pull-Down. Input buffer off */ +#define CY_GPIO_DM_OD_DRIVESLOW_IN_OFF (0x04UL) /**< \brief Open Drain, Drives Low. Input buffer off */ +#define CY_GPIO_DM_OD_DRIVESHIGH_IN_OFF (0x05UL) /**< \brief Open Drain, Drives High. Input buffer off */ +#define CY_GPIO_DM_STRONG_IN_OFF (0x06UL) /**< \brief Strong Drive. Input buffer off */ +#define CY_GPIO_DM_PULLUP_DOWN_IN_OFF (0x07UL) /**< \brief Resistive Pull-Up/Down. Input buffer off */ +#define CY_GPIO_DM_HIGHZ (0x08UL) /**< \brief Digital High-Z. Input buffer on */ +#define CY_GPIO_DM_PULLUP (0x0AUL) /**< \brief Resistive Pull-Up. Input buffer on */ +#define CY_GPIO_DM_PULLDOWN (0x0BUL) /**< \brief Resistive Pull-Down. Input buffer on */ +#define CY_GPIO_DM_OD_DRIVESLOW (0x0CUL) /**< \brief Open Drain, Drives Low. Input buffer on */ +#define CY_GPIO_DM_OD_DRIVESHIGH (0x0DUL) /**< \brief Open Drain, Drives High. Input buffer on */ +#define CY_GPIO_DM_STRONG (0x0EUL) /**< \brief Strong Drive. Input buffer on */ +#define CY_GPIO_DM_PULLUP_DOWN (0x0FUL) /**< \brief Resistive Pull-Up/Down. Input buffer on */ +/** \} */ + +/** +* \defgroup group_gpio_vtrip Voltage trip mode +* \{ +* Constants to be used for setting the voltage trip type on the pin. +*/ +#define CY_GPIO_VTRIP_CMOS (0x00UL) /**< \brief Input buffer compatible with CMOS and I2C interfaces */ +#define CY_GPIO_VTRIP_TTL (0x01UL) /**< \brief Input buffer compatible with TTL and MediaLB interfaces */ +/** \} */ + +/** +* \defgroup group_gpio_slewRate Slew Rate Mode +* \{ +* Constants to be used for setting the slew rate of the pin. +*/ +#define CY_GPIO_SLEW_FAST (0x00UL) /**< \brief Fast slew rate */ +#define CY_GPIO_SLEW_SLOW (0x01UL) /**< \brief Slow slew rate */ +/** \} */ + +/** +* \defgroup group_gpio_driveStrength Pin drive strength +* \{ +* Constants to be used for setting the drive strength of the pin. +*/ +#define CY_GPIO_DRIVE_FULL (0x00UL) /**< \brief Full drive strength: Max drive current */ +#define CY_GPIO_DRIVE_1_2 (0x01UL) /**< \brief 1/2 drive strength: 1/2 drive current */ +#define CY_GPIO_DRIVE_1_4 (0x02UL) /**< \brief 1/4 drive strength: 1/4 drive current */ +#define CY_GPIO_DRIVE_1_8 (0x03UL) /**< \brief 1/8 drive strength: 1/8 drive current */ +/** \} */ + +/** +* \defgroup group_gpio_interruptTrigger Interrupt trigger type +* \{ +* Constants to be used for setting the interrupt trigger type on the pin. +*/ +#define CY_GPIO_INTR_DISABLE (0x00UL) /**< \brief Disable the pin interrupt generation */ +#define CY_GPIO_INTR_RISING (0x01UL) /**< \brief Rising-Edge interrupt */ +#define CY_GPIO_INTR_FALLING (0x02UL) /**< \brief Falling-Edge interrupt */ +#define CY_GPIO_INTR_BOTH (0x03UL) /**< \brief Both-Edge interrupt */ +/** \} */ + +/** +* \defgroup group_gpio_sioVreg SIO output buffer mode +* \{ +* Constants to be used for setting the SIO output buffer mode on the pin. +*/ +#define CY_SIO_VREG_UNREGULATED (0x00UL) /**< \brief Unregulated output buffer */ +#define CY_SIO_VREG_REGULATED (0x01UL) /**< \brief Regulated output buffer */ +/** \} */ + +/** +* \defgroup group_gpio_sioIbuf SIO input buffer mode +* \{ +* Constants to be used for setting the SIO input buffer mode on the pin. +*/ +#define CY_SIO_IBUF_SINGLEENDED (0x00UL) /**< \brief Single ended input buffer */ +#define CY_SIO_IBUF_DIFFERENTIAL (0x01UL) /**< \brief Differential input buffer */ +/** \} */ + +/** +* \defgroup group_gpio_sioVtrip SIO input buffer trip-point +* \{ +* Constants to be used for setting the SIO input buffer trip-point of the pin. +*/ +#define CY_SIO_VTRIP_CMOS (0x00UL) /**< \brief CMOS input buffer (single-ended) */ +#define CY_SIO_VTRIP_TTL (0x01UL) /**< \brief TTL input buffer (single-ended) */ +#define CY_SIO_VTRIP_0_5VDDIO_0_5VOH (0x00UL) /**< \brief 0.5xVddio or 0.5xVoh (differential) */ +#define CY_SIO_VTRIP_0_4VDDIO_1_0VREF (0x01UL) /**< \brief 0.4xVddio or 0.4xVoh (differential) */ +/** \} */ + +/** +* \defgroup group_gpio_sioVref SIO reference voltage for input buffer trip-point +* \{ +* Constants to be used for setting the reference voltage of SIO input buffer trip-point. +*/ +#define CY_SIO_VREF_PINREF (0x00UL) /**< \brief Vref from analog pin */ +#define CY_SIO_VREF_1_2V (0x01UL) /**< \brief Vref from internal 1.2V reference */ +#define CY_SIO_VREF_AMUX_A (0x02UL) /**< \brief Vref from AMUXBUS_A */ +#define CY_SIO_VREF_AMUX_B (0x03UL) /**< \brief Vref from AMUXBUS_B */ +/** \} */ + +/** +* \defgroup group_gpio_sioVoh Regulated output voltage level (Voh) and input buffer trip-point of an SIO pair +* \{ +* Constants to be used for setting the Voh and input buffer trip-point of an SIO pair +*/ +#define CY_SIO_VOH_1_00 (0x00UL) /**< \brief Voh = 1 x Reference */ +#define CY_SIO_VOH_1_25 (0x01UL) /**< \brief Voh = 1.25 x Reference */ +#define CY_SIO_VOH_1_49 (0x02UL) /**< \brief Voh = 1.49 x Reference */ +#define CY_SIO_VOH_1_67 (0x03UL) /**< \brief Voh = 1.67 x Reference */ +#define CY_SIO_VOH_2_08 (0x04UL) /**< \brief Voh = 2.08 x Reference */ +#define CY_SIO_VOH_2_50 (0x05UL) /**< \brief Voh = 2.50 x Reference */ +#define CY_SIO_VOH_2_78 (0x06UL) /**< \brief Voh = 2.78 x Reference */ +#define CY_SIO_VOH_4_16 (0x07UL) /**< \brief Voh = 4.16 x Reference */ +/** \} */ + +/** \} group_gpio_macros */ + +/*************************************** +* Function Prototypes +***************************************/ + +/** +* \addtogroup group_gpio_functions +* \{ +*/ + +/** +* \addtogroup group_gpio_functions_init +* \{ +*/ + +cy_en_gpio_status_t Cy_GPIO_Pin_Init(GPIO_PRT_Type* base, uint32_t pinNum, const cy_stc_gpio_pin_config_t *config); +cy_en_gpio_status_t Cy_GPIO_Port_Init(GPIO_PRT_Type* base, const cy_stc_gpio_prt_config_t *config); +void Cy_GPIO_Pin_FastInit(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t driveMode, uint32_t outVal, en_hsiom_sel_t hsiom); +void Cy_GPIO_Port_Deinit(GPIO_PRT_Type* base); +__STATIC_INLINE void Cy_GPIO_SetHSIOM(GPIO_PRT_Type* base, uint32_t pinNum, en_hsiom_sel_t value); +__STATIC_INLINE en_hsiom_sel_t Cy_GPIO_GetHSIOM(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE GPIO_PRT_Type* Cy_GPIO_PortToAddr(uint32_t portNum); + +/** \} group_gpio_functions_init */ + +/** +* \addtogroup group_gpio_functions_gpio +* \{ +*/ + +__STATIC_INLINE uint32_t Cy_GPIO_Read(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_Write(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_ReadOut(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_Set(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_Clr(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_Inv(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_SetDrivemode(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_GetDrivemode(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_SetVtrip(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_GetVtrip(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_SetSlewRate(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_GetSlewRate(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_SetDriveSel(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_GetDriveSel(GPIO_PRT_Type* base, uint32_t pinNum); + +/** \} group_gpio_functions_gpio */ + +/** +* \addtogroup group_gpio_functions_sio +* \{ +*/ + +__STATIC_INLINE void Cy_GPIO_SetVregEn(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_GetVregEn(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_SetIbufMode(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_GetIbufMode(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_SetVtripSel(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_GetVtripSel(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_SetVrefSel(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_GetVrefSel(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_SetVohSel(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_GetVohSel(GPIO_PRT_Type* base, uint32_t pinNum); + +/** \} group_gpio_functions_sio */ + +/** +* \addtogroup group_gpio_functions_interrupt +* \{ +*/ + +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptStatus(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_ClearInterrupt(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_SetInterruptMask(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptMask(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptStatusMasked(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_SetSwInterrupt(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_SetInterruptEdge(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptEdge(GPIO_PRT_Type* base, uint32_t pinNum); +__STATIC_INLINE void Cy_GPIO_SetFilter(GPIO_PRT_Type* base, uint32_t value); +__STATIC_INLINE uint32_t Cy_GPIO_GetFilter(GPIO_PRT_Type* base); + +#if (IOSS_GPIO_GPIO_PORT_NR_0_31 != 0) || defined (CY_DOXYGEN) +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause0(void); +#endif /* (IOSS_GPIO_GPIO_PORT_NR_0_31 != 0) */ + +#if (IOSS_GPIO_GPIO_PORT_NR_32_63 != 0) || defined (CY_DOXYGEN) +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause1(void); +#endif /* (IOSS_GPIO_GPIO_PORT_NR_32_63 != 0) */ + +#if (IOSS_GPIO_GPIO_PORT_NR_64_95 != 0) || defined (CY_DOXYGEN) +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause2(void); +#endif /* (IOSS_GPIO_GPIO_PORT_NR_64_95 != 0) */ + +#if (IOSS_GPIO_GPIO_PORT_NR_96_127 != 0) || defined (CY_DOXYGEN) +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause3(void); +#endif /* (IOSS_GPIO_GPIO_PORT_NR_96_127 != 0) */ + +/** \} group_gpio_functions_interrupt */ + + +/** +* \addtogroup group_gpio_functions_init +* \{ +*/ + +/******************************************************************************* +* Function Name: Cy_GPIO_SetHSIOM +****************************************************************************//** +* +* \brief Configures the HSIOM connection to the pin. +* +* Connects the specified High-Speed Input Output Multiplexer (HSIOM) selection +* to the pin. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param value +* HSIOM input selection +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetHSIOM +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetHSIOM(GPIO_PRT_Type* base, uint32_t pinNum, en_hsiom_sel_t value) +{ + uint32_t portNum; + uint32_t tempReg; + HSIOM_PRT_Type* portAddrHSIOM; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_HSIOM_VALID(value)); + + portNum = ((uint32_t)(base) - GPIO_BASE) / GPIO_PRT_SECTION_SIZE; + portAddrHSIOM = (HSIOM_PRT_Type*)(HSIOM_BASE + (HSIOM_PRT_SECTION_SIZE * portNum)); + + if(pinNum < CY_GPIO_PRT_HALF) + { + tempReg = portAddrHSIOM->PORT_SEL0 & ~(CY_GPIO_HSIOM_MASK << (pinNum << CY_GPIO_HSIOM_OFFSET)); + portAddrHSIOM->PORT_SEL0 = tempReg | ((value & CY_GPIO_HSIOM_MASK) << (pinNum << CY_GPIO_HSIOM_OFFSET)); + } + else + { + pinNum -= CY_GPIO_PRT_HALF; + tempReg = portAddrHSIOM->PORT_SEL1 & ~(CY_GPIO_HSIOM_MASK << (pinNum << CY_GPIO_HSIOM_OFFSET)); + portAddrHSIOM->PORT_SEL1 = tempReg | ((value & CY_GPIO_HSIOM_MASK) << (pinNum << CY_GPIO_HSIOM_OFFSET)); + } +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetHSIOM +****************************************************************************//** +* +* \brief Returns the current HSIOM multiplexer connection to the pin. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* HSIOM input selection +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetHSIOM +* +*******************************************************************************/ +__STATIC_INLINE en_hsiom_sel_t Cy_GPIO_GetHSIOM(GPIO_PRT_Type* base, uint32_t pinNum) +{ + uint32_t returnValue; + uint32_t portNum; + HSIOM_PRT_Type* portAddrHSIOM; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + portNum = ((uint32_t)(base) - GPIO_BASE) / GPIO_PRT_SECTION_SIZE; + portAddrHSIOM = (HSIOM_PRT_Type*)(HSIOM_BASE + (HSIOM_PRT_SECTION_SIZE * portNum)); + + if(pinNum < CY_GPIO_PRT_HALF) + { + returnValue = (portAddrHSIOM->PORT_SEL0 >> (pinNum << CY_GPIO_HSIOM_OFFSET)) & CY_GPIO_HSIOM_MASK; + } + else + { + pinNum -= CY_GPIO_PRT_HALF; + returnValue = (portAddrHSIOM->PORT_SEL1 >> (pinNum << CY_GPIO_HSIOM_OFFSET)) & CY_GPIO_HSIOM_MASK; + } + + return (en_hsiom_sel_t)returnValue; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_PortToAddr +****************************************************************************//** +* +* \brief Retrieves the port address based on the given port number. +* +* This is a helper function to calculate the port base address when given a port +* number. It is to be used when pin access needs to be calculated at runtime. +* +* \param portNum +* Port number +* +* \return +* Base address of the port register structure +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_PortToAddr +* +*******************************************************************************/ +__STATIC_INLINE GPIO_PRT_Type* Cy_GPIO_PortToAddr(uint32_t portNum) +{ + GPIO_PRT_Type* base; + + if(portNum < (uint32_t)IOSS_GPIO_GPIO_PORT_NR) + { + base = (GPIO_PRT_Type *)(GPIO_BASE + (GPIO_PRT_SECTION_SIZE * portNum)); + } + else + { + /* Error: Return default base address */ + base = (GPIO_PRT_Type *)(GPIO_BASE); + } + + return (base); +} + +/** \} group_gpio_functions_init */ + +/** +* \addtogroup group_gpio_functions_gpio +* \{ +*/ + +/******************************************************************************* +* Function Name: Cy_GPIO_Read +****************************************************************************//** +* +* \brief Reads the current logic level on the input buffer of the pin. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register. +* Bit position 8 is the routed pin through the port glitch filter. +* +* \return +* Logic level present on the pin +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_Read +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_Read(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_FILTER_PIN_VALID(pinNum)); + + return (base->IN >> (pinNum)) & CY_GPIO_IN_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_Write +****************************************************************************//** +* +* \brief Write a logic 0 or logic 1 state to the output driver. +* +* This function should be used only for software driven pins. It does not have +* any effect on peripheral driven pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param value +* Logic level to drive out on the pin +* +* \return +* void +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_Write +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_Write(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(value)); + + /* Thread-safe: Directly access the pin registers instead of base->OUT */ + if(0UL == value) + { + base->OUT_CLR = CY_GPIO_OUT_MASK << pinNum; + } + else + { + base->OUT_SET = CY_GPIO_OUT_MASK << pinNum; + } +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_ReadOut +****************************************************************************//** +* +* \brief Reads the current logic level on the pin output driver. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* Logic level on the pin output driver +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_ReadOut +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_ReadOut(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + return (base->OUT >> pinNum) & CY_GPIO_OUT_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_Set +****************************************************************************//** +* +* \brief Set a pin output to logic state high. +* +* This function should be used only for software driven pins. It does not have +* any effect on peripheral driven pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* void +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_Set +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_Set(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + base->OUT_SET = CY_GPIO_OUT_MASK << pinNum; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_Clr +****************************************************************************//** +* +* \brief Set a pin output to logic state Low. +* +* This function should be used only for software driven pins. It does not have +* any effect on peripheral driven pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* void +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_Clr +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_Clr(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + base->OUT_CLR = CY_GPIO_OUT_MASK << pinNum; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_Inv +****************************************************************************//** +* +* \brief Set a pin output logic state to the inverse of the current output +* logic state. +* +* This function should be used only for software driven pins. It does not have +* any effect on peripheral driven pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* void +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_Inv +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_Inv(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + base->OUT_INV = CY_GPIO_OUT_MASK << pinNum; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_SetDrivemode +****************************************************************************//** +* +* \brief Configures the pin output buffer drive mode and input buffer enable. +* +* The output buffer drive mode and input buffer enable are combined into a single +* parameter. The drive mode controls the behavior of the pin in general. +* Enabling the input buffer allows the digital pin state to be read but also +* contributes to extra current consumption. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param value +* Pin drive mode. Options are detailed in \ref group_gpio_driveModes macros +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetDrivemode +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetDrivemode(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value) +{ + uint32_t tempReg; + uint32_t pinLoc; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_DM_VALID(value)); + + pinLoc = pinNum << CY_GPIO_DRIVE_MODE_OFFSET; + tempReg = (base->CFG & ~(CY_GPIO_CFG_DM_MASK << pinLoc)); + base->CFG = tempReg | ((value & CY_GPIO_CFG_DM_MASK) << pinLoc); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetDrivemode +****************************************************************************//** +* +* \brief Returns the pin output buffer drive mode and input buffer enable state. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* Pin drive mode. Options are detailed in \ref group_gpio_driveModes macros +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetDrivemode +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetDrivemode(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + return (base->CFG >> (pinNum << CY_GPIO_DRIVE_MODE_OFFSET)) & CY_GPIO_CFG_DM_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_SetVtrip +****************************************************************************//** +* +* \brief Configures the GPIO pin input buffer voltage threshold mode. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param value +* Pin voltage threshold mode. Options are detailed in \ref group_gpio_vtrip macros +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetVtrip +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetVtrip(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value) +{ + uint32_t tempReg; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(value)); + + tempReg = base->CFG_IN & ~(CY_GPIO_CFG_IN_VTRIP_SEL_MASK << pinNum); + base->CFG_IN = tempReg | ((value & CY_GPIO_CFG_IN_VTRIP_SEL_MASK) << pinNum); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetVtrip +****************************************************************************//** +* +* \brief Returns the pin input buffer voltage threshold mode. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* Pin voltage threshold mode. Options are detailed in \ref group_gpio_vtrip macros +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetVtrip +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetVtrip(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + return (base->CFG_IN >> pinNum) & CY_GPIO_CFG_IN_VTRIP_SEL_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_SetSlewRate +****************************************************************************//** +* +* \brief Configures the pin output buffer slew rate. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param value +* Pin slew rate. Options are detailed in \ref group_gpio_slewRate macros +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetSlewRate +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetSlewRate(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value) +{ + uint32_t tempReg; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(value)); + + tempReg = base->CFG_OUT & ~(CY_GPIO_CFG_OUT_SLOW_MASK << pinNum); + base->CFG_OUT = tempReg | ((value & CY_GPIO_CFG_OUT_SLOW_MASK) << pinNum); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetSlewRate +****************************************************************************//** +* +* \brief Returns the pin output buffer slew rate. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* Pin slew rate. Options are detailed in \ref group_gpio_slewRate macros +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetSlewRate +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetSlewRate(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + return (base->CFG_OUT >> pinNum) & CY_GPIO_CFG_OUT_SLOW_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_SetDriveSel +****************************************************************************//** +* +* \brief Configures the pin output buffer drive strength. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param value +* Pin drive strength. Options are detailed in \ref group_gpio_driveStrength macros +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetDriveSel +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetDriveSel(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value) +{ + uint32_t tempReg; + uint32_t pinLoc; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_DRIVE_SEL_VALID(value)); + + pinLoc = (uint32_t)(pinNum << 1u) + CY_GPIO_CFG_OUT_DRIVE_OFFSET; + tempReg = base->CFG_OUT & ~(CY_GPIO_CFG_OUT_DRIVE_SEL_MASK << pinLoc); + base->CFG_OUT = tempReg | ((value & CY_GPIO_CFG_OUT_DRIVE_SEL_MASK) << pinLoc); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetDriveSel +****************************************************************************//** +* +* \brief Returns the pin output buffer drive strength. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* Pin drive strength. Options are detailed in \ref group_gpio_driveStrength macros +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetDriveSel +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetDriveSel(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + return ((base->CFG_OUT >> ((uint32_t)(pinNum << 1u) + CY_GPIO_CFG_OUT_DRIVE_OFFSET)) + & CY_GPIO_CFG_OUT_DRIVE_SEL_MASK); +} + +/** \} group_gpio_functions_gpio */ + +/** +* \addtogroup group_gpio_functions_sio +* \{ +*/ + +/******************************************************************************* +* Function Name: Cy_GPIO_SetVregEn +****************************************************************************//** +* +* \brief Configures the SIO pin pair output buffer regulation mode. +* +* Note that this function has no effect on non-SIO pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param value +* SIO pair output buffer regulator mode. Options are detailed in \ref group_gpio_sioVreg macros +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetVregEn +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetVregEn(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value) +{ + uint32_t tempReg; + uint32_t pinLoc; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(value)); + + pinLoc = (pinNum & CY_GPIO_SIO_ODD_PIN_MASK) << CY_GPIO_CFG_SIO_OFFSET; + tempReg = base->CFG_SIO & ~(CY_GPIO_VREG_EN_MASK << pinLoc); + base->CFG_SIO = tempReg | ((value & CY_GPIO_VREG_EN_MASK) << pinLoc); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetVregEn +****************************************************************************//** +* +* \brief Returns the SIO pin pair output buffer regulation mode. +* +* Note that this function has no effect on non-SIO pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* SIO pair output buffer regulator mode. Options are detailed in \ref group_gpio_sioVreg macros +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetVregEn +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetVregEn(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + return (base->CFG_SIO >> ((pinNum & CY_GPIO_SIO_ODD_PIN_MASK) << CY_GPIO_CFG_SIO_OFFSET)) & CY_GPIO_VREG_EN_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_SetIbufMode +****************************************************************************//** +* +* \brief Configures the SIO pin pair input buffer mode. +* +* Note that this function has no effect on non-SIO pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param value +* SIO pair input buffer mode. Options are detailed in \ref group_gpio_sioIbuf macros +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetIbufMode +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetIbufMode(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value) +{ + uint32_t tempReg; + uint32_t pinLoc; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(value)); + + pinLoc = ((pinNum & CY_GPIO_SIO_ODD_PIN_MASK) << CY_GPIO_CFG_SIO_OFFSET) + CY_GPIO_IBUF_SHIFT; + tempReg = (base->CFG_SIO & ~(CY_GPIO_IBUF_MASK << pinLoc)); + base->CFG_SIO = tempReg | ((value & CY_GPIO_IBUF_MASK) << pinLoc); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetIbufMode +****************************************************************************//** +* +* \brief Returns the SIO pin pair input buffer mode. +* +* Note that this function has no effect on non-SIO pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* SIO pair input buffer mode. Options are detailed in \ref group_gpio_sioIbuf macros +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetIbufMode +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetIbufMode(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + return (base->CFG_SIO >> (((pinNum & CY_GPIO_SIO_ODD_PIN_MASK) << CY_GPIO_CFG_SIO_OFFSET) + CY_GPIO_IBUF_SHIFT)) & CY_GPIO_IBUF_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_SetVtripSel +****************************************************************************//** +* +* \brief Configures the SIO pin pair input buffer trip point. +* +* Note that this function has no effect on non-SIO pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param value +* SIO pair input buffer trip point. Options are detailed in \ref group_gpio_sioVtrip macros +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetVtripSel +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetVtripSel(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value) +{ + uint32_t tempReg; + uint32_t pinLoc; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(value)); + + pinLoc = ((pinNum & CY_GPIO_SIO_ODD_PIN_MASK) << CY_GPIO_CFG_SIO_OFFSET) + CY_GPIO_VTRIP_SEL_SHIFT; + tempReg = (base->CFG_SIO & ~(CY_GPIO_VTRIP_SEL_MASK << pinLoc)); + base->CFG_SIO = tempReg | ((value & CY_GPIO_VTRIP_SEL_MASK) << pinLoc); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetVtripSel +****************************************************************************//** +* +* \brief Returns the SIO pin pair input buffer trip point. +* +* Note that this function has no effect on non-SIO pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* SIO pair input buffer trip point. Options are detailed in \ref group_gpio_sioVtrip macros +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetVtripSel +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetVtripSel(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + return (base->CFG_SIO >> (((pinNum & CY_GPIO_SIO_ODD_PIN_MASK) << CY_GPIO_CFG_SIO_OFFSET) + CY_GPIO_VTRIP_SEL_SHIFT)) & CY_GPIO_VTRIP_SEL_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_SetVrefSel +****************************************************************************//** +* +* \brief Configures the SIO reference voltage for the input buffer trip point. +* +* Note that this function has no effect on non-SIO pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param value +* SIO pair reference voltage. Options are detailed in \ref group_gpio_sioVref macros +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetVrefSel +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetVrefSel(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value) +{ + uint32_t tempReg; + uint32_t pinLoc; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_VREF_SEL_VALID(value)); + + pinLoc = ((pinNum & CY_GPIO_SIO_ODD_PIN_MASK) << CY_GPIO_CFG_SIO_OFFSET) + CY_GPIO_VREF_SEL_SHIFT; + tempReg = (base->CFG_SIO & ~(CY_GPIO_VREF_SEL_MASK << pinLoc)); + base->CFG_SIO = tempReg | ((value & CY_GPIO_VREF_SEL_MASK) << pinLoc); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetVrefSel +****************************************************************************//** +* +* \brief Returns the SIO reference voltage for the input buffer trip point. +* +* Note that this function has no effect on non-SIO pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* SIO pair reference voltage. Options are detailed in \ref group_gpio_sioVref macros +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetVrefSel +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetVrefSel(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + return (base->CFG_SIO >> (((pinNum & CY_GPIO_SIO_ODD_PIN_MASK) << CY_GPIO_CFG_SIO_OFFSET) + CY_GPIO_VREF_SEL_SHIFT)) & CY_GPIO_VREF_SEL_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_SetVohSel +****************************************************************************//** +* +* \brief Configures the regulated output reference multiplier for the SIO pin pair. +* +* The regulated output reference controls both the output level of digital output +* pin and the input trip point of digital input pin in the SIO pair. +* +* Note that this function has no effect on non-SIO pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \param value +* SIO pair reference voltage. Options are detailed in \ref group_gpio_sioVoh macros +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetVohSel +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetVohSel(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value) +{ + uint32_t tempReg; + uint32_t pinLoc; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_VOH_SEL_VALID(value)); + + pinLoc = ((pinNum & CY_GPIO_SIO_ODD_PIN_MASK) << CY_GPIO_CFG_SIO_OFFSET) + CY_GPIO_VOH_SEL_SHIFT; + tempReg = (base->CFG_SIO & ~(CY_GPIO_VOH_SEL_MASK << pinLoc)); + base->CFG_SIO = tempReg | ((value & CY_GPIO_VOH_SEL_MASK) << pinLoc); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetVohSel +****************************************************************************//** +* +* \brief Returns the regulated output reference multiplier for the SIO pin pair. +* +* Note that this function has no effect on non-SIO pins. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* +* \return +* SIO pair reference voltage. Options are detailed in \ref group_gpio_sioVoh macros +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetVohSel +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetVohSel(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(pinNum)); + + return (base->CFG_SIO >> (((pinNum & CY_GPIO_SIO_ODD_PIN_MASK) << CY_GPIO_CFG_SIO_OFFSET) + CY_GPIO_VOH_SEL_SHIFT)) & CY_GPIO_VOH_SEL_MASK; +} + +/** \} group_gpio_functions_sio */ + +/** +* \addtogroup group_gpio_functions_interrupt +* \{ +*/ + +/******************************************************************************* +* Function Name: Cy_GPIO_GetInterruptStatus +****************************************************************************//** +* +* \brief Returns the current unmasked interrupt state of the pin. +* +* The core processor's NVIC is triggered by the masked interrupt bits. This +* function allows reading the unmasked interrupt state. Whether the bit +* positions actually trigger the interrupt are defined by the interrupt mask bits. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* Bit position 8 is the routed pin through the port glitch filter. +* +* \return +* 0 = Pin interrupt condition not detected +* 1 = Pin interrupt condition detected +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_GetInterruptStatus +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptStatus(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_FILTER_PIN_VALID(pinNum)); + + return (base->INTR >> pinNum) & CY_GPIO_INTR_STATUS_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_ClearInterrupt +****************************************************************************//** +* +* \brief Clears the triggered pin interrupt. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register +* Bit position 8 is the routed pin through the port glitch filter. +* +* \return +* void +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_ClearInterrupt +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_ClearInterrupt(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_FILTER_PIN_VALID(pinNum)); + + /* Any INTR MMIO registers AHB clearing must be preceded with an AHB read access */ + (void)base->INTR; + + base->INTR = CY_GPIO_INTR_STATUS_MASK << pinNum; + + /* This read ensures that the initial write has been flushed out to the hardware */ + (void)base->INTR; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_SetInterruptMask +****************************************************************************//** +* +* \brief Configures the pin interrupt to be forwarded to the CPU NVIC. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register. +* Bit position 8 is the routed pin through the port glitch filter. +* +* \param value +* 0 = Pin interrupt not forwarded to CPU interrupt controller +* 1 = Pin interrupt masked and forwarded to CPU interrupt controller +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetInterruptMask +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetInterruptMask(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value) +{ + uint32_t tempReg; + + CY_ASSERT_L2(CY_GPIO_IS_FILTER_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_VALUE_VALID(value)); + + tempReg= base->INTR_MASK & ~(CY_GPIO_INTR_EN_MASK << pinNum); + base->INTR_MASK = tempReg | ((value & CY_GPIO_INTR_EN_MASK) << pinNum); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetInterruptMask +****************************************************************************//** +* +* \brief Returns the state of the pin interrupt mask. +* +* This mask is used to determine whether the pin is configured to be forwarded +* to the CPU NVIC. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register. +* Bit position 8 is the routed pin through the port glitch filter. +* +* \return +* 0 = Pin interrupt not forwarded to CPU interrupt controller +* 1 = Pin interrupt masked and forwarded to CPU interrupt controller +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetInterruptMask +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptMask(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_FILTER_PIN_VALID(pinNum)); + + return (base->INTR_MASK >> pinNum) & CY_GPIO_INTR_EN_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetInterruptStatusMasked +****************************************************************************//** +* +* \brief Return the pin's current interrupt state after being masked. +* +* The core processor's NVIC is triggered by the masked interrupt bits. This +* function allows reading this masked interrupt state. Note that the bits that +* are not masked will not be forwarded to the NVIC. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register. +* Bit position 8 is the routed pin through the port glitch filter. +* +* \return +* 0 = Pin interrupt not detected or not forwarded to CPU interrupt controller +* 1 = Pin interrupt detected and forwarded to CPU interrupt controller +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_GetInterruptStatusMasked +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptStatusMasked(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_FILTER_PIN_VALID(pinNum)); + + return (base->INTR_MASKED >> pinNum) & CY_GPIO_INTR_MASKED_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_SetSwInterrupt +****************************************************************************//** +* +* \brief Force a pin interrupt to trigger. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register. +* Bit position 8 is the routed pin through the port glitch filter. +* +* \return +* void +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetSwInterrupt +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetSwInterrupt(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_FILTER_PIN_VALID(pinNum)); + + base->INTR_SET = CY_GPIO_INTR_SET_MASK << pinNum; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_SetInterruptEdge +****************************************************************************//** +* +* \brief Configures the type of edge that will trigger a pin interrupt. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register. +* Bit position 8 is the routed pin through the port glitch filter. +* +* \param value +* Pin interrupt mode. Options are detailed in \ref group_gpio_interruptTrigger macros +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetInterruptEdge +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetInterruptEdge(GPIO_PRT_Type* base, uint32_t pinNum, uint32_t value) +{ + uint32_t tempReg; + uint32_t pinLoc; + + CY_ASSERT_L2(CY_GPIO_IS_FILTER_PIN_VALID(pinNum)); + CY_ASSERT_L2(CY_GPIO_IS_INT_EDGE_VALID(value)); + + pinLoc = pinNum << CY_GPIO_INTR_CFG_OFFSET; + tempReg = base->INTR_CFG & ~(CY_GPIO_INTR_EDGE_MASK << pinLoc); + base->INTR_CFG = tempReg | ((value & CY_GPIO_INTR_EDGE_MASK) << pinLoc); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetInterruptEdge +****************************************************************************//** +* +* \brief Returns the current pin interrupt edge type. +* +* \param base +* Pointer to the pin's port register base address +* +* \param pinNum +* Position of the pin bit-field within the port register. +* Bit position 8 is the routed pin through the port glitch filter. +* +* \return +* Pin interrupt mode. Options are detailed in \ref group_gpio_interruptTrigger macros +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetInterruptEdge +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptEdge(GPIO_PRT_Type* base, uint32_t pinNum) +{ + CY_ASSERT_L2(CY_GPIO_IS_FILTER_PIN_VALID(pinNum)); + + return (base->INTR_CFG >> (pinNum << CY_GPIO_INTR_CFG_OFFSET)) & CY_GPIO_INTR_EDGE_MASK; +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_SetFilter +****************************************************************************//** +* +* \brief Configures which pin on the port connects to the port-specific glitch filter. +* +* Each port contains a single 50ns glitch filter. Any of the pins on the port +* can be routed to this filter such that the input signal is filtered before +* reaching the edge-detect interrupt circuitry. The state of the filterred pin +* can also be read by calling the Cy_GPIO_Read() function. +* +* \param base +* Pointer to the pin's port register base address +* +* \param value +* The number of the port pin to route to the port filter (0...7) +* +* \return +* void +* +* \note +* This function modifies a port register in a read-modify-write operation. It is +* not thread safe as the resource is shared among multiple pins on a port. +* +* \note +* The filtered pin does not have an associated HSIOM connection. Therefore +* it cannot be routed directly to other peripherals in hardware. +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetFilter +* +*******************************************************************************/ +__STATIC_INLINE void Cy_GPIO_SetFilter(GPIO_PRT_Type* base, uint32_t value) +{ + uint32_t tempReg; + + CY_ASSERT_L2(CY_GPIO_IS_PIN_VALID(value)); + + tempReg = base->INTR_CFG & ~(CY_GPIO_INTR_FLT_EDGE_MASK << CY_GPIO_INTR_FILT_OFFSET); + base->INTR_CFG = tempReg | ((value & CY_GPIO_INTR_FLT_EDGE_MASK) << CY_GPIO_INTR_FILT_OFFSET); +} + + +/******************************************************************************* +* Function Name: Cy_GPIO_GetFilter +****************************************************************************//** +* +* \brief Returns which pin is currently configured to connect to the port-specific +* glitch filter. +* +* Each port contains a single 50ns glitch filter. Any of the pins on the port +* can be routed to this filter such that the input signal is filtered before +* reaching the edge-detect interrupt circuitry. The state of the filterred pin +* can also be read by calling the Cy_GPIO_Read() function. +* +* \param base +* Pointer to the pin's port register base address +* +* \return +* The number of the port pin routed to the port filter (0...7) +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_SetFilter +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetFilter(GPIO_PRT_Type* base) +{ + return (base->INTR_CFG >> CY_GPIO_INTR_FILT_OFFSET) & CY_GPIO_INTR_FLT_EDGE_MASK; +} + + +#if (IOSS_GPIO_GPIO_PORT_NR_0_31 != 0) || defined (CY_DOXYGEN) + +/******************************************************************************* +* Function Name: Cy_GPIO_GetInterruptCause0 +****************************************************************************//** +* +* \brief Returns the interrupt status for ports 0 to 31. +* +* \return +* 0 = Interrupt not detected on port +* 1 = Interrupt detected and sent to CPU interrupt controller on port +* +* \funcusage +* \snippet gpio/gpio_v1_10_sut_01.cydsn/main_cm4.c snippet_Cy_GPIO_GetInterruptCause0 +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause0(void) +{ + return GPIO->INTR_CAUSE0; +} + +#endif + +#if (IOSS_GPIO_GPIO_PORT_NR_32_63 != 0) || defined (CY_DOXYGEN) + +/******************************************************************************* +* Function Name: Cy_GPIO_GetInterruptCause1 +****************************************************************************//** +* +* \brief Returns the interrupt status for ports 32 to 63. +* +* \return +* 0 = Interrupt not detected on port +* 1 = Interrupt detected and sent to CPU interrupt controller on port +* +* \funcusage +* Refer to the Cy_GPIO_GetInterruptCause0() example. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause1(void) +{ + return GPIO->INTR_CAUSE1; +} + +#endif + +#if (IOSS_GPIO_GPIO_PORT_NR_64_95 != 0) || defined (CY_DOXYGEN) + +/******************************************************************************* +* Function Name: Cy_GPIO_GetInterruptCause2 +****************************************************************************//** +* +* \brief Returns the interrupt status for ports 64 to 95. +* +* \return +* 0 = Interrupt not detected on port +* 1 = Interrupt detected and sent to CPU interrupt controller on port +* +* \funcusage +* Refer to the Cy_GPIO_GetInterruptCause0() example. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause2(void) +{ + return GPIO->INTR_CAUSE2; +} + +#endif + +#if (IOSS_GPIO_GPIO_PORT_NR_96_127 != 0) || defined (CY_DOXYGEN) + +/******************************************************************************* +* Function Name: Cy_GPIO_GetInterruptCause3 +****************************************************************************//** +* +* \brief Returns the interrupt status for ports 96 to 127. +* +* \return +* 0 = Interrupt not detected on port +* 1 = Interrupt detected and sent to CPU interrupt controller on port +* +* \funcusage +* Refer to the Cy_GPIO_GetInterruptCause0() example. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause3(void) +{ + return GPIO->INTR_CAUSE3; +} + +#endif + +/** \} group_gpio_functions_interrupt */ + +/** \} group_gpio_functions */ + +#if defined(__cplusplus) +} +#endif + +#endif /* CY_GPIO_H */ + +/** \} group_gpio */ + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/i2s/cy_i2s.c b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/i2s/cy_i2s.c new file mode 100644 index 0000000000..38d316dc09 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/i2s/cy_i2s.c @@ -0,0 +1,287 @@ +/***************************************************************************//** +* \file cy_i2s.c +* \version 2.0.1 +* +* The source code file for the I2S driver. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include "cy_i2s.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/******************************************************************************* +* Function Name: Cy_I2S_Init +****************************************************************************//** +* +* Initializes the I2S module in accordance with a configuration structure. +* +* \pre If the I2S module is initialized previously, the \ref Cy_I2S_DeInit() +* must be called before calling this function. +* +* \param base The pointer to the I2S instance address. +* +* \param config The pointer to a configuration structure. +* +* \return error / status code. See \ref cy_en_i2s_status_t. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_Init +* +*******************************************************************************/ +cy_en_i2s_status_t Cy_I2S_Init(I2S_Type * base, cy_stc_i2s_config_t const * config) +{ + cy_en_i2s_status_t ret = CY_I2S_BAD_PARAM; + + if((NULL != base) && (NULL != config)) + { + cy_en_i2s_ws_pw_t wsPulseWidth; + cy_en_i2s_len_t channelLength; + uint32_t channels; + uint32_t clockDiv = (uint32_t)config->clkDiv - 1U; + + CY_ASSERT_L2(CY_I2S_IS_CLK_DIV_VALID(clockDiv)); + + /* The clock setting */ + base->CLOCK_CTL = _VAL2FLD(I2S_CLOCK_CTL_CLOCK_DIV, clockDiv) | + _BOOL2FLD(I2S_CLOCK_CTL_CLOCK_SEL, config->extClk); + + /* The Tx setting */ + if (config->txEnabled) + { + CY_ASSERT_L3(CY_I2S_IS_ALIGNMENT_VALID(config->txAlignment)); + CY_ASSERT_L3(CY_I2S_IS_OVHDATA_VALID(config->txOverheadValue)); + + if ((CY_I2S_TDM_MODE_A == config->txAlignment) || (CY_I2S_TDM_MODE_B == config->txAlignment)) + { + channels = (uint32_t)config->txChannels - 1UL; + wsPulseWidth = config->txWsPulseWidth; + channelLength = CY_I2S_LEN32; + + CY_ASSERT_L2(CY_I2S_IS_CHANNELS_VALID(channels)); + CY_ASSERT_L3(CY_I2S_IS_WSPULSE_VALID(wsPulseWidth)); + CY_ASSERT_L3(CY_I2S_IS_LEN_VALID(config->txWordLength)); + } + else + { + channels = 1UL; + wsPulseWidth = CY_I2S_WS_ONE_CHANNEL_LENGTH; + channelLength = config->txChannelLength; + + CY_ASSERT_L3(CY_I2S_IS_CHAN_WORD_VALID(channelLength, config->txWordLength)); + } + + CY_ASSERT_L2(CY_I2S_IS_TRIG_LEVEL_VALID(config->txFifoTriggerLevel, channels)); + + base->TX_WATCHDOG = config->txWatchdogValue; + + base->TX_CTL = _VAL2FLD(I2S_TX_CTL_I2S_MODE, config->txAlignment) | + _BOOL2FLD(I2S_TX_CTL_B_CLOCK_INV, config->txSdoLatchingTime) | + _VAL2FLD(I2S_TX_CTL_CH_NR, channels) | + _BOOL2FLD(I2S_TX_CTL_MS, config->txMasterMode) | + _VAL2FLD(I2S_TX_CTL_WS_PULSE, wsPulseWidth) | + _BOOL2FLD(I2S_TX_CTL_WD_EN, config->txWatchdogEnable) | + _BOOL2FLD(I2S_TX_CTL_SCKO_POL, config->txSckoInversion) | + _BOOL2FLD(I2S_TX_CTL_SCKI_POL, config->txSckiInversion) | + _VAL2FLD(I2S_TX_CTL_CH_LEN, channelLength) | + _VAL2FLD(I2S_TX_CTL_WORD_LEN, config->txWordLength) | + _VAL2FLD(I2S_TX_CTL_OVHDATA, config->txOverheadValue); + } + + /* The Rx setting */ + if (config->rxEnabled) + { + CY_ASSERT_L3(CY_I2S_IS_ALIGNMENT_VALID(config->rxAlignment)); + + if ((CY_I2S_TDM_MODE_A == config->rxAlignment) || (CY_I2S_TDM_MODE_B == config->rxAlignment)) + { + channels = (uint32_t)config->rxChannels - 1UL; + wsPulseWidth = config->rxWsPulseWidth; + channelLength = CY_I2S_LEN32; + + CY_ASSERT_L2(CY_I2S_IS_CHANNELS_VALID(channels)); + CY_ASSERT_L3(CY_I2S_IS_WSPULSE_VALID(wsPulseWidth)); + CY_ASSERT_L3(CY_I2S_IS_LEN_VALID(config->rxWordLength)); + } + else + { + channels = 1UL; + wsPulseWidth = CY_I2S_WS_ONE_CHANNEL_LENGTH; + channelLength = config->rxChannelLength; + + CY_ASSERT_L3(CY_I2S_IS_CHAN_WORD_VALID(channelLength, config->rxWordLength)); + } + + CY_ASSERT_L2(CY_I2S_IS_TRIG_LEVEL_VALID(config->rxFifoTriggerLevel, channels)); + + base->RX_WATCHDOG = config->rxWatchdogValue; + + base->RX_CTL = _VAL2FLD(I2S_RX_CTL_I2S_MODE, config->rxAlignment) | + _BOOL2FLD(I2S_RX_CTL_B_CLOCK_INV, config->rxSdiLatchingTime) | + _VAL2FLD(I2S_RX_CTL_CH_NR, channels) | + _BOOL2FLD(I2S_RX_CTL_MS, config->rxMasterMode) | + _VAL2FLD(I2S_RX_CTL_WS_PULSE, wsPulseWidth) | + _BOOL2FLD(I2S_RX_CTL_WD_EN, config->rxWatchdogEnable) | + _BOOL2FLD(I2S_RX_CTL_SCKO_POL, config->rxSckoInversion) | + _BOOL2FLD(I2S_RX_CTL_SCKI_POL, config->rxSckiInversion) | + _VAL2FLD(I2S_RX_CTL_CH_LEN, channelLength) | + _VAL2FLD(I2S_RX_CTL_WORD_LEN, config->rxWordLength) | + _BOOL2FLD(I2S_RX_CTL_BIT_EXTENSION, config->rxSignExtension); + } + + /* The I2S enable setting */ + if (config->txEnabled) + { + base->CTL |= I2S_CTL_TX_ENABLED_Msk; + } + + if (config->rxEnabled) + { + base->CTL |= I2S_CTL_RX_ENABLED_Msk; + } + + /* The FIFO setting */ + if (config->txEnabled) + { + base->TX_FIFO_CTL = _VAL2FLD(I2S_TX_FIFO_CTL_TRIGGER_LEVEL, config->txFifoTriggerLevel); + + base->TR_CTL |= _BOOL2FLD(I2S_TR_CTL_TX_REQ_EN, config->txDmaTrigger); + } + + if (config->rxEnabled) + { + base->RX_FIFO_CTL = _VAL2FLD(I2S_RX_FIFO_CTL_TRIGGER_LEVEL, config->rxFifoTriggerLevel); + + base->TR_CTL |= _BOOL2FLD(I2S_TR_CTL_RX_REQ_EN, config->rxDmaTrigger); + } + + ret = CY_I2S_SUCCESS; + } + + return (ret); +} + + +/******************************************************************************* +* Function Name: Cy_I2S_DeInit +****************************************************************************//** +* +* Uninitializes the I2S module (reverts default register values). +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_DeInit +* +*******************************************************************************/ +void Cy_I2S_DeInit(I2S_Type * base) +{ + base->INTR_MASK = 0UL; /* Disable interrupts prior to stopping the operation */ + base->CMD = 0UL; + base->TR_CTL = 0UL; + base->TX_FIFO_CTL = 0UL; + base->RX_FIFO_CTL = 0UL; + base->CTL = 0UL; + base->TX_CTL = CY_I2S_TX_CTL_DEFAULT; + base->RX_CTL = CY_I2S_RX_CTL_DEFAULT; + base->TX_WATCHDOG = 0UL; + base->RX_WATCHDOG = 0UL; + base->CLOCK_CTL = 0UL; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_DeepSleepCallback +****************************************************************************//** +* +* This is a callback function to be used at the application layer to +* manage an I2S operation during the Deep-Sleep cycle. It stores the I2S state +* (Tx/Rx enabled/disabled/paused) into the context structure and stops the +* communication before entering into Deep-Sleep power mode and restores the I2S +* state after waking up. +* +* \param +* callbackParams - The pointer to the callback parameters structure, +* see \ref cy_stc_syspm_callback_params_t. +* +* \return the SysPm callback status \ref cy_en_syspm_status_t. +* +* \note Use the \ref cy_stc_i2s_context_t data type for definition of the +* *context element of the \ref cy_stc_syspm_callback_params_t strusture. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_DeepSleepCallback +* +*******************************************************************************/ +cy_en_syspm_status_t Cy_I2S_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams) +{ + cy_en_syspm_status_t ret = CY_SYSPM_SUCCESS; + CY_ASSERT_L1(NULL != callbackParams->context); + I2S_Type * locBase = (I2S_Type*) callbackParams->base; + uint32_t * locInterruptMask = (uint32_t*) &(((cy_stc_i2s_context_t*)(callbackParams->context))->interruptMask); + uint32_t * locState = (uint32_t*) &(((cy_stc_i2s_context_t*)(callbackParams->context))->enableState); + + switch(callbackParams->mode) + { + case CY_SYSPM_CHECK_READY: + case CY_SYSPM_CHECK_FAIL: + break; + + case CY_SYSPM_BEFORE_TRANSITION: + *locInterruptMask = Cy_I2S_GetInterruptMask(locBase); /* Store I2S interrupts */ + *locState = Cy_I2S_GetCurrentState(locBase); /* Store I2S state */ + if (0UL != (*locState & I2S_CMD_TX_START_Msk)) + { + Cy_I2S_DisableTx(locBase); /* Stop TX operation */ + } + if (0UL != (*locState & I2S_CMD_RX_START_Msk)) + { + Cy_I2S_DisableRx(locBase); /* Stop RX operation */ + } + Cy_I2S_SetInterruptMask(locBase, 0UL); /* Disable I2S interrupts */ + /* Unload FIFOs in order not to lose data (if needed) */ + break; + + case CY_SYSPM_AFTER_TRANSITION: + if (0UL != (*locState & I2S_CMD_RX_START_Msk)) + { + Cy_I2S_ClearRxFifo(locBase); /* Clear the RX FIFO */ + Cy_I2S_EnableRx(locBase); /* Start RX operation */ + } + if (0UL != (*locState & I2S_CMD_TX_START_Msk)) + { + Cy_I2S_ClearTxFifo(locBase); /* Clear the TX FIFO */ + Cy_I2S_WriteTxData(locBase, 0UL); /* Fill at least one TX frame */ + Cy_I2S_WriteTxData(locBase, 0UL); + if (0UL != (*locState & I2S_CMD_TX_PAUSE_Msk)) + { + Cy_I2S_PauseTx(locBase); /* Restore the TX paused state */ + } + Cy_I2S_EnableTx(locBase); /* Start TX operation */ + } + Cy_I2S_ClearInterrupt(locBase, *locInterruptMask); /* Clear possible pending I2S interrupts */ + Cy_I2S_SetInterruptMask(locBase, *locInterruptMask); /* Restore I2S interrupts */ + break; + + default: + ret = CY_SYSPM_FAIL; + break; + } + + return(ret); +} + + +#ifdef __cplusplus +} +#endif + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/i2s/cy_i2s.h b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/i2s/cy_i2s.h new file mode 100644 index 0000000000..0e89d1a5c4 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/i2s/cy_i2s.h @@ -0,0 +1,1087 @@ +/***************************************************************************//** +* \file cy_i2s.h +* \version 2.0.1 +* +* The header file of the I2S driver. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +/** +* \defgroup group_i2s Inter-IC Sound (I2S) +* \{ +* The I2S driver provides a function API to manage Inter-IC Sound. I2S is used +* to send digital audio streaming data to external I2S devices, such as audio +* codecs or simple DACs. It can also receive digital audio streaming data. +* +* Features: +* * An industry standard NXP I2S interface. +* * Supports master/slave TX/RX operation. +* * Programmable Channel/Word Lengths. +* * Supports External Clock operation. +* +* The I2S bus is an industry standard. The hardware interface was +* developed by Philips Semiconductors (now NXP Semiconductors). +* +* \section group_i2s_configuration_considerations Configuration Considerations +* +* To set up an I2S, provide the configuration parameters in the +* \ref cy_stc_i2s_config_t structure. +* +* For example, for Tx configuration, set txEnabled to true, configure +* txDmaTrigger (depending on whether DMA is going to be used or not), set +* extClk (if an external clock is used), provide clkDiv, txMasterMode, +* txAlignment, txChannels (only 2 is supported in I2S and Left Justified modes) +* txSdoLatchingTime (for slave mode only), txChannelLength, txWordLength, +* txWsPulseWidth (for TMD modes only), txWatchdogEnable and txWatchdogValue +* (both for Slave mode only, and when the watchdog interrupt will be used), +* either txSckoInversion or txSckiInversion (based on txMasterMode setting), +* txFifoTriggerLevel (when the Trig interrupt will be used) and txOverheadValue +* (only when the word length is less than channel length). +* A similar setup is for the Rx configuration. +* +* To initialize the I2S block, call the \ref Cy_I2S_Init function, providing the +* filled \ref cy_stc_i2s_config_t structure. +* Before starting the transmission, clear the FIFO \ref Cy_I2S_ClearTxFifo, then +* fill the first Tx data frame by calling \ref Cy_I2S_WriteTxData once for each +* channel (e.g. twice for I2S mode with only two channels) with zero data. Then +* call the \ref Cy_I2S_EnableTx itself. +* For the reception the sequence is the same except for filling the first data +* frame, just RX FIFO clearing is enough. +* +* For example: +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_Init +* +* If you use a DMA, the DMA channel should be previously configured. The I2S interrupts +* (if applicable) can be enabled by calling \ref Cy_I2S_SetInterruptMask. +* +* For example, if the trigger interrupt is used, during operation the ISR +* should call the \ref Cy_I2S_WriteTxData as many times as required for your +* FIFO payload, but not more than the FIFO size. Then call \ref Cy_I2S_ClearInterrupt +* with appropriate parameters. +* +* The I2S/Left Justified data formats always contains two data channels. +* They are ordered one-by-one in the FIFOs, left always goes first. +* So in case of mono audio stream transmission, each sample can be put twice +* into the TX FIFO (in this case both channels will sound the same), +* or combined with zeroes: sample1-zero-sample2-zero (in this case only the +* left channel will finally sound, for right-only case zero should go first). +* The TDM frame word order in FIFOs is similar, one-by-one. +* +* If a DMA is used and the DMA channel is properly configured - no CPU activity +* (or any application code) is needed for I2S operation. +* +* The I2S frame appears as: +* \image html i2s_frame.png +* This is an example for the channel length = 32. A similar is for all the rest +* channel lengths, with one limitation: the word length could be less or equal +* to the channel length. See the device Technical Reference Manual (TRM) +* for more details. +* +* \section group_i2s_more_information More Information +* See: the the I2S chapter of the device technical reference manual (TRM); +* I2S_PDL Component datasheet; +* CE218636 - PSOC 6 MCU INTER-IC SOUND (I2S) EXAMPLE. +* +* \section group_i2s_MISRA MISRA-C Compliance +* The I2S driver has the following specific deviations: +* +* +* +* +* +* +* +* +* +* +* +* +* +*
MISRA RuleRule Class (Required/Advisory)Rule DescriptionDescription of Deviation(s)
11.4AA cast should not be performed between a pointer to the object type and +* a different pointer to the object type.The function \ref Cy_I2S_DeepSleepCallback is a callback of +* \ref cy_en_syspm_status_t type. The cast operation safety in this +* function becomes the user responsibility because the pointer is +* initialized when a callback is registered in the SysPm driver.
+* +* \section group_i2s_changelog Changelog +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
VersionChangesReason for Change
2.0.1Added Low Power Callback sectionDocumentation update and clarification
2.0The slave operation is added, Left Justified and TDM modes are added
1.0Initial version
+* +* \defgroup group_i2s_macros Macros +* \defgroup group_i2s_functions Functions +* \{ +* \defgroup group_i2s_functions_syspm_callback Low Power Callback +* \} +* \defgroup group_i2s_data_structures Data Structures +* \defgroup group_i2s_enums Enumerated Types +*/ + + +#if !defined CY_I2S_H +#define CY_I2S_H + +#include +#include +#include "syslib/cy_syslib.h" +#include "syspm/cy_syspm.h" + +#ifndef CY_IP_MXAUDIOSS + #error "The I2S driver is not supported on this device" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup group_i2s_macros +* \{ +*/ + +/** The driver major version */ +#define CY_I2S_DRV_VERSION_MAJOR 2 + +/** The driver minor version */ +#define CY_I2S_DRV_VERSION_MINOR 0 + +/** The I2S driver identifier */ +#define CY_I2S_ID (CY_PDL_DRV_ID(0x20U)) + +/** +* \defgroup group_i2s_macros_intrerrupt_masks Interrupt Masks +* \{ +*/ + +/** Bit 0: Less entries in the TX FIFO than specified by Trigger Level. */ +#define CY_I2S_INTR_TX_TRIGGER (I2S_INTR_TX_TRIGGER_Msk) +/** Bit 1: TX FIFO is not full. */ +#define CY_I2S_INTR_TX_NOT_FULL (I2S_INTR_TX_NOT_FULL_Msk) +/** Bit 4: TX FIFO is empty, i.e. it has 0 entries. */ +#define CY_I2S_INTR_TX_EMPTY (I2S_INTR_TX_EMPTY_Msk) +/** Bit 5: Attempt to write to a full TX FIFO. */ +#define CY_I2S_INTR_TX_OVERFLOW (I2S_INTR_TX_OVERFLOW_Msk) +/** Bit 6: Attempt to read from an empty TX FIFO. +* This happens when the IP is ready to transfer data and TX_EMPTY is '1'. */ +#define CY_I2S_INTR_TX_UNDERFLOW (I2S_INTR_TX_UNDERFLOW_Msk) +/** Bit 8: Tx watchdog event occurs. */ +#define CY_I2S_INTR_TX_WD (I2S_INTR_TX_WD_Msk) +/** Bit 16: More entries in the RX FIFO than specified by Trigger Level. */ +#define CY_I2S_INTR_RX_TRIGGER (I2S_INTR_RX_TRIGGER_Msk) +/** Bit 18: RX FIFO is not empty. */ +#define CY_I2S_INTR_RX_NOT_EMPTY (I2S_INTR_RX_NOT_EMPTY_Msk) +/** Bit 19: RX FIFO is full. */ +#define CY_I2S_INTR_RX_FULL (I2S_INTR_RX_FULL_Msk) +/** Bit 21: Attempt to write to a full RX FIFO. */ +#define CY_I2S_INTR_RX_OVERFLOW (I2S_INTR_RX_OVERFLOW_Msk) +/** Bit 22: Attempt to read from an empty RX FIFO. */ +#define CY_I2S_INTR_RX_UNDERFLOW (I2S_INTR_RX_UNDERFLOW_Msk) +/** Bit 24: Rx watchdog event occurs. */ +#define CY_I2S_INTR_RX_WD (I2S_INTR_RX_WD_Msk) + +/** \} group_i2s_macros_intrerrupt_masks */ + + +/** +* \defgroup group_i2s_macros_current_state Current State +* \{ +*/ + +/** Transmission is active */ +#define CY_I2S_TX_START (I2S_CMD_TX_START_Msk) +/** Transmission is paused */ +#define CY_I2S_TX_PAUSE (I2S_CMD_TX_PAUSE_Msk) +/** Reception is active */ +#define CY_I2S_RX_START (I2S_CMD_RX_START_Msk) + +/** \} group_i2s_macros_current_state */ + +/** \} group_i2s_macros */ + +/** +* \addtogroup group_i2s_enums +* \{ +*/ + +/** +* I2S status definitions. +*/ + +typedef enum +{ + CY_I2S_SUCCESS = 0x00UL, /**< Successful. */ + CY_I2S_BAD_PARAM = CY_I2S_ID | CY_PDL_STATUS_ERROR | 0x01UL /**< One or more invalid parameters. */ +} cy_en_i2s_status_t; + + +/** +* I2S data alignment. +*/ +typedef enum +{ + CY_I2S_LEFT_JUSTIFIED = 0U, /**< Left justified. */ + CY_I2S_I2S_MODE = 1U, /**< I2S mode. */ + CY_I2S_TDM_MODE_A = 2U, /**< TDM mode A. */ + CY_I2S_TDM_MODE_B = 3U /**< TDM mode B. */ +} cy_en_i2s_alignment_t; + +/** +* I2S channel/word length. +*/ +typedef enum +{ + CY_I2S_LEN8 = 0U, /**< Channel/word length: 8 bit. */ + CY_I2S_LEN16 = 1U, /**< Channel/Word length: 16 bit. */ + CY_I2S_LEN18 = 2U, /**< Channel/Word length: 18 bit. */ + CY_I2S_LEN20 = 3U, /**< Channel/Word length: 20 bit. */ + CY_I2S_LEN24 = 4U, /**< Channel/Word length: 24 bit. */ + CY_I2S_LEN32 = 5U /**< Channel/Word length: 32 bit. */ +} cy_en_i2s_len_t; + +/** +* I2S TX overhead value. +*/ +typedef enum +{ + CY_I2S_OVHDATA_ZERO = 0U, /**< Fill overhead bits by zeroes. */ + CY_I2S_OVHDATA_ONE = 1U, /**< Fill overhead bits by ones. */ +} cy_en_i2s_overhead_t; + +/** +* I2S WS pulse width. +*/ +typedef enum +{ + CY_I2S_WS_ONE_SCK_CYCLE = 0U, /**< WS pulse width is one SCK cycle. */ + CY_I2S_WS_ONE_CHANNEL_LENGTH = 1U, /**< WS pulse width is one channel length. */ +} cy_en_i2s_ws_pw_t; + +/** \} group_i2s_enums */ + +/** +* \addtogroup group_i2s_data_structures +* \{ +*/ + +/** +* I2S initialization configuration. +*/ +typedef struct +{ + bool txEnabled; /**< Enables the I2S TX component: 'false': disabled. 'true': enabled. */ + bool rxEnabled; /**< Enables the I2S RX component: 'false': disabled. 'true': enabled. */ + bool txDmaTrigger; /**< 'false': TX DMA trigger disable, 'true': TX DMA trigger enable. */ + bool rxDmaTrigger; /**< 'false': RX DMA trigger disable, 'true': RX DMA trigger enable. */ + uint8_t clkDiv; /**< CLK_SEL divider: 1: Bypass, 2: 1/2, 3: 1/3, ..., 64: 1/64. */ + bool extClk; /**< 'false': internal clock, 'true': external clock. */ + bool txMasterMode; /**< 'false': TX in slave mode, 'true': TX in master mode. */ + cy_en_i2s_alignment_t txAlignment; /**< TX data alignment, see: #cy_en_i2s_alignment_t. */ + cy_en_i2s_ws_pw_t txWsPulseWidth; /**< TX Word Select pulse width. + The value of this parameter is ignored in I2S and Left Justified modes + the WS pulse width is always "one channel length" in these modes. */ + bool txWatchdogEnable; /**< 'false': TX watchdog disabled, 'true': TX watchdog enabled. */ + uint32_t txWatchdogValue; /**< TX watchdog counter value (32 bit). */ + bool txSdoLatchingTime; /**< 'false': SDO bit starts at falling edge (accordingly to the I2S + Standard, if txSckoInversion is false), + 'true': SDO bit starts at rising edge which goes before the above + mentioned falling edge, i.e. the SDO signal is advanced by 0.5 SCK + period (if txSckoInversion is false). + If txSckoInversion is true - the rising/falling edges just swaps + in above explanations. + Effective only in slave mode, must be false in master mode.*/ + bool txSckoInversion; /**< TX SCKO polarity: + 'false': When transmitter is in master mode, serial data is + transmitted off the falling bit clock edge (accordingly to + the I2S Standard); + 'true': When transmitter is in master mode, serial data is + transmitted off the rising bit clock edge. + Effective only in master mode. */ + bool txSckiInversion; /**< TX SCKI polarity: + 'false': When transmitter is in slave mode, serial data is + transmitted off the falling bit clock edge (accordingly to + the I2S Standard); + 'true': When transmitter is in slave mode, serial data is + transmitted off the rising bit clock edge. + Effective only in slave mode. */ + uint8_t txChannels; /**< Number of TX channels, valid range is 1...8 for TDM modes. + In the I2S and Left Justified modes the value of this parameter is + ignored - the real number of channels is always 2 in these modes. */ + cy_en_i2s_len_t txChannelLength; /**< TX channel length, see #cy_en_i2s_len_t, + the value of this parameter is ignored in TDM modes, the real + channel length is 32 bit in these modes. */ + cy_en_i2s_len_t txWordLength; /**< TX word length, see #cy_en_i2s_len_t, + must be less or equal to txChannelLength. */ + cy_en_i2s_overhead_t txOverheadValue; /**< TX overhead bits value + when the word length is less than the channel length. */ + uint8_t txFifoTriggerLevel; /**< TX FIFO interrupt trigger level (0, 1, ..., 255). */ + bool rxMasterMode; /**< 'false': RX in slave mode, 'true': RX in master mode. */ + cy_en_i2s_alignment_t rxAlignment; /**< RX data alignment, see: #cy_en_i2s_alignment_t. */ + cy_en_i2s_ws_pw_t rxWsPulseWidth; /**< RX Word Select pulse width. + The value of this parameter is ignored in I2S and Left Justified modes + the WS pulse width is always "one channel length" in these modes. */ + bool rxWatchdogEnable; /**< 'false': RX watchdog disabled, 'true': RX watchdog enabled. */ + uint32_t rxWatchdogValue; /**< RX watchdog counter value (32 bit). */ + bool rxSdiLatchingTime; /**< 'false': SDI bit starts at falling edge (accordingly to the I2S + Standard if rxSckoInversion is false), + 'true': SDI bit starts at rising edge which goes after the above + mentioned falling edge, i.e. the SDI signal is delayed by 0.5 SCK + period (if rxSckoInversion is false). + If rxSckoInversion is true - the rising/falling edges just swaps + in above explanations. + Effective only in master mode, must be false in slave mode. */ + bool rxSckoInversion; /**< RX SCKO polarity: + 'false': When receiver is in master mode, serial data is + captured by the rising bit clock edge (accordingly to the + I2S Standard); + 'true': When receiver is in master mode, serial data is + captured by the falling bit clock edge. + Effective only in master mode. */ + bool rxSckiInversion; /**< RX SCKI polarity: + 'false': When receiver is in slave mode, serial data is + captured by the rising bit clock edge (accordingly to the + I2S Standard); + 'true': When receiver is in slave mode, serial data is + captured by the falling bit clock edge. + Effective only in slave mode. */ + uint8_t rxChannels; /**< Number of RX channels, valid range is 1...8 for TDM modes. + In the I2S and Left Justified modes the value of this parameter is + ignored - the real number of channels is always 2 in these modes. */ + cy_en_i2s_len_t rxChannelLength; /**< RX channel length, see #cy_en_i2s_len_t, + the value of this parameter is ignored in TDM modes, the real + channel length is 32 bit in these modes. */ + cy_en_i2s_len_t rxWordLength; /**< RX word length, see #cy_en_i2s_len_t, + must be less or equal to rxChannelLength. */ + bool rxSignExtension; /**< RX value sign extension (when the word length is less than 32 bits), + 'false': all MSB are filled by zeroes, + 'true': all MSB are filled by the original sign bit value. */ + uint8_t rxFifoTriggerLevel; /**< RX FIFO interrupt trigger level + (0, 1, ..., (255 - (number of channels))). */ +} cy_stc_i2s_config_t; + + +/** + * The I2S backup structure type to be used for the SysPm callback. + * \ref Cy_I2S_DeepSleepCallback context definition. + * + * \cond Also can be used for other purposes to store the current Tx/Rx + * operation state and interrupt settings - the factors that are usually + * changed on the fly. \endcond + */ +typedef struct +{ + uint32_t enableState; /**< Stores the I2S state */ + uint32_t interruptMask; /**< Stores the I2S interrupt mask */ +} cy_stc_i2s_context_t; + +/** \} group_i2s_data_structures */ + +/** \cond INTERNAL */ +/****************************************************************************** + * Local definitions +*******************************************************************************/ + +#define CY_I2S_INTR_MASK (CY_I2S_INTR_TX_TRIGGER | \ + CY_I2S_INTR_TX_NOT_FULL | \ + CY_I2S_INTR_TX_EMPTY | \ + CY_I2S_INTR_TX_OVERFLOW | \ + CY_I2S_INTR_TX_UNDERFLOW | \ + CY_I2S_INTR_TX_WD | \ + CY_I2S_INTR_RX_TRIGGER | \ + CY_I2S_INTR_RX_NOT_EMPTY | \ + CY_I2S_INTR_RX_FULL | \ + CY_I2S_INTR_RX_OVERFLOW | \ + CY_I2S_INTR_RX_UNDERFLOW | \ + CY_I2S_INTR_RX_WD) + +/* Non-zero default values */ +#define CY_I2S_TX_CTL_CH_NR_DEFAULT (0x1U) +#define CY_I2S_TX_CTL_I2S_MODE_DEFAULT (0x2U) +#define CY_I2S_TX_CTL_WS_PULSE_DEFAULT (0x1U) +#define CY_I2S_TX_CTL_CH_LEN_DEFAULT (0x4U) +#define CY_I2S_TX_CTL_WORD_LEN_DEFAULT (0x4U) + +#define CY_I2S_TX_CTL_DEFAULT (_VAL2FLD(I2S_TX_CTL_CH_NR, CY_I2S_TX_CTL_CH_NR_DEFAULT) | \ + _VAL2FLD(I2S_TX_CTL_I2S_MODE, CY_I2S_TX_CTL_I2S_MODE_DEFAULT) | \ + _VAL2FLD(I2S_TX_CTL_WS_PULSE, CY_I2S_TX_CTL_WS_PULSE_DEFAULT) | \ + _VAL2FLD(I2S_TX_CTL_CH_LEN, CY_I2S_TX_CTL_CH_LEN_DEFAULT) | \ + _VAL2FLD(I2S_TX_CTL_WORD_LEN, CY_I2S_TX_CTL_WORD_LEN_DEFAULT)) + +#define CY_I2S_RX_CTL_CH_NR_DEFAULT (0x1U) +#define CY_I2S_RX_CTL_I2S_MODE_DEFAULT (0x2U) +#define CY_I2S_RX_CTL_WS_PULSE_DEFAULT (0x1U) +#define CY_I2S_RX_CTL_CH_LEN_DEFAULT (0x4U) +#define CY_I2S_RX_CTL_WORD_LEN_DEFAULT (0x4U) + +#define CY_I2S_RX_CTL_DEFAULT (_VAL2FLD(I2S_RX_CTL_CH_NR, CY_I2S_RX_CTL_CH_NR_DEFAULT) | \ + _VAL2FLD(I2S_RX_CTL_I2S_MODE, CY_I2S_RX_CTL_I2S_MODE_DEFAULT) | \ + _VAL2FLD(I2S_RX_CTL_WS_PULSE, CY_I2S_RX_CTL_WS_PULSE_DEFAULT) | \ + _VAL2FLD(I2S_RX_CTL_CH_LEN, CY_I2S_RX_CTL_CH_LEN_DEFAULT) | \ + _VAL2FLD(I2S_RX_CTL_WORD_LEN, CY_I2S_RX_CTL_WORD_LEN_DEFAULT)) + +/* Macros for conditions used by CY_ASSERT calls */ +#define CY_I2S_IS_ALIGNMENT_VALID(alignment) ((CY_I2S_LEFT_JUSTIFIED == (alignment)) || \ + (CY_I2S_I2S_MODE == (alignment)) || \ + (CY_I2S_TDM_MODE_A == (alignment)) || \ + (CY_I2S_TDM_MODE_B == (alignment))) + +#define CY_I2S_IS_LEN_VALID(length) ((CY_I2S_LEN8 == (length)) || \ + (CY_I2S_LEN16 == (length)) || \ + (CY_I2S_LEN18 == (length)) || \ + (CY_I2S_LEN20 == (length)) || \ + (CY_I2S_LEN24 == (length)) || \ + (CY_I2S_LEN32 == (length))) + +#define CY_I2S_IS_OVHDATA_VALID(overhead) ((CY_I2S_OVHDATA_ZERO == (overhead)) || \ + (CY_I2S_OVHDATA_ONE == (overhead))) + +#define CY_I2S_IS_WSPULSE_VALID(wsPulse) ((CY_I2S_WS_ONE_SCK_CYCLE == (wsPulse)) || \ + (CY_I2S_WS_ONE_CHANNEL_LENGTH == (wsPulse))) + +#define CY_I2S_IS_CLK_DIV_VALID(clkDiv) ((clkDiv) <= 63U) +#define CY_I2S_IS_CHANNELS_VALID(channels) ((channels) <= 7UL) +#define CY_I2S_IS_INTR_MASK_VALID(interrupt) (0UL == ((interrupt) & ((uint32_t) ~CY_I2S_INTR_MASK))) + +#define CY_I2S_IS_CHAN_WORD_VALID(channel, word) ((CY_I2S_IS_LEN_VALID(channel)) && \ + (CY_I2S_IS_LEN_VALID(word)) && \ + ((channel) >= (word))) +#define CY_I2S_IS_TRIG_LEVEL_VALID(trigLevel, channels) ((trigLevel) <= (255U - (channels))) + +/** \endcond */ + + +/** +* \addtogroup group_i2s_functions +* \{ +*/ + + cy_en_i2s_status_t Cy_I2S_Init(I2S_Type * base, cy_stc_i2s_config_t const * config); + void Cy_I2S_DeInit(I2S_Type * base); + +/** \addtogroup group_i2s_functions_syspm_callback +* The driver supports SysPm callback for Deep Sleep transition. +* \{ +*/ +cy_en_syspm_status_t Cy_I2S_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams); +/** \} */ + +__STATIC_INLINE void Cy_I2S_EnableTx(I2S_Type * base); +__STATIC_INLINE void Cy_I2S_PauseTx(I2S_Type * base); +__STATIC_INLINE void Cy_I2S_ResumeTx(I2S_Type * base); +__STATIC_INLINE void Cy_I2S_DisableTx(I2S_Type * base); +__STATIC_INLINE void Cy_I2S_EnableRx(I2S_Type * base); +__STATIC_INLINE void Cy_I2S_DisableRx(I2S_Type * base); +__STATIC_INLINE uint32_t Cy_I2S_GetCurrentState(I2S_Type const * base); + +__STATIC_INLINE void Cy_I2S_ClearTxFifo(I2S_Type * base); +__STATIC_INLINE uint32_t Cy_I2S_GetNumInTxFifo(I2S_Type const * base); +__STATIC_INLINE void Cy_I2S_WriteTxData(I2S_Type * base, uint32_t data); +__STATIC_INLINE uint8_t Cy_I2S_GetTxReadPointer(I2S_Type const * base); +__STATIC_INLINE uint8_t Cy_I2S_GetTxWritePointer(I2S_Type const * base); +__STATIC_INLINE void Cy_I2S_FreezeTxFifo(I2S_Type * base); +__STATIC_INLINE void Cy_I2S_UnfreezeTxFifo(I2S_Type * base); + +__STATIC_INLINE void Cy_I2S_ClearRxFifo(I2S_Type * base); +__STATIC_INLINE uint32_t Cy_I2S_GetNumInRxFifo(I2S_Type const * base); +__STATIC_INLINE uint32_t Cy_I2S_ReadRxData(I2S_Type const * base); +__STATIC_INLINE uint32_t Cy_I2S_ReadRxDataSilent(I2S_Type const * base); +__STATIC_INLINE uint8_t Cy_I2S_GetRxReadPointer(I2S_Type const * base); +__STATIC_INLINE uint8_t Cy_I2S_GetRxWritePointer(I2S_Type const * base); +__STATIC_INLINE void Cy_I2S_FreezeRxFifo(I2S_Type * base); +__STATIC_INLINE void Cy_I2S_UnfreezeRxFifo(I2S_Type * base); + +__STATIC_INLINE uint32_t Cy_I2S_GetInterruptStatus(I2S_Type const * base); +__STATIC_INLINE void Cy_I2S_ClearInterrupt(I2S_Type * base, uint32_t interrupt); +__STATIC_INLINE void Cy_I2S_SetInterrupt(I2S_Type * base, uint32_t interrupt); +__STATIC_INLINE uint32_t Cy_I2S_GetInterruptMask(I2S_Type const * base); +__STATIC_INLINE void Cy_I2S_SetInterruptMask(I2S_Type * base, uint32_t interrupt); +__STATIC_INLINE uint32_t Cy_I2S_GetInterruptStatusMasked(I2S_Type const * base); + +/******************************************************************************* +* Function Name: Cy_I2S_EnableTx +****************************************************************************//** +* +* Starts an I2S transmission. Interrupts enabling (by the +* \ref Cy_I2S_SetInterruptMask) is required after this function call, in case +* if any I2S interrupts are used in the application. +* +* \pre Cy_I2S_Init() must be called before. +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_EnableTx +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_EnableTx(I2S_Type * base) +{ + base->CMD |= I2S_CMD_TX_START_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_PauseTx +****************************************************************************//** +* +* Pauses an I2S transmission. +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_PauseTx +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_PauseTx(I2S_Type * base) +{ + base->CMD |= I2S_CMD_TX_PAUSE_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_ResumeTx +****************************************************************************//** +* +* Resumes an I2S transmission. +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_ResumeTx +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_ResumeTx(I2S_Type * base) +{ + base->CMD &= (uint32_t) ~I2S_CMD_TX_PAUSE_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_DisableTx +****************************************************************************//** +* +* Stops an I2S transmission. +* +* \pre TX interrupts disabling (by the \ref Cy_I2S_SetInterruptMask) is required +* prior to this function call, in case if any TX I2S interrupts are used. +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_DisableTx +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_DisableTx(I2S_Type * base) +{ + base->CMD &= (uint32_t) ~I2S_CMD_TX_START_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_EnableRx +****************************************************************************//** +* +* Starts an I2S reception. Interrupts enabling (by the +* \ref Cy_I2S_SetInterruptMask) is required after this function call, in case +* if any I2S interrupts are used in the application. +* +* \pre \ref Cy_I2S_Init() must be called before. +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_EnableRx +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_EnableRx(I2S_Type * base) +{ + base->CMD |= I2S_CMD_RX_START_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_DisableRx +****************************************************************************//** +* +* Stops an I2S reception. +* +* \pre RX interrupts disabling (by the \ref Cy_I2S_SetInterruptMask) is required +* prior to this function call, in case if any RX I2S interrupts are used. +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_DisableRx +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_DisableRx(I2S_Type * base) +{ + base->CMD &= (uint32_t) ~I2S_CMD_RX_START_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_GetCurrentState +****************************************************************************//** +* +* Returns the current I2S state (TX/RX running/paused/stopped). +* +* \param base The pointer to the I2S instance address. +* +* \return The current state \ref group_i2s_macros_current_state. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_GetCurrentState +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_I2S_GetCurrentState(I2S_Type const * base) +{ + return (base->CMD & (I2S_CMD_TX_START_Msk | I2S_CMD_TX_PAUSE_Msk | I2S_CMD_RX_START_Msk)); +} + + +/******************************************************************************* +* Function Name: Cy_I2S_ClearTxFifo +****************************************************************************//** +* +* Clears the TX FIFO (resets the Read/Write FIFO pointers). +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_ClearTxFifo +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_ClearTxFifo(I2S_Type * base) +{ + base->TX_FIFO_CTL |= I2S_TX_FIFO_CTL_CLEAR_Msk; + base->TX_FIFO_CTL &= (uint32_t) ~I2S_TX_FIFO_CTL_CLEAR_Msk; + (void) base->TX_FIFO_CTL; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_GetNumInTxFifo +****************************************************************************//** +* +* Gets the number of used words in the TX FIFO. +* +* \param base The pointer to the I2S instance address. +* +* \return The current number of used words in the TX FIFO. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_GetNumInTxFifo +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_I2S_GetNumInTxFifo(I2S_Type const * base) +{ + return (_FLD2VAL(I2S_TX_FIFO_STATUS_USED, base->TX_FIFO_STATUS)); +} + + +/******************************************************************************* +* Function Name: Cy_I2S_WriteTxData +****************************************************************************//** +* +* Writes data to the TX FIFO. Increases the TX FIFO level. +* +* \param base The pointer to the I2S instance address. +* +* \param data Data to be written to the TX FIFO. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_WriteTxData +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_WriteTxData(I2S_Type * base, uint32_t data) +{ + base->TX_FIFO_WR = data; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_GetTxReadPointer +****************************************************************************//** +* +* Gets the TX FIFO Read pointer. This function is rather for debug purposes. +* +* \param base The pointer to the I2S instance address. +* +* \return The current TX Read pointer value. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_GetTxReadPointer +* +*******************************************************************************/ +__STATIC_INLINE uint8_t Cy_I2S_GetTxReadPointer(I2S_Type const * base) +{ + return ((uint8_t) _FLD2VAL(I2S_TX_FIFO_STATUS_RD_PTR, base->TX_FIFO_STATUS)); +} + + +/******************************************************************************* +* Function Name: Cy_I2S_GetTxWritePointer +****************************************************************************//** +* +* Gets the TX FIFO Write pointer. This function is rather for debug purposes. +* +* \param base The pointer to the I2S instance address. +* +* \return The current TX Write pointer value. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_GetTxWritePointer +* +*******************************************************************************/ +__STATIC_INLINE uint8_t Cy_I2S_GetTxWritePointer(I2S_Type const * base) +{ + return ((uint8_t) _FLD2VAL(I2S_TX_FIFO_STATUS_WR_PTR, base->TX_FIFO_STATUS)); +} + + +/******************************************************************************* +* Function Name: Cy_I2S_FreezeTxFifo +****************************************************************************//** +* +* Freezes the TX FIFO. This function is rather for debug purposes. +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_FreezeTxFifo +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_FreezeTxFifo(I2S_Type * base) +{ + base->TX_FIFO_CTL |= I2S_TX_FIFO_CTL_FREEZE_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_UnfreezeTxFifo +****************************************************************************//** +* +* Unfreezes the TX FIFO. This function is rather for debug purposes. +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_UnfreezeTxFifo +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_UnfreezeTxFifo(I2S_Type * base) +{ + base->TX_FIFO_CTL &= (uint32_t) ~I2S_TX_FIFO_CTL_FREEZE_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_ClearRxFifo +****************************************************************************//** +* +* Clears the RX FIFO (resets the Read/Write FIFO pointers). +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_ClearRxFifo +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_ClearRxFifo(I2S_Type * base) +{ + base->RX_FIFO_CTL |= I2S_RX_FIFO_CTL_CLEAR_Msk; + base->RX_FIFO_CTL &= (uint32_t) ~I2S_RX_FIFO_CTL_CLEAR_Msk; + (void) base->RX_FIFO_CTL; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_GetNumInRxFifo +****************************************************************************//** +* +* Gets the number of used words in the RX FIFO. +* +* \param base The pointer to the I2S instance address. +* +* \return The current number of used words in rge RX FIFO. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_GetNumInRxFifo +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_I2S_GetNumInRxFifo(I2S_Type const * base) +{ + return (_FLD2VAL(I2S_RX_FIFO_STATUS_USED, base->RX_FIFO_STATUS)); +} + + +/******************************************************************************* +* Function Name: Cy_I2S_ReadRxData +****************************************************************************//** +* +* Reads data from the RX FIFO. Decreases the RX FIFO level. +* +* \param base The pointer to the I2S instance address. +* +* \return The read data. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_ReadRxData +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_I2S_ReadRxData(I2S_Type const * base) +{ + return (base->RX_FIFO_RD); +} + + +/******************************************************************************* +* Function Name: Cy_I2S_ReadRxDataSilent +****************************************************************************//** +* +* Reads data from the RX FIFO without updating the RX FIFO read pointer. +* This function is rather for debug purposes. +* +* \param base The pointer to the I2S instance address. +* +* \return The read data. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_ReadRxDataSilent +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_I2S_ReadRxDataSilent(I2S_Type const * base) +{ + return (base->RX_FIFO_RD_SILENT); +} + + +/******************************************************************************* +* Function Name: Cy_I2S_GetRxReadPointer +****************************************************************************//** +* +* Gets the RX FIFO Read pointer. This function is rather for debug purposes. +* +* \param base The pointer to the I2S instance address. +* +* \return The current RX Read pointer value. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_GetRxReadPointer +* +*******************************************************************************/ +__STATIC_INLINE uint8_t Cy_I2S_GetRxReadPointer(I2S_Type const * base) +{ + return ((uint8_t) _FLD2VAL(I2S_RX_FIFO_STATUS_RD_PTR, base->RX_FIFO_STATUS)); +} + + +/******************************************************************************* +* Function Name: Cy_I2S_GetRxWritePointer +****************************************************************************//** +* +* Gets the RX FIFO Write pointer. This function is rather for debug purposes. +* +* \param base The pointer to the I2S instance address. +* +* \return The current RX Write pointer value. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_GetRxWritePointer +* +*******************************************************************************/ +__STATIC_INLINE uint8_t Cy_I2S_GetRxWritePointer(I2S_Type const * base) +{ + return ((uint8_t) _FLD2VAL(I2S_RX_FIFO_STATUS_WR_PTR, base->RX_FIFO_STATUS)); +} + + +/******************************************************************************* +* Function Name: Cy_I2S_FreezeRxFifo +****************************************************************************//** +* +* Freezes the RX FIFO. This function is rather for debug purposes. +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_FreezeRxFifo +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_FreezeRxFifo(I2S_Type * base) +{ + base->RX_FIFO_CTL |= I2S_RX_FIFO_CTL_FREEZE_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_UnfreezeRxFifo +****************************************************************************//** +* +* Unfreezes the RX FIFO. This function is rather for debug purposes. +* +* \param base The pointer to the I2S instance address. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_UnfreezeRxFifo +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_UnfreezeRxFifo(I2S_Type * base) +{ + base->RX_FIFO_CTL &= (uint32_t) ~I2S_RX_FIFO_CTL_FREEZE_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_GetInterruptStatus +****************************************************************************//** +* +* Gets an interrupt status (returns a content of the INTR register). +* +* \param base The pointer to the I2S instance address. +* +* \return The interrupt bit mask \ref group_i2s_macros_intrerrupt_masks. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_GetInterruptStatus +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_I2S_GetInterruptStatus(I2S_Type const * base) +{ + return (base->INTR); +} + + +/******************************************************************************* +* Function Name: Cy_I2S_ClearInterrupt +****************************************************************************//** +* +* Clears one or more interrupt factors (sets the INTR register). +* +* \param base The pointer to the I2S instance address. +* +* \param interrupt Interrupt bit mask \ref group_i2s_macros_intrerrupt_masks. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_ClearInterrupt +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_ClearInterrupt(I2S_Type * base, uint32_t interrupt) +{ + CY_ASSERT_L2(CY_I2S_IS_INTR_MASK_VALID(interrupt)); + base->INTR = interrupt; + (void) base->INTR; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_SetInterrupt +****************************************************************************//** +* +* Sets one or more interrupt factors (sets the INTR_SET register). +* +* \param base The pointer to the I2S instance address. +* +* \param interrupt Interrupt bit mask \ref group_i2s_macros_intrerrupt_masks. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_SetInterrupt +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_SetInterrupt(I2S_Type * base, uint32_t interrupt) +{ + CY_ASSERT_L2(CY_I2S_IS_INTR_MASK_VALID(interrupt)); + base->INTR_SET = interrupt; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_GetInterruptMask +****************************************************************************//** +* +* Returns the interrupt mask (a content of the INTR_MASK register). +* +* \param base The pointer to the I2S instance address. +* +* \return The interrupt bit mask \ref group_i2s_macros_intrerrupt_masks. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_GetInterruptMask +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_I2S_GetInterruptMask(I2S_Type const * base) +{ + return (base->INTR_MASK); +} + + +/******************************************************************************* +* Function Name: Cy_I2S_SetInterruptMask +****************************************************************************//** +* +* Sets one or more interrupt factor masks (the INTR_MASK register). +* +* \param base The pointer to the I2S instance address. +* +* \param interrupt Interrupt bit mask \ref group_i2s_macros_intrerrupt_masks. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_SetInterruptMask +* +*******************************************************************************/ +__STATIC_INLINE void Cy_I2S_SetInterruptMask(I2S_Type * base, uint32_t interrupt) +{ + CY_ASSERT_L2(CY_I2S_IS_INTR_MASK_VALID(interrupt)); + base->INTR_MASK = interrupt; +} + + +/******************************************************************************* +* Function Name: Cy_I2S_GetInterruptStatusMasked +****************************************************************************//** +* +* Returns the interrupt status masked (a content of the INTR_MASKED register). +* +* \param base The pointer to the I2S instance address. +* +* \return The interrupt bit mask(s) \ref group_i2s_macros_intrerrupt_masks. +* +* \funcusage +* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c snippet_Cy_I2S_ClearInterrupt +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_I2S_GetInterruptStatusMasked(I2S_Type const * base) +{ + return (base->INTR_MASKED); +} + +/** \} group_i2s_functions */ + +#ifdef __cplusplus +} +#endif + +#endif /* CY_I2S_H */ + + +/** \} group_i2s */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_drv.c b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_drv.c new file mode 100644 index 0000000000..c6732f2dc6 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_drv.c @@ -0,0 +1,170 @@ +/***************************************************************************//** +* \file cy_ipc_drv.c +* \version 1.10.1 +* +* \breif +* IPC Driver - This source file contains the low-level driver code for +* the IPC hardware. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include "cy_ipc_drv.h" + + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_LockRelease +****************************************************************************//** +* +* The function is used to release an IPC channel from the locked state. +* The function also has a way to specify through a parameter which IPC +* interrupts must be notified during the release event. +* +* \param base +* This parameter is a handle that represents the base address of the registers +* of the IPC channel. +* The parameter is generally returned from a call to the \ref +* Cy_IPC_Drv_GetIpcBaseAddress. +* +* \param releaseEventIntr +* Bit encoded list of IPC interrupt lines that are triggered by a release event. +* +* \return Status of the operation +* \retval CY_IPC_DRV_SUCCESS: The function executed successfully and the IPC channel +* was released. +* \retval CY_IPC_DRV_ERROR: The IPC channel was not acquired before the +* function call. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_ReadMsgPtr +* +*******************************************************************************/ +cy_en_ipcdrv_status_t Cy_IPC_Drv_LockRelease (IPC_STRUCT_Type* base, uint32_t releaseEventIntr) +{ + cy_en_ipcdrv_status_t retStatus; + + /* Check to make sure the IPC is Acquired */ + if( Cy_IPC_Drv_IsLockAcquired(base) ) + { + /* The IPC was acquired, release the IPC channel */ + Cy_IPC_Drv_ReleaseNotify(base, releaseEventIntr); + + retStatus = CY_IPC_DRV_SUCCESS; + } + else /* The IPC channel was already released (not acquired) */ + { + retStatus = CY_IPC_DRV_ERROR; + } + + return (retStatus); +} + + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_SendMsgWord +****************************************************************************//** +* +* This function is used to send a 32-bit word message through an IPC channel. +* The function also has an associated notification field that will let the +* message notify one or multiple IPC interrupts. The IPC channel is locked and +* remains locked after the function returns. The receiver of the message should +* release the channel. +* +* \param base +* This parameter is a handle that represents the base address of the registers +* of the IPC channel. +* The parameter is generally returned from a call to the \ref +* Cy_IPC_Drv_GetIpcBaseAddress. +* +* \param notifyEventIntr +* Bit encoded list of IPC interrupt lines that are triggered by a notification. +* +* \param message +* The message word that is the data placed in the IPC data register. +* +* \return Status of the operation: +* \retval CY_IPC_DRV_SUCCESS: The send operation was successful. +* \retval CY_IPC_DRV_ERROR: The IPC channel is unavailable because it is already locked. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_SendMsgWord +* +*******************************************************************************/ +cy_en_ipcdrv_status_t Cy_IPC_Drv_SendMsgWord (IPC_STRUCT_Type* base, uint32_t notifyEventIntr, uint32_t message) +{ + cy_en_ipcdrv_status_t retStatus; + + if( CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockAcquire(base) ) + { + /* If the channel was acquired, send the message. */ + Cy_IPC_Drv_WriteDataValue(base, message); + + Cy_IPC_Drv_AcquireNotify(base, notifyEventIntr); + + retStatus = CY_IPC_DRV_SUCCESS; + } + else + { + /* Channel was already acquired, return Error */ + retStatus = CY_IPC_DRV_ERROR; + } + return (retStatus); +} + + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_ReadMsgWord +****************************************************************************//** +* +* This function is used to read a 32-bit word message through an IPC channel. +* This function assumes that the channel is locked (for a valid message). +* If the channel is not locked, the message is invalid. The user must call +* Cy_IPC_Drv_Release() function after reading the message to release the +* IPC channel. +* +* \param base +* This parameter is a handle that represents the base address of the registers +* of the IPC channel. +* The parameter is generally returned from a call to the \ref +* Cy_IPC_Drv_GetIpcBaseAddress. +* +* \param message +* A variable where the read data is copied. +* +* \return Status of the operation +* \retval CY_IPC_DRV_SUCCESS: The function executed successfully and the IPC +* was acquired. +* \retval CY_IPC_DRV_ERROR: The function encountered an error because the IPC +* channel was already in a released state, meaning the data +* may be invalid. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_ReadMsgWord +* +*******************************************************************************/ +cy_en_ipcdrv_status_t Cy_IPC_Drv_ReadMsgWord (IPC_STRUCT_Type const * base, uint32_t * message) +{ + cy_en_ipcdrv_status_t retStatus; + + CY_ASSERT_L1(NULL != message); + + if ( Cy_IPC_Drv_IsLockAcquired(base) ) + { + /* The channel is locked; message is valid. */ + *message = Cy_IPC_Drv_ReadDataValue(base); + + retStatus = CY_IPC_DRV_SUCCESS; + } + else + { + /* The channel is not locked so channel is invalid. */ + retStatus = CY_IPC_DRV_ERROR; + } + return(retStatus); +} + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_drv.h b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_drv.h new file mode 100644 index 0000000000..bf8005a7af --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_drv.h @@ -0,0 +1,930 @@ +/***************************************************************************//** +* \file cy_ipc_drv.h +* \version 1.10.1 +* +* Provides an API declaration of the IPC driver. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#ifndef CY_IPC_DRV_H +#define CY_IPC_DRV_H + + +/** +* \defgroup group_ipc Inter Process Communication (IPC) +* \{ +* The inter-processor communication (IPC) driver provides a safe and reliable +* method to transfer data between CPUs. Hardware locking ensures that only one +* device can acquire and transfer data at a time so no data is lost or +* overwritten by asynchronous processes or CPUs. +* +* There are three parts to the API: +* - Driver-level (DRV) API - used internally by Semaphore and Pipe levels +* - Pipe-level (PIPE) API - establishes a communication channel between +* processors +* - Semaphore-level (SEMA) API - enables users to set and clear flags to +* synchronize operations. +* +* Firmware does not need to use the DRV API. It can implement IPC functionality +* entirely with the PIPE and SEMA APIs. +* +* \section group_ipc_background Background +* +* IPC is implemented in hardware as a collection of individual communication +* channels, each with a set of 32-bit registers. The IPC design implements a set +* of interrupts that enable each processor to notify the other that data is +* available, or has been processed. There is also a locking mechanism that +* allows only one CPU to gain access at a time. +* +* The Driver-level API manages each channel's registers to implement IPC +* functionality. For information on the IPC registers, see the IPC chapter of +* the Technical Reference Manual (TRM). +* +* At the hardware level, communication is a five-step process. +* -# The sending processor acquires a channel +* -# It puts data into the channel +* -# The sender generates a notify event (interrupt) +* -# The receiving processor identifies the sender and retrieves the data +* -# The receiving processor generates a release event (interrupt) +* +* \image html ipc_driver.png +* +* These transactions are handled transparently by the DRV-level API. Use the +* PIPE and SEMA layers of the API to implement communication in your application. +* The data transferred is limited to a single 32-bit value. As implemented by +* the PIPE API, that value is a pointer to a data structure of arbitrary size +* and complexity. +* +* \section group_ipc_overview Overview +* +* The Pipe is the key element in the PDL design. A pipe is typically a +* full-duplex communication channel between CPU cores. A pipe allows a single +* conduit to transfer messages or data to and from multiple processes or CPUs. +* +* A pipe has two endpoints, one on each core. Each endpoint contains a dedicated +* IPC channel and an interrupt. IPC channels 0-7 and IPC interrupts 0-7 are +* reserved for system use. +* +* The pipe also contains the number of clients it supports, and for each client +* a callback function. So the pipe can service a number of clients, each with a +* separate callback function, on either endpoint. The number of clients a pipe +* supports is the sum of each endpoint's clients. +* +* This design enables any number of processes on the sending core to put +* arbitrary data into a single pipe. The first element of that data is the +* client ID of the client that should handle the data. +* +* An interrupt notifies the receiving core that data is available. The receiving +* core parses the data to identify the client, and then dispatches the event to +* the appropriate client via the client callback function. An interrupt notifies +* the sending core that the receiver is finished. In this way a single pipe can +* manage arbitrary data transfers between cores with data flowing in either +* direction. +* +* \image html ipc_ints.png +* +* The application can use semaphores to control access to shared resources, as +* required by the application's logic. +* +* The PDL provides two specific files that set up default IPC functionality. +* They are cy_ipc_config.h and cy_ipc_config.c. You can modify these files based +* on the requirements of your design. If you use PSoC Creator as a development +* environment, it will not overwrite your changes when you generate the +* application or build your code. +* +* \section group_ipc_pipe_layer PIPE layer +* +* A pipe is a communication channel between two endpoints. PSoC 6 devices support +* 16 IPC channels, and 16 IPC interrupts, each numbered 0-15. IPC Channels 0-7 +* and IPC interrupts 0-7 are reserved for system use. Channels 8-15 and +* interrupts 8-15 are available for application use. +* +* A full duplex pipe uses two IPC channels, one per endpoint. Each endpoint +* specifies all the information required to process a message (either sent or +* received). Each endpoint is configured to use an IPC channel, and an IPC +* interrupt. Common practice is to use the interrupt with the same number as +* the IPC channel. However, IPC Interrupts are not directly associated with the +* IPC channels, so any channel can use any interrupt. Any IPC channel can +* trigger 0, 1 or all the IPC interrupts at once, depending on the Notify or +* Release masks used. +* +* It is also possible to set up a one-directional pipe, using a single IPC +* channel. In this design one processor is always the sender, and the other is +* always the receiver. However, there are still two endpoints. +* +* A pipe supports an arbitrary number of clients with an array of callback +* functions, one per client. The client ID is the index number into the array +* for the client. After a pipe is configured and initialized, the application +* calls Cy_IPC_Pipe_RegisterCallback() once per client to register each client's +* callback function. Multiple clients can use the same callback function. The +* endpoints in a pipe share the callback array. +* +* Use Cy_IPC_Pipe_SendMessage() to send data. You specify both the "to" and +* "from" endpoints, and a callback function to be used when the data transfer is +* complete. The data is a 32-bit void pointer. The data pointed to is arbitrary, +* and can be an array, a structure, or a location in memory. The only limitation +* is that the first element of the data must be a 32-bit unsigned word containing +* a client ID number. The ID number is the index into the callback array. +* +* When a message is sent, the receiving endpoint's interrupt handler is called. +* The ISR can perform any task required by the design. However, as part of its +* function it calls \ref Cy_IPC_Pipe_ExecCallback. This function retrieves the +* client ID from the data and calls the associated callback function. +* The user-supplied callback function handles the data in whatever way is +* appropriate based on the application logic. +* +* After the callback function is returned by the receiver, it invokes the release +* callback function defined by the sender of the message. +* +* \section group_ipc_sema_layer SEMA Layer +* +* A semaphore is a flag the application uses to control access to a shared +* resource. The SEMA-level API uses an IPC channel to implement +* semaphores. Startup code sets up a default semaphore system. The +* default system creates an array of 128 semaphores (four 32-bit values). +* Semaphores 0-15 are reserved for system use. See +* Configuration Considerations - SEMA. +* +* Functions are available to initialize the semaphore system, to set or +* clear a semaphore, or to get the semaphore's current status. Application +* logic uses SEMA functions to relate a particular semaphore to a particular +* shared resource, and set, clear, or check the flag when accessing the +* shared resource. +* +* \section group_ipc_configuration_cypipe Configuration Considerations - CYPIPE +* +* There are none. The cy_ipc_config files set up the required CYPIPE for system +* use. Do not modify the CYPIPE. It uses IPC channels 5 and 6 to implement full +* duplex communication between cores. On the CM0+ the notify interrupt is +* assigned to NVIC IRQn 27. See System Interrupt (SysInt) for background. +* +* To create your own pipe you should make 3 steps: +* -# Define pipe callbacks processing interrupt handler +* -# Define your pipe configuration by cy_stc_ipc_pipe_config_t type structure +* -# Call Cy_IPC_Pipe_Init() to initialize your pipe on both cores +* +* \section group_ipc_configuration_sema Configuration Considerations - SEMA +* +* Startup code calls Cy_IPC_SystemSemaInit() (in cy_ipc_config.c) to set up +* semaphore functionality. This function calls the PDL init function +* Cy_IPC_Sema_Init() with default values. By default the semaphore system +* uses IPC channel 4, and creates 128 semaphores. Do not change the IPC +* channel. You can change the number of semaphores. +* +* To change the number of semaphores, modify this line of code in cy_ipc_config.h. +* +* \code +* #define CY_IPC_SEMA_COUNT (uint32_t)(128u) +* \endcode +* +* The file cy_ipc_config.c declares array ipcSemaArray to hold the semaphore +* flags based on the size defined for this symbol. Use increments of 32. You +* must have at least 32 semaphores. Semaphores 0-15 are reserved for +* system use. Your application can use semaphores greater than 15. +* +* \section group_ipc_more_information More Information +* +* Cy_IPC_SystemSemaInit() and Cy_IPC_SystemPipeInit() functions are called in the +* SystemInit function. If the default startup file is not used, or SystemInit is +* not called in your project, call the following three functions prior to +* executing any flash or EmEEPROM write or erase operation. For example: +* -# Cy_IPC_SystemSemaInit() +* -# Cy_IPC_SystemPipeInit() +* -# Cy_Flash_Init() +* +* Also Cy_IPC_SystemPipeInit function is called to support BLE host/controller +* communication. +* +* See the technical reference manual(TRM) for more information on the IPC. +* +* \section group_ipc_MISRA MISRA-C Compliance +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
MISRA RuleRule Class (Required/Advisory)Rule DescriptionDescription of Deviation(s)
10.3RThe value of a complex expression of integer type shall be cast +* only to a type of the same signedness that is no wider than the underlying +* type of the expression.The cast from integer to enumeration value is used to calculate +* the interrupt vector source from the integer number of the IPC interrupt +* structure, so there is no way to avoid this cast.
11.4AA cast should not be performed between a pointer to the void to a +* pointer to the object type.The cast from the void to pointer and vice versa is used to transmit +* data via the \ref group_ipc channel by exchanging the pointer. We +* exchange only one pointer, so there is no way to avoid this cast.
+* +* \section group_ipc_changelog Changelog +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
VersionChangesReason for Change
1.10.1Updated description of the \ref Cy_IPC_Pipe_Init, +* \ref Cy_IPC_Pipe_EndpointInit, \ref Cy_IPC_Sema_Set functions. +* Added / updated code snippets. +* Documentation update and clarification
1.10Added support for more IPC structuresNew device support
1.0Initial version
+* +* \defgroup group_ipc_drv IPC driver layer (IPC_DRV) +* \{ +* The functions of this layer are used in the higher IPC levels +* (Semaphores and Pipes). +* Users should not call any of these IPC functions directly. +* +* \defgroup group_ipc_macros Macros +* Macro definitions are used in the driver +* +* \defgroup group_ipc_functions Functions +* Functions are used in the driver +* +* \defgroup group_ipc_data_structures Data Structures +* Data structures are used in the driver +* +* \defgroup group_ipc_enums Enumerated Types +* Enumerations are used in the driver +* \} +* +* \defgroup group_ipc_sema IPC semaphores layer (IPC_SEMA) +* \defgroup group_ipc_pipe IPC pipes layer (IPC_PIPE) +* +*/ + +/******************************************************************************/ +/* Include files */ +/******************************************************************************/ +#include "syslib/cy_syslib.h" +#include "cy_device_headers.h" +#include "cy_ipc_config.h" +#include + +/** +* \addtogroup group_ipc_macros +* \{ +*/ + +/** Driver major version */ +#define CY_IPC_DRV_VERSION_MAJOR 1 + +/** Driver minor version */ +#define CY_IPC_DRV_VERSION_MINOR 10 + +/** Defines a value to indicate that no notification events are needed */ +#define CY_IPC_NO_NOTIFICATION (uint32_t)(0x00000000ul) + +/* Error Code constants */ +#define CY_IPC_ID CY_PDL_DRV_ID(0x22u) /**< Software PDL driver ID for IPC */ + +/** Return prefix for IPC driver function status codes */ +#define CY_IPC_ID_INFO (uint32_t)( CY_IPC_ID | CY_PDL_STATUS_INFO ) +/** Return prefix for IPC driver function warning return values */ +#define CY_IPC_ID_WARNING (uint32_t)( CY_IPC_ID | CY_PDL_STATUS_WARNING) +/** Return prefix for IPC driver function error return values */ +#define CY_IPC_ID_ERROR (uint32_t)( CY_IPC_ID | CY_PDL_STATUS_ERROR) + +/** Converts the IPC interrupt channel number to interrupt vector */ +#define CY_IPC_INTR_NUM_TO_VECT(x) ((int32_t)cpuss_interrupts_ipc_0_IRQn + (x)) + +/** \} group_ipc_macros */ + +/* end of definition in device.h */ + + +/** +* \addtogroup group_ipc_enums +* \{ +*/ + +/** +* This is a list of ENUMs used for function return status. +*/ +typedef enum +{ + /** Function was successfully executed */ + CY_IPC_DRV_SUCCESS = (0x00u), + /** Function was not executed due to an error. + Typical conditions for the error explained + in the function description */ + CY_IPC_DRV_ERROR = ( CY_IPC_ID_ERROR + 1ul), +} cy_en_ipcdrv_status_t; + +/** \} group_ipc_enums */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** \cond INTERNAL */ + +__STATIC_INLINE void Cy_IPC_Drv_WriteDataValue (IPC_STRUCT_Type* base, uint32_t dataValue); +__STATIC_INLINE uint32_t Cy_IPC_Drv_ReadDataValue (IPC_STRUCT_Type const * base); + +__STATIC_INLINE uint32_t Cy_IPC_Drv_ExtractAcquireMask (uint32_t intMask); +__STATIC_INLINE uint32_t Cy_IPC_Drv_ExtractReleaseMask (uint32_t intMask); + +/** \endcond */ + +/** +* \addtogroup group_ipc_functions +* \{ +*/ + +__STATIC_INLINE IPC_STRUCT_Type* Cy_IPC_Drv_GetIpcBaseAddress (uint32_t ipcIndex); +__STATIC_INLINE IPC_INTR_STRUCT_Type* Cy_IPC_Drv_GetIntrBaseAddr (uint32_t ipcIntrIndex); + +__STATIC_INLINE void Cy_IPC_Drv_AcquireNotify (IPC_STRUCT_Type * base, uint32_t notifyEventIntr); +__STATIC_INLINE void Cy_IPC_Drv_ReleaseNotify (IPC_STRUCT_Type * base, uint32_t notifyEventIntr); + +__STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_LockAcquire (IPC_STRUCT_Type const * base); +cy_en_ipcdrv_status_t Cy_IPC_Drv_LockRelease (IPC_STRUCT_Type * base, uint32_t releaseEventIntr); +__STATIC_INLINE bool Cy_IPC_Drv_IsLockAcquired (IPC_STRUCT_Type const * base); +__STATIC_INLINE uint32_t Cy_IPC_Drv_GetLockStatus (IPC_STRUCT_Type const * base); + +cy_en_ipcdrv_status_t Cy_IPC_Drv_SendMsgWord (IPC_STRUCT_Type * base, uint32_t notifyEventIntr, uint32_t message); +cy_en_ipcdrv_status_t Cy_IPC_Drv_ReadMsgWord (IPC_STRUCT_Type const * base, uint32_t * message); +__STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_SendMsgPtr (IPC_STRUCT_Type* base, uint32_t notifyEventIntr, void const * msgPtr); +__STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_ReadMsgPtr (IPC_STRUCT_Type const * base, void ** msgPtr); + +__STATIC_INLINE void Cy_IPC_Drv_SetInterruptMask (IPC_INTR_STRUCT_Type * base, + uint32_t ipcReleaseMask, uint32_t ipcNotifyMask); +__STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptMask (IPC_INTR_STRUCT_Type const * base); +__STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptStatusMasked (IPC_INTR_STRUCT_Type const * base); +__STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptStatus (IPC_INTR_STRUCT_Type const * base); +__STATIC_INLINE void Cy_IPC_Drv_SetInterrupt (IPC_INTR_STRUCT_Type * base, + uint32_t ipcReleaseMask, uint32_t ipcNotifyMask); +__STATIC_INLINE void Cy_IPC_Drv_ClearInterrupt (IPC_INTR_STRUCT_Type * base, + uint32_t ipcReleaseMask, uint32_t ipcNotifyMask); + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_GetIpcBaseAddress +****************************************************************************//** +* +* This function takes an IPC channel index as a parameter and returns the base +* address the IPC registers corresponding to the IPC channel. +* +* \note The user is responsible for ensuring that ipcIndex does not exceed the +* limits. +* +* \param ipcIndex +* Represents the number of IPC structure. This is converted to the base address of +* the IPC channel registers. +* +* \return +* Returns a pointer to the base of the IPC registers. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_SendMsgWord +* +*******************************************************************************/ +__STATIC_INLINE IPC_STRUCT_Type* Cy_IPC_Drv_GetIpcBaseAddress (uint32_t ipcIndex) +{ + CY_ASSERT_L1((uint32_t)CY_IPC_CHANNELS > ipcIndex); + return ( (IPC_STRUCT_Type*) ( &IPC->STRUCT[ipcIndex] ) ); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_GetIntrBaseAddr +****************************************************************************//** +* +* This function takes an IPC interrupt structure index and returns the base +* address of the IPC interrupt registers corresponding to the IPC Interrupt. +* +* \note The user is responsible for ensuring that ipcIntrIndex does not exceed the +* limits. +* +* \param ipcIntrIndex +* Represents the number of IPC interrupt structure. This is converted to the +* base address of the IPC interrupt registers. +* +* \return +* Returns a pointer to the base of the IPC interrupt registers. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_GetInterruptStatus +* +*******************************************************************************/ +__STATIC_INLINE IPC_INTR_STRUCT_Type* Cy_IPC_Drv_GetIntrBaseAddr (uint32_t ipcIntrIndex) +{ + CY_ASSERT_L1((uint32_t)CY_IPC_INTERRUPTS > ipcIntrIndex); + return ( (IPC_INTR_STRUCT_Type*) ( &IPC->INTR_STRUCT[ipcIntrIndex] ) ); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_SetInterruptMask +****************************************************************************//** +* +* This function is used to set the interrupt mask for an IPC Interrupt. +* The mask sets release or acquire notification events for all IPC channels. +* +* \param base +* This is a handle to the IPC interrupt. This handle can be calculated from the +* IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr. +* +* \param ipcReleaseMask +* An encoded list of all IPC channels that can trigger the interrupt on a +* release event. +* +* \param ipcNotifyMask +* An encoded list of all IPC channels that can trigger the interrupt on a +* notify event. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_GetInterruptStatusMasked +* +*******************************************************************************/ +__STATIC_INLINE void Cy_IPC_Drv_SetInterruptMask (IPC_INTR_STRUCT_Type* base, + uint32_t ipcReleaseMask, uint32_t ipcNotifyMask) +{ + CY_ASSERT_L1(0ul == (ipcNotifyMask & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk))); + CY_ASSERT_L1(0ul == (ipcReleaseMask & ~(uint32_t)(IPC_STRUCT_RELEASE_INTR_RELEASE_Msk))); + base->INTR_MASK = _VAL2FLD( IPC_INTR_STRUCT_INTR_MASK_NOTIFY, ipcNotifyMask) | + _VAL2FLD( IPC_INTR_STRUCT_INTR_MASK_RELEASE, ipcReleaseMask); +} + + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_GetInterruptMask +****************************************************************************//** +* +* This function is used to read the interrupt mask. +* +* \param base +* This is a handle to the IPC interrupt. This handle can be calculated from +* the IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr. +* +* \return +* The return value is encoded as follows +* +*
Interrupt sources Value +*
Ipc_PORTX_RELEASE Xth bit set +*
Ipc_PORTX_NOTIFY X+16th bit set +*
+* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_GetInterruptStatusMasked +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptMask(IPC_INTR_STRUCT_Type const * base) +{ + return (base->INTR_MASK); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_GetInterruptStatusMasked +****************************************************************************//** +* +* This function is used to read the active unmasked interrupt. This function +* can be used in the interrupt service routine to find which source triggered +* the interrupt. +* +* \param base +* This is a handle to the IPC interrupt. This handle can be calculated from the +* IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr. +* +* \return +* The return value is encoded as follows +* +*
Interrupt sources Value +*
Ipc_PORTX_RELEASE Xth bit set +*
Ipc_PORTX_NOTIFY X+16th bit set +*
+* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_GetInterruptStatusMasked +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptStatusMasked (IPC_INTR_STRUCT_Type const * base) +{ + return (base->INTR_MASKED); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_GetInterruptStatus +****************************************************************************//** +* +* This function is used to read the pending interrupts. Note that this read is +* an unmasked read of the interrupt status. Interrupt sources read as active by +* this function would generate interrupts only if they were not masked. +* +* \param base +* This is a handle to the IPC interrupt. This handle can be calculated from the +* IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr. +* +* \return +* The return value is encoded as follows +* +*
Interrupt sources Value +*
Ipc_PORTX_RELEASE Xth bit set +*
Ipc_PORTX_NOTIFY X+16th bit set +*
+* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_GetInterruptStatus +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptStatus(IPC_INTR_STRUCT_Type const * base) +{ + return (base->INTR); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_SetInterrupt +****************************************************************************//** +* +* This function is used to set the interrupt source. This function can be used +* to activate interrupts through software. +* \note That interrupt sources set using this interrupt would generate interrupts +* only if they are not masked. +* +* \param base +* This is a handle to the IPC interrupt. This handle can be calculated from the +* IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr. +* +* \param ipcReleaseMask +* An encoded list of all IPC channels that can trigger the interrupt on a +* release event. +* +* \param ipcNotifyMask +* An encoded list of all IPC channels that can trigger the interrupt on a +* notify event. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_SetInterrupt +* +*******************************************************************************/ +__STATIC_INLINE void Cy_IPC_Drv_SetInterrupt(IPC_INTR_STRUCT_Type* base, uint32_t ipcReleaseMask, uint32_t ipcNotifyMask) +{ + CY_ASSERT_L1(0ul == (ipcNotifyMask & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk))); + CY_ASSERT_L1(0ul == (ipcReleaseMask & ~(uint32_t)(IPC_STRUCT_RELEASE_INTR_RELEASE_Msk))); + base->INTR_SET = _VAL2FLD( IPC_INTR_STRUCT_INTR_NOTIFY, ipcNotifyMask ) | + _VAL2FLD( IPC_INTR_STRUCT_INTR_RELEASE, ipcReleaseMask ); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_ClearInterrupt +****************************************************************************//** +* +* This function is used to clear the interrupt source. Use this function to clear +* a pending interrupt source in the interrupt status. +* +* \param base +* This is a handle to the IPC interrupt. This handle can be calculated from the +* IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr. +* +* \param ipcReleaseMask +* An encoded list of all IPC channels that can trigger the interrupt on a +* release event. +* +* \param ipcNotifyMask +* An encoded list of all IPC channels that can trigger the interrupt on a +* notify event. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_GetInterruptStatusMasked +* +*******************************************************************************/ +__STATIC_INLINE void Cy_IPC_Drv_ClearInterrupt(IPC_INTR_STRUCT_Type* base, uint32_t ipcReleaseMask, uint32_t ipcNotifyMask) +{ + CY_ASSERT_L1(0ul == (ipcNotifyMask & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk))); + CY_ASSERT_L1(0ul == (ipcReleaseMask & ~(uint32_t)(IPC_STRUCT_RELEASE_INTR_RELEASE_Msk))); + base->INTR = _VAL2FLD(IPC_INTR_STRUCT_INTR_NOTIFY, ipcNotifyMask) | + _VAL2FLD(IPC_INTR_STRUCT_INTR_RELEASE, ipcReleaseMask); + (void)base->INTR; /* Read the register to flush the cache */ +} + +/** \} group_ipc_functions */ + +/** \} group_ipc */ + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_AcquireNotify +****************************************************************************//** +* +* The function generates a notify event by IPC interrupt structures. +* +* \param base +* This parameter is a handle that represents the base address of the registers +* of the IPC channel. +* The parameter is generally returned from a call to the \ref +* Cy_IPC_Drv_GetIpcBaseAddress. +* +* \param notifyEventIntr +* Bit encoded list of IPC interrupt structures that are triggered +* by a notification. Bit number correspond to number of the IPC interrupt +* structure. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_LockAcquire +* +*******************************************************************************/ +__STATIC_INLINE void Cy_IPC_Drv_AcquireNotify (IPC_STRUCT_Type* base, uint32_t notifyEventIntr) +{ + CY_ASSERT_L1(0ul == (notifyEventIntr & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk))); + base->NOTIFY = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, notifyEventIntr); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_ReleaseNotify +****************************************************************************//** +* +* The function generates a notify event to an IPC interrupt structure. +* +* \param base +* This parameter is a handle that represents the base address of the registers +* of the IPC channel. +* The parameter is generally returned from a call to the \ref +* Cy_IPC_Drv_GetIpcBaseAddress. +* +* \param notifyEventIntr +* Bit encoded list of IPC interrupt lines that are triggered by a notification. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_ReadMsgWord +* +*******************************************************************************/ +__STATIC_INLINE void Cy_IPC_Drv_ReleaseNotify (IPC_STRUCT_Type* base, uint32_t notifyEventIntr) +{ + CY_ASSERT_L1(0ul == (notifyEventIntr & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk))); + base->RELEASE = _VAL2FLD(IPC_INTR_STRUCT_INTR_RELEASE, notifyEventIntr); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_WriteDataValue +****************************************************************************//** +* +* The function writes a value to the DATA register of the IPC channel. +* +* This function is internal and should not be called directly by user +* software. +* +* \param base +* This parameter is a handle that represents the base address of the registers +* of the IPC channel. +* The parameter is generally returned from a call to the \ref +* Cy_IPC_Drv_GetIpcBaseAddress. +* +* \param dataValue +* Value to be written. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_IPC_Drv_WriteDataValue (IPC_STRUCT_Type* base, uint32_t dataValue) +{ + base->DATA = dataValue; +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_ReadDataValue +****************************************************************************//** +* +* The function reads a value from the DATA register of the IPC channel. +* +* This function is internal and should not be called directly by user +* software. +* +* \param base +* This parameter is a handle that represents the base address of the registers +* of the IPC channel. +* The parameter is generally returned from a call to the \ref +* Cy_IPC_Drv_GetIpcBaseAddress. +* +* \return +* Value from DATA register. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_IPC_Drv_ReadDataValue (IPC_STRUCT_Type const * base) +{ + return (base->DATA); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_IsLockAcquired +****************************************************************************//** +* +* The function is used to test the status of an IPC channel. The function +* tells the reader if the IPC channel was in the locked or released state. +* +* \param base +* This parameter is a handle that represents the base address of the registers +* of the IPC channel. +* The parameter is generally returned from a call to the \ref +* Cy_IPC_Drv_GetIpcBaseAddress. +* +* \return +* Status for the function: +* true: The IPC channel is in the Locked state. +* false: The IPC channel is in the Released state. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_LockAcquire +* +*******************************************************************************/ +__STATIC_INLINE bool Cy_IPC_Drv_IsLockAcquired (IPC_STRUCT_Type const * base) +{ + return ( 0u != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, base->LOCK_STATUS) ); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_GetLockStatus +****************************************************************************//** +* +* The function is used to get the status of an IPC channel. +* +* \param base +* This parameter is a handle that represents the base address of the registers +* of the IPC channel. +* The parameter is generally returned from a call to the \ref +* Cy_IPC_Drv_GetIpcBaseAddress. +* +* \return +* Value from LOCK_STATUS register. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_GetLockStatus +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_IPC_Drv_GetLockStatus (IPC_STRUCT_Type const * base) +{ + return (base->LOCK_STATUS); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_ExtractAcquireMask +****************************************************************************//** +* +* The function extracts an Acquire mask part from full interrupt mask value. +* +* This function is internal and should not be called directly by user +* software. +* +* \param intMask +* Interrupt mask value to be processed. +* +* \return +* Acquire mask value. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_IPC_Drv_ExtractAcquireMask (uint32_t intMask) +{ + return _FLD2VAL(IPC_INTR_STRUCT_INTR_MASK_NOTIFY, intMask); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_ExtractReleaseMask +****************************************************************************//** +* +* The function extracts a Release mask part from full interrupt mask value. +* +* This function is internal and should not be called directly by user +* software. +* +* \param intMask +* Interrupt mask value to be processed. +* +* \return +* Release mask value. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_IPC_Drv_ExtractReleaseMask (uint32_t intMask) +{ + return _FLD2VAL(IPC_INTR_STRUCT_INTR_MASK_RELEASE, intMask); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_SendMsgPtr +****************************************************************************//** +* +* This function is used to send a message pointer through an IPC channel. +* The message structure may hold a generic pointer that may contain the address +* of any user data type or structure. This parameter could be a pointer to a 32-bit +* integer, an array, or even a data structure defined in the user code. This +* function acts as a transfer engine for sending the pointer. Any memory +* management of the pointer allocation and deallocation is up to the application +* code. +* The function also has an associated notification field that will let the +* message notify one or multiple interrupts. +* +* \param base +* This parameter is a handle that represents the base address of the registers +* of the IPC channel. +* The parameter is generally returned from a call to the \ref +* Cy_IPC_Drv_GetIpcBaseAddress. +* +* \param notifyEventIntr +* Bit encoded list of IPC interrupt lines that are triggered during the release +* action. +* +* \param msgPtr +* The message pointer that is being sent over the IPC channel. +* +* \return Status of the operation: +* \retval CY_IPC_DRV_SUCCESS: The send operation was successful. +* \retval CY_IPC_DRV_ERROR: The IPC channel is unavailable because +* it is already locked. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_SendMsgPtr +* +*******************************************************************************/ +__STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_SendMsgPtr(IPC_STRUCT_Type* base, uint32_t notifyEventIntr, void const * msgPtr) +{ + CY_ASSERT_L1(NULL != msgPtr); + return Cy_IPC_Drv_SendMsgWord(base, notifyEventIntr, (uint32_t)msgPtr); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_ReadMsgPtr +****************************************************************************//** +* +* This function is used to read a 32-bit pointer message through an IPC channel. +* +* \param base +* This parameter is a handle that represents the base address of the registers +* of the IPC channel. +* The parameter is generally returned from a call to the \ref +* Cy_IPC_Drv_GetIpcBaseAddress. +* +* \param msgPtr +* Pointer variable to hold the data pointer that is being read from the IPC +* channel. +* +* +* \return Status of the operation +* \retval CY_IPC_DRV_SUCCESS: The function executed successfully and the IPC +* was acquired. +* \retval CY_IPC_DRV_ERROR: The function encountered an error because the IPC +* channel was already in a released state meaning the data +* in it is invalid. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_ReadMsgPtr +* +*******************************************************************************/ +__STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_ReadMsgPtr (IPC_STRUCT_Type const * base, void ** msgPtr) +{ + CY_ASSERT_L1(NULL != msgPtr); + return Cy_IPC_Drv_ReadMsgWord(base, (uint32_t *)msgPtr); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Drv_LockAcquire +****************************************************************************//** +* +* This function is used to acquire the IPC channel. +* +* \param base +* This parameter is a handle that represents the base address of the registers +* of the IPC channel. +* The parameter is generally returned from a call to the \ref +* Cy_IPC_Drv_GetIpcBaseAddress +* +* \return Status of the operation +* \retval CY_IPC_DRV_SUCCESS: The IPC was successfully acquired +* \retval CY_IPC_DRV_ERROR: The IPC was not acquired because it was already acquired +* by another master +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Drv_LockAcquire +* +*******************************************************************************/ +__STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_LockAcquire (IPC_STRUCT_Type const * base) +{ + return ( 0ul != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, base->ACQUIRE)) ? CY_IPC_DRV_SUCCESS : CY_IPC_DRV_ERROR; +} + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(CY_IPC_DRV_H) */ + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_pipe.c b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_pipe.c new file mode 100644 index 0000000000..7c8b830edc --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_pipe.c @@ -0,0 +1,565 @@ +/***************************************************************************//** +* \file cy_ipc_pipe.c +* \version 1.10.1 +* +* Description: +* IPC Pipe Driver - This source file includes code for the Pipe layer on top +* of the IPC driver. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include "cy_ipc_pipe.h" + +/* Define a pointer to array of endPoints. */ +static cy_stc_ipc_pipe_ep_t * cy_ipc_pipe_epArray = NULL; + +/******************************************************************************* +* Function Name: Cy_IPC_Pipe_Config +****************************************************************************//** +* +* This function stores a copy of a pointer to the array of endpoints. All +* access to endpoints will be via the index of the endpoint in this array. +* +* \note In general case, this function is called in the default startup code, +* so user doesn't need to call it anywhere. +* However, it may be useful in case of some pipe customizations. +* +* \param theEpArray +* This is the pointer to an array of endpoint structures that the designer +* created and will be used to reference all endpoints. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_myIpcPipeEpArray +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Pipe_Config +* +*******************************************************************************/ +void Cy_IPC_Pipe_Config(cy_stc_ipc_pipe_ep_t * theEpArray) +{ + /* Keep copy of this endpoint */ + if (cy_ipc_pipe_epArray == NULL) + { + cy_ipc_pipe_epArray = theEpArray; + } +} + +/******************************************************************************* +* Function Name: Cy_IPC_Pipe_Init +****************************************************************************//** +* +* Initializes the system pipes. The system pipes are used by BLE. +* \note The function should be called on all CPUs. +* +* \note In general case, this function is called in the default startup code, +* so user doesn't need to call it anywhere. +* However, it may be useful in case of some pipe customizations. +* +* \param config +* This is the pointer to the pipe configuration structure +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_myIpcPipeCbArray +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_myIpcPipeEpConfig +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Pipe_Init +* +*******************************************************************************/ +void Cy_IPC_Pipe_Init(cy_stc_ipc_pipe_config_t const *config) +{ + /* Create the interrupt structures and arrays needed */ + + cy_stc_sysint_t ipc_intr_cypipeConfig; + + cy_stc_ipc_pipe_ep_config_t epConfigDataA; + cy_stc_ipc_pipe_ep_config_t epConfigDataB; + + /* Parameters checking begin */ + CY_ASSERT_L1(NULL != config); + #if (CY_CPU_CORTEX_M0P) + CY_ASSERT_L2((uint32_t)(1UL << __NVIC_PRIO_BITS) > config->ep0ConfigData.ipcNotifierPriority); + #else + CY_ASSERT_L2((uint32_t)(1UL << __NVIC_PRIO_BITS) > config->ep1ConfigData.ipcNotifierPriority); + #endif + CY_ASSERT_L1(NULL != config->endpointsCallbacksArray); + CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > config->ep0ConfigData.epAddress); + CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > config->ep1ConfigData.epAddress); + CY_ASSERT_L1(NULL != config->userPipeIsrHandler); + /* Parameters checking end */ + +#if (CY_CPU_CORTEX_M0P) + + /* Receiver endpoint = EP0, Sender endpoint = EP1 */ + epConfigDataA = config->ep0ConfigData; + epConfigDataB = config->ep1ConfigData; + + /* Configure CM0 interrupts */ + ipc_intr_cypipeConfig.intrSrc = (IRQn_Type)epConfigDataA.ipcNotifierMuxNumber; + ipc_intr_cypipeConfig.cm0pSrc = (cy_en_intr_t)((int32_t)cpuss_interrupts_ipc_0_IRQn + (int32_t)epConfigDataA.ipcNotifierNumber); + ipc_intr_cypipeConfig.intrPriority = epConfigDataA.ipcNotifierPriority; + +#else + + /* Receiver endpoint = EP1, Sender endpoint = EP0 */ + epConfigDataA = config->ep1ConfigData; + epConfigDataB = config->ep0ConfigData; + + /* Configure interrupts */ + ipc_intr_cypipeConfig.intrSrc = (IRQn_Type)(cpuss_interrupts_ipc_0_IRQn + epConfigDataA.ipcNotifierNumber); + ipc_intr_cypipeConfig.intrPriority = epConfigDataA.ipcNotifierPriority; + +#endif + + /* Initialize the pipe endpoints */ + Cy_IPC_Pipe_EndpointInit(epConfigDataA.epAddress, + config->endpointsCallbacksArray, + config->endpointClientsCount, + epConfigDataA.epConfig, + &ipc_intr_cypipeConfig); + + /* Create the endpoints for the CM4 just for reference */ + Cy_IPC_Pipe_EndpointInit(epConfigDataB.epAddress, NULL, 0ul, epConfigDataB.epConfig, NULL); + + (void)Cy_SysInt_Init(&ipc_intr_cypipeConfig, config->userPipeIsrHandler); + + /* Enable the interrupts */ + NVIC_EnableIRQ(ipc_intr_cypipeConfig.intrSrc); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Pipe_EndpointInit +****************************************************************************//** +* +* This function initializes the endpoint of a pipe for the current CPU. The +* current CPU is the CPU that is executing the code. An endpoint of a pipe +* is for the IPC channel that receives a message for the current CPU. +* +* After this function is called, the callbackArray needs to be populated +* with the callback functions for that endpoint using the +* Cy_IPC_Pipe_RegisterCallback() function. +* +* \note In general case, this function is called within \ref Cy_IPC_Pipe_Init, +* so user doesn't need to call it anywhere. +* However, it may be useful in case of some pipe/endpoint customizations. +* +* \param epAddr +* This parameter is the address (or index in the array of endpoint structures) +* that designates the endpoint you want to initialize. +* +* \param cbArray +* This is a pointer to the callback function array. Based on the client ID, one +* of the functions in this array is called to process the message. +* +* \param cbCnt +* This is the size of the callback array, or the number of defined clients. +* +* \param epConfig +* This value defines the IPC channel, IPC interrupt number, and the interrupt +* mask for the entire pipe. +* The format of the endpoint configuration +* Bits[31:16] Interrupt Mask +* Bits[15:8 ] IPC interrupt +* Bits[ 7:0 ] IPC channel +* +* \param epInterrupt +* This is a pointer to the endpoint interrupt description structure. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_myIpcPipeCbArray +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_myIpcPipeEpConfig +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Pipe_EndpointInit +* +*******************************************************************************/ +void Cy_IPC_Pipe_EndpointInit(uint32_t epAddr, cy_ipc_pipe_callback_array_ptr_t cbArray, + uint32_t cbCnt, uint32_t epConfig, cy_stc_sysint_t const *epInterrupt) +{ + cy_stc_ipc_pipe_ep_t * endpoint; + + CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > epAddr); + + endpoint = &cy_ipc_pipe_epArray[epAddr]; + + /* Extract the channel, interrupt and interrupt mask */ + endpoint->ipcChan = _FLD2VAL(CY_IPC_PIPE_CFG_CHAN, epConfig); + endpoint->intrChan = _FLD2VAL(CY_IPC_PIPE_CFG_INTR, epConfig); + endpoint->pipeIntMask = _FLD2VAL(CY_IPC_PIPE_CFG_IMASK, epConfig); + + /* Assign IPC channel to this endpoint */ + endpoint->ipcPtr = Cy_IPC_Drv_GetIpcBaseAddress (endpoint->ipcChan); + + /* Assign interrupt structure to endpoint and Initialize the interrupt mask for this endpoint */ + endpoint->ipcIntrPtr = Cy_IPC_Drv_GetIntrBaseAddr(endpoint->intrChan); + + /* Only allow notify and release interrupts from endpoints in this pipe. */ + Cy_IPC_Drv_SetInterruptMask(endpoint->ipcIntrPtr, endpoint->pipeIntMask, endpoint->pipeIntMask); + + /* Save the Client count and the callback array pointer */ + endpoint->clientCount = cbCnt; + endpoint->callbackArray = cbArray; + endpoint->busy = CY_IPC_PIPE_ENDPOINT_NOTBUSY; + + if (NULL != epInterrupt) + { + endpoint->pipeIntrSrc = epInterrupt->intrSrc; + } +} + + +/******************************************************************************* +* Function Name: Cy_IPC_Pipe_SendMessage +****************************************************************************//** +* +* This function is used to send a message from one endpoint to another. It +* generates an interrupt on the endpoint that receives the message and a +* release interrupt to the sender to acknowledge the message has been processed. +* +* \param toAddr +* This parameter is the address (or index in the array of endpoint structures) +* of the endpoint to which you are sending the message. +* +* \param fromAddr +* This parameter is the address (or index in the array of endpoint structures) +* of the endpoint from which the message is being sent. +* +* \param msgPtr +* Pointer to the message structure to be sent. +* +* \param callBackPtr +* Pointer to the Release callback function. +* +* \return +* CY_IPC_PIPE_SUCCESS: Message was sent to the other end of the pipe +* CY_IPC_PIPE_ERROR_BAD_HANDLE: The handle provided for the pipe was not valid +* CY_IPC_PIPE_ERROR_SEND_BUSY: The pipe is already busy sending a message +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_myReleaseCallback +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Pipe_SendMessage +* +*******************************************************************************/ +cy_en_ipc_pipe_status_t Cy_IPC_Pipe_SendMessage(uint32_t toAddr, uint32_t fromAddr, + void * msgPtr, cy_ipc_pipe_relcallback_ptr_t callBackPtr) +{ + cy_en_ipc_pipe_status_t returnStatus; + uint32_t releaseMask; + uint32_t notifyMask; + + cy_stc_ipc_pipe_ep_t * fromEp; + cy_stc_ipc_pipe_ep_t * toEp; + + CY_ASSERT_L1(NULL != msgPtr); + CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > toAddr); + CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > fromAddr); + + toEp = &(cy_ipc_pipe_epArray[toAddr]); + fromEp = &cy_ipc_pipe_epArray[fromAddr]; + + /* Create the release mask for the "fromAddr" channel's interrupt channel */ + releaseMask = (uint32_t)(1ul << (fromEp->intrChan)); + + /* Shift into position */ + releaseMask = _VAL2FLD(CY_IPC_PIPE_MSG_RELEASE, releaseMask); + + /* Create the notify mask for the "toAddr" channel's interrupt channel */ + notifyMask = (uint32_t)(1ul << (toEp->intrChan)); + + /* Check if IPC channel valid */ + if( toEp->ipcPtr != NULL) + { + if(fromEp->busy == CY_IPC_PIPE_ENDPOINT_NOTBUSY) + { + /* Attempt to acquire the channel */ + if( CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockAcquire(toEp->ipcPtr) ) + { + /* Mask out the release mask area */ + * (uint32_t *) msgPtr &= ~(CY_IPC_PIPE_MSG_RELEASE_Msk); + + * (uint32_t *) msgPtr |= releaseMask; + + /* If the channel was acquired, write the message. */ + Cy_IPC_Drv_WriteDataValue(toEp->ipcPtr, (uint32_t) msgPtr); + + /* Set the busy flag. The ISR clears this after the release */ + fromEp->busy = CY_IPC_PIPE_ENDPOINT_BUSY; + + /* Setup release callback function */ + fromEp->releaseCallbackPtr = callBackPtr; + + /* Cause notify event/interrupt */ + Cy_IPC_Drv_AcquireNotify(toEp->ipcPtr, notifyMask); + + returnStatus = CY_IPC_PIPE_SUCCESS; + } + else + { + /* Channel was already acquired, return Error */ + returnStatus = CY_IPC_PIPE_ERROR_SEND_BUSY; + } + } + else + { + /* Channel may not be acquired, but the release interrupt has not executed yet */ + returnStatus = CY_IPC_PIPE_ERROR_SEND_BUSY; + } + } + else + { + /* Null pipe handle. */ + returnStatus = CY_IPC_PIPE_ERROR_BAD_HANDLE; + } + return (returnStatus); +} + + + +/******************************************************************************* +* Function Name: Cy_IPC_Pipe_RegisterCallback +****************************************************************************//** +* +* This function registers a callback that is called when a message is received +* on a pipe. +* The client_ID is the same as the index of the callback function array. +* The callback may be a real function pointer or NULL if no callback is required. +* +* \param epAddr +* This parameter is the address (or index in the array of endpoint structures) +* that designates the endpoint to which you want to add callback functions. +* +* \param callBackPtr +* Pointer to the callback function called when the endpoint has received a message. +* If this parameters is NULL current callback will be unregistered. +* +* \param clientId +* The index in the callback array (Client ID) where the function pointer is saved. +* +* \return +* CY_IPC_PIPE_SUCCESS: Callback registered successfully +* CY_IPC_PIPE_ERROR_BAD_CLIENT: Client ID out of range, callback not registered. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_myAcquireCallback +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Pipe_RegisterCallback +* +*******************************************************************************/ +cy_en_ipc_pipe_status_t Cy_IPC_Pipe_RegisterCallback(uint32_t epAddr, cy_ipc_pipe_callback_ptr_t callBackPtr, uint32_t clientId) +{ + cy_en_ipc_pipe_status_t returnStatus; + cy_stc_ipc_pipe_ep_t * thisEp; + + CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > epAddr); + + thisEp = &cy_ipc_pipe_epArray[epAddr]; + + /* Check if clientId is between 0 and less than client count */ + if (clientId < thisEp->clientCount) + { + /* Copy callback function into callback function pointer array */ + thisEp->callbackArray[clientId] = callBackPtr; + + returnStatus = CY_IPC_PIPE_SUCCESS; + } + else + { + returnStatus = CY_IPC_PIPE_ERROR_BAD_CLIENT; + } + return (returnStatus); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Pipe_RegisterCallbackRel +****************************************************************************//** +* +* This function registers a default callback if a release interrupt +* is generated but the current release callback function is null. +* +* +* \param epAddr +* This parameter is the address (or index in the array of endpoint structures) +* that designates the endpoint to which you want to add a release callback function. +* +* \param callBackPtr +* Pointer to the callback executed when the endpoint has received a message. +* If this parameters is NULL current callback will be unregistered. +* +* \return +* None +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_myDefaultReleaseCallback +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Pipe_RegisterCallbackRel +* +*******************************************************************************/ +void Cy_IPC_Pipe_RegisterCallbackRel(uint32_t epAddr, cy_ipc_pipe_relcallback_ptr_t callBackPtr) +{ + cy_stc_ipc_pipe_ep_t * endpoint; + + CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > epAddr); + + endpoint = &cy_ipc_pipe_epArray[epAddr]; + + /* Copy callback function into callback function pointer array */ + endpoint->defaultReleaseCallbackPtr = callBackPtr; +} + +/******************************************************************************* +* Function Name: Cy_IPC_Pipe_ExecCallback +****************************************************************************//** +* +* This function is called by the ISR for a given pipe endpoint to dispatch +* the appropriate callback function based on the client ID for that endpoint. +* +* \param endpoint +* Pointer to endpoint structure. +* +* \return +* None +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_myIpcPipeEpArray +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Pipe_ExecCallback +* +*******************************************************************************/ +void Cy_IPC_Pipe_ExecCallback(cy_stc_ipc_pipe_ep_t * endpoint) +{ + uint32_t *msgPtr = NULL; + uint32_t clientID; + uint32_t shadowIntr; + uint32_t releaseMask = (uint32_t)0; + + cy_ipc_pipe_callback_ptr_t callbackPtr; + + /* Parameters checking begin */ + CY_ASSERT_L1(NULL != endpoint); + CY_ASSERT_L1(NULL != endpoint->ipcPtr); + CY_ASSERT_L1(NULL != endpoint->ipcIntrPtr); + CY_ASSERT_L1(NULL != endpoint->callbackArray); + /* Parameters checking end */ + + shadowIntr = Cy_IPC_Drv_GetInterruptStatusMasked(endpoint->ipcIntrPtr); + + /* Check to make sure the interrupt was a notify interrupt */ + if (0ul != Cy_IPC_Drv_ExtractAcquireMask(shadowIntr)) + { + /* Clear the notify interrupt. */ + Cy_IPC_Drv_ClearInterrupt(endpoint->ipcIntrPtr, CY_IPC_NO_NOTIFICATION, Cy_IPC_Drv_ExtractAcquireMask(shadowIntr)); + + if ( Cy_IPC_Drv_IsLockAcquired (endpoint->ipcPtr) ) + { + /* Extract Client ID */ + if( CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_ReadMsgPtr (endpoint->ipcPtr, (void **)&msgPtr)) + { + /* Get release mask */ + releaseMask = _FLD2VAL(CY_IPC_PIPE_MSG_RELEASE, *msgPtr); + clientID = _FLD2VAL(CY_IPC_PIPE_MSG_CLIENT, *msgPtr); + + /* Make sure client ID is within valid range */ + if (endpoint->clientCount > clientID) + { + callbackPtr = endpoint->callbackArray[clientID]; /* Get the callback function */ + + if (callbackPtr != NULL) + { + callbackPtr(msgPtr); /* Call the function pointer for "clientID" */ + } + } + } + + /* Must always release the IPC channel */ + (void)Cy_IPC_Drv_LockRelease (endpoint->ipcPtr, releaseMask); + } + } + + /* Check to make sure the interrupt was a release interrupt */ + if (0ul != Cy_IPC_Drv_ExtractReleaseMask(shadowIntr)) /* Check for a Release interrupt */ + { + /* Clear the release interrupt */ + Cy_IPC_Drv_ClearInterrupt(endpoint->ipcIntrPtr, Cy_IPC_Drv_ExtractReleaseMask(shadowIntr), CY_IPC_NO_NOTIFICATION); + + if (endpoint->releaseCallbackPtr != NULL) + { + endpoint->releaseCallbackPtr(); + + /* Clear the pointer after it was called */ + endpoint->releaseCallbackPtr = NULL; + } + else + { + if (endpoint->defaultReleaseCallbackPtr != NULL) + { + endpoint->defaultReleaseCallbackPtr(); + } + } + + /* Clear the busy flag when release is detected */ + endpoint->busy = CY_IPC_PIPE_ENDPOINT_NOTBUSY; + } + + (void)Cy_IPC_Drv_GetInterruptStatus(endpoint->ipcIntrPtr); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Pipe_EndpointPause +****************************************************************************//** +* +* This function sets the receiver endpoint to paused state. +* +* \param epAddr +* This parameter is the address (or index in the array of endpoint structures) +* that designates the endpoint to pause. +* +* \return +* CY_IPC_PIPE_SUCCESS: Callback registered successfully +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Pipe_EndpointPauseResume +* +*******************************************************************************/ +cy_en_ipc_pipe_status_t Cy_IPC_Pipe_EndpointPause(uint32_t epAddr) +{ + cy_stc_ipc_pipe_ep_t * endpoint; + + CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > epAddr); + + endpoint = &cy_ipc_pipe_epArray[epAddr]; + + /* Disable the interrupts */ + NVIC_DisableIRQ(endpoint->pipeIntrSrc); + + return (CY_IPC_PIPE_SUCCESS); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Pipe_EndpointResume +****************************************************************************//** +* +* This function sets the receiver endpoint to active state. +* +* \param epAddr +* This parameter is the address (or index in the array of endpoint structures) +* that designates the endpoint to resume. +* +* \return +* CY_IPC_PIPE_SUCCESS: Callback registered successfully +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Pipe_EndpointPauseResume +* +*******************************************************************************/ +cy_en_ipc_pipe_status_t Cy_IPC_Pipe_EndpointResume(uint32_t epAddr) +{ + cy_stc_ipc_pipe_ep_t * endpoint; + + CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > epAddr); + + endpoint = &cy_ipc_pipe_epArray[epAddr]; + + /* Enable the interrupts */ + NVIC_EnableIRQ(endpoint->pipeIntrSrc); + + return (CY_IPC_PIPE_SUCCESS); +} + + +/* [] END OF FILE */ + diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_pipe.h b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_pipe.h new file mode 100644 index 0000000000..0bac9a0e16 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_pipe.h @@ -0,0 +1,265 @@ +/***************************************************************************//** +* \file cy_ipc_pipe.h +* \version 1.10.1 +* +* Description: +* IPC Pipe Driver - This header file contains all the function prototypes, +* structure definitions, pipe constants, and pipe endpoint address definitions. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ +#ifndef CY_IPC_PIPE_H +#define CY_IPC_PIPE_H + +/******************************************************************************/ +/* Include files */ +/******************************************************************************/ +#include "ipc/cy_ipc_drv.h" +#include "syslib/cy_syslib.h" +#include "sysint/cy_sysint.h" + +/** +* \addtogroup group_ipc_pipe IPC pipes layer (IPC_PIPE) +* \{ +* The Pipe functions provide a method to transfer one or more words of data +* between CPUs or tasks. The data can be defined as a single 32-bit unsigned +* word, an array of data, or a user-defined structure. The only limitation is +* that the first word in the array or structure must be a 32-bit unsigned word +* in which a client ID number is passed. The client ID dictates the callback +* function that will be called by the receiver of the message. After the +* callback function returns by the receiver, it will invoke a release callback +* function defined by the sender of the message. +* +* A User Pipe is provided for the user to transfer data between CPUs and +* tasks. +* +* \defgroup group_ipc_pipe_macros Macros +* Macro definitions are used in the driver +* +* \defgroup group_ipc_pipe_functions Functions +* Functions are used in the driver +* +* \defgroup group_ipc_pipe_data_structures Data Structures +* Data structures are used in the driver +* +* \defgroup group_ipc_pipe_enums Enumerated Types +* Enumerations are used in the driver +* \} +* +*/ + +/* + * This section defines the system level constants required to define + * callback arrays for the Cypress pipe and the user pipe. These defines + * are used for both the max callback count and maximum clients. +*/ + +/** Typedef for pipe callback function pointer */ +typedef void (* cy_ipc_pipe_callback_ptr_t)(uint32_t * msgPtr); + +/** Typedef for a pipe release callback function pointer */ +typedef void (* cy_ipc_pipe_relcallback_ptr_t)(void); + +/** Typedef for array of callback function pointers */ +typedef cy_ipc_pipe_callback_ptr_t *cy_ipc_pipe_callback_array_ptr_t; + + +/** +* \addtogroup group_ipc_pipe_macros +* \{ +*/ + +/* + * The System pipe address is what is used to send a message to one of the + * endpoints of a pipe. Currently the Cypress pipe and the User pipe + * are supported. For parts with extra IPC channels users may create + * their own custom pipes and create their own pipe addresses. + * + * The format of the endpoint configuration + * Bits[31:16] Interrupt Mask + * Bits[15:8 ] IPC interrupt + * Bits[ 7:0 ] IPC channel + */ +#define CY_IPC_PIPE_CFG_IMASK_Pos (16UL) /**< Interrupts shift value for endpoint address */ +#define CY_IPC_PIPE_CFG_IMASK_Msk (0xFFFF0000UL) /**< Interrupts mask for endpoint address */ +#define CY_IPC_PIPE_CFG_INTR_Pos (8UL) /**< IPC Interrupt shift value for endpoint address */ +#define CY_IPC_PIPE_CFG_INTR_Msk (0x0000FF00UL) /**< IPC Interrupt mask for endpoint address */ +#define CY_IPC_PIPE_CFG_CHAN_Pos (0UL) /**< IPC Channel shift value for endpoint address */ +#define CY_IPC_PIPE_CFG_CHAN_Msk (0x000000FFUL) /**< IPC Channel mask for endpoint address */ + + + +#define CY_IPC_PIPE_MSG_CLIENT_Msk (0x000000FFul) /**< Client mask for first word of Pipe message */ +#define CY_IPC_PIPE_MSG_CLIENT_Pos (0ul) /**< Client shift for first word of Pipe message */ +#define CY_IPC_PIPE_MSG_USR_Msk (0x0000FF00ul) /**< User data mask for first word of Pipe message */ +#define CY_IPC_PIPE_MSG_USR_Pos (8ul) /**< User data shift for first word of Pipe message */ +#define CY_IPC_PIPE_MSG_RELEASE_Msk (0xFFFF0000ul) /**< Mask for message release mask */ +#define CY_IPC_PIPE_MSG_RELEASE_Pos (16UL) /**< Shift require to line up mask to LSb */ + +/** Use to set the busy flag when waiting for a release interrupt */ +#define CY_IPC_PIPE_ENDPOINT_BUSY (1UL) +/** Denotes that a release interrupt is not pending */ +#define CY_IPC_PIPE_ENDPOINT_NOTBUSY (0UL) + +/** \} group_ipc_pipe_macros */ + +/** +* \addtogroup group_ipc_pipe_data_structures +* \{ +*/ + +/** +* This is the definition of a pipe endpoint. There is one endpoint structure +* for each CPU in a pipe. It contains all the information to process a message +* send to other CPUs in the pipe. +*/ +typedef struct +{ + uint32_t ipcChan; /**< IPC channel number used for this endpoint to receive messages */ + uint32_t intrChan; /**< IPC interrupt channel number used for this endpoint to receive interrupts */ + uint32_t pipeIntMask; /**< Release/Notify interrupt mask that includes all endpoints on pipe */ + IRQn_Type pipeIntrSrc; /**< Interrupt vector number that includes all endpoints on pipe */ + + IPC_STRUCT_Type *ipcPtr; /**< Pointer to receive IPC channel ( If ipcPtr == NULL, cannot receive ) */ + IPC_INTR_STRUCT_Type *ipcIntrPtr; /**< Pointer to IPC interrupt, needed to clear the interrupt */ + uint32_t busy; /**< Endpoint busy flag. If sent no messages can be sent from this endpoint */ + uint32_t clientCount; /**< Client count and size of MsgCallback array */ + + cy_ipc_pipe_callback_array_ptr_t callbackArray; /**< Pointer to array of callback functions, one for each Client */ + cy_ipc_pipe_relcallback_ptr_t releaseCallbackPtr; /**< Pointer to release callback function */ + cy_ipc_pipe_relcallback_ptr_t defaultReleaseCallbackPtr; /**< Pointer to default release callback function */ +} cy_stc_ipc_pipe_ep_t; + +/** The Pipe endpoint configuration structure. */ +typedef struct +{ + uint32_t ipcNotifierNumber; /**< Notifier */ + uint32_t ipcNotifierPriority; /**< Notifier Priority */ + uint32_t ipcNotifierMuxNumber; /**< CM0+ interrupt multiplexer number */ + + uint32_t epAddress; /**< Index in the array of endpoint structure */ + uint32_t epConfig; /**< Configuration mask, contains IPC channel, IPC interrupt number, + and the interrupt mask */ +} cy_stc_ipc_pipe_ep_config_t; + +/** The Pipe channel configuration structure. */ +typedef struct +{ + /** Specifies the notify interrupt number for the first endpoint */ + cy_stc_ipc_pipe_ep_config_t ep0ConfigData; + + /** Specifies the notify interrupt number for the second endpoint */ + cy_stc_ipc_pipe_ep_config_t ep1ConfigData; + + /** Client count and size of MsgCallback array */ + uint32_t endpointClientsCount; + + /** Pipes callback function array. */ + cy_ipc_pipe_callback_array_ptr_t endpointsCallbacksArray; + + /** User IRQ handler function that is called when IPC receive data to process (interrupt was raised). */ + cy_israddress userPipeIsrHandler; +} cy_stc_ipc_pipe_config_t; + +/** \} goup_ipc_pipe_data_structures */ + +/** +* \addtogroup group_ipc_pipe_macros +* \{ +*/ +/* Status and error types */ +#define CY_IPC_PIPE_RTN (0x0200ul) /**< Software PDL driver ID for IPC pipe functions */ +#define CY_IPC_PIPE_ID_INFO (uint32_t)( CY_IPC_ID_INFO | CY_IPC_PIPE_RTN) /**< Return prefix for IPC pipe function status codes */ +#define CY_IPC_PIPE_ID_WARNING (uint32_t)( CY_IPC_ID_WARNING | CY_IPC_PIPE_RTN) /**< Return prefix for IPC pipe function warning return values */ +#define CY_IPC_PIPE_ID_ERROR (uint32_t)( CY_IPC_ID_ERROR | CY_IPC_PIPE_RTN) /**< Return prefix for IPC pipe function error return values */ + +/** \} group_ipc_pipe_macros */ + +/** +* \addtogroup group_ipc_pipe_enums +* \{ +*/ + +/** Return constants for IPC pipe functions. */ +typedef enum +{ + CY_IPC_PIPE_SUCCESS =(uint32_t)(0x00u), /**< Pipe API return for no error */ + CY_IPC_PIPE_ERROR_NO_IPC =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 1ul), /**< Pipe API return for no valid IPC channel */ + CY_IPC_PIPE_ERROR_NO_INTR =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 2ul), /**< Pipe API return for no valid interrupt */ + CY_IPC_PIPE_ERROR_BAD_PRIORITY =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 3ul), /**< Pipe API return for bad priority parameter */ + CY_IPC_PIPE_ERROR_BAD_HANDLE =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 4ul), /**< Pipe API return for bad pipe handle */ + CY_IPC_PIPE_ERROR_BAD_ID =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 5ul), /**< Pipe API return for bad pipe ID */ + CY_IPC_PIPE_ERROR_DIR_ERROR =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 6ul), /**< Pipe API return for invalid direction (Not used at this time) */ + CY_IPC_PIPE_ERROR_SEND_BUSY =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 7ul), /**< Pipe API return for pipe is currently busy */ + CY_IPC_PIPE_ERROR_NO_MESSAGE =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 8ul), /**< Pipe API return for no message indicated */ + CY_IPC_PIPE_ERROR_BAD_CPU =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 9ul), /**< Pipe API return for invalid CPU value */ + CY_IPC_PIPE_ERROR_BAD_CLIENT =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 10ul) /**< Pipe API return for client out of range */ +} cy_en_ipc_pipe_status_t; + +/** \} group_ipc_pipe_enums */ + +/** +* \addtogroup group_ipc_pipe_data_structures +* \{ +*/ + +/** \cond +* NOTE: This doxygen comment must be placed before some code entity, or else +* it will belong to a random entity that follows it, e.g. group_ipc_functions +* +* Client identifier for a message. +* For a given pipe, traffic across the pipe can be multiplexed with multiple +* senders on one end and multiple receivers on the other end. +* +* The first 32-bit word of the message is used to identify the client that owns +* the message. +* +* The upper 16 bits are the client ID. +* +* The lower 16 bits are for use by the client in any way desired. +* +* The lower 16 bits are preserved (not modified) and not interpreted in any way. +* \endcond +*/ + +/** \} group_ipc_pipe_data_structures */ + +/******************************************************************************/ +/* Global function prototypes (definition in C source) */ +/******************************************************************************/ + +/** +* \addtogroup group_ipc_pipe_functions +* \{ +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +void Cy_IPC_Pipe_EndpointInit(uint32_t epAddr, cy_ipc_pipe_callback_array_ptr_t cbArray, + uint32_t cbCnt, uint32_t epConfig, cy_stc_sysint_t const *epInterrupt); +cy_en_ipc_pipe_status_t Cy_IPC_Pipe_SendMessage(uint32_t toAddr, uint32_t fromAddr, void *msgPtr, + cy_ipc_pipe_relcallback_ptr_t callBackPtr); +cy_en_ipc_pipe_status_t Cy_IPC_Pipe_RegisterCallback(uint32_t epAddr, + cy_ipc_pipe_callback_ptr_t callBackPtr, uint32_t clientId); +void Cy_IPC_Pipe_ExecCallback(cy_stc_ipc_pipe_ep_t * endpoint); +void Cy_IPC_Pipe_RegisterCallbackRel(uint32_t epAddr, cy_ipc_pipe_relcallback_ptr_t callBackPtr); +void Cy_IPC_Pipe_Config(cy_stc_ipc_pipe_ep_t * theEpArray); +void Cy_IPC_Pipe_Init(cy_stc_ipc_pipe_config_t const *config); + +cy_en_ipc_pipe_status_t Cy_IPC_Pipe_EndpointPause(uint32_t epAddr); +cy_en_ipc_pipe_status_t Cy_IPC_Pipe_EndpointResume(uint32_t epAddr); + +#ifdef __cplusplus +} +#endif + +/** \} group_ipc_pipe_functions */ + +#endif /* CY_IPC_PIPE_H */ + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_sema.c b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_sema.c new file mode 100644 index 0000000000..1154997e23 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_sema.c @@ -0,0 +1,392 @@ +/***************************************************************************//** +* \file cy_ipc_sema.c +* \version 1.10.1 +* +* Description: +* IPC Semaphore Driver - This source file contains the source code for the +* semaphore level APIs for the IPC interface. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include "ipc/cy_ipc_drv.h" +#include "ipc/cy_ipc_sema.h" +#include "syslib/cy_syslib.h" +#include /* The memset() definition */ + +/* Defines a mask to Check if semaphore count is a multiple of 32 */ +#define CY_IPC_SEMA_PER_WORD_MASK (CY_IPC_SEMA_PER_WORD - 1ul) + +/* Pointer to IPC structure used for semaphores */ +static IPC_STRUCT_Type* cy_semaIpcStruct; + +/* +* Internal IPC semaphore control data structure. +*/ +typedef struct +{ + uint32_t maxSema; /* Maximum semaphores in system */ + uint32_t *arrayPtr; /* Pointer to semaphores array */ +} cy_stc_ipc_sema_t; + +/******************************************************************************* +* Function Name: Cy_IPC_Sema_Init +****************************************************************************//** +* +* This function initializes the semaphores subsystem. The user must create an +* array of unsigned 32-bit words to hold the semaphore bits. The number +* of semaphores will be the size of the array * 32. The total semaphores count +* will always be a multiple of 32. +* +* \note In a multi-CPU system this init function should be called with all +* initialized parameters on one CPU only to provide a pointer to SRAM that can +* be shared between all the CPUs in the system that will use semaphores. +* On other CPUs user must specify the IPC semaphores channel and pass 0 / NULL +* to count and memPtr parameters correspondingly. +* +* \param ipcChannel +* The IPC channel number used for semaphores +* +* \param count +* The maximum number of semaphores to be supported (multiple of 32). +* +* \param memPtr +* This points to the array of (count/32) words that contain the semaphore data. +* +* \return Status of the operation +* \retval CY_IPC_SEMA_SUCCESS: Successfully initialized +* \retval CY_IPC_SEMA_BAD_PARAM: Memory pointer is NULL and count is not zero, +* or count not multiple of 32 +* \retval CY_IPC_SEMA_ERROR_LOCKED: Could not acquire semaphores IPC channel +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Sema_Init +* +*******************************************************************************/ +cy_en_ipcsema_status_t Cy_IPC_Sema_Init(uint32_t ipcChannel, + uint32_t count, uint32_t memPtr[]) +{ + /* Structure containing semaphores control data */ + static cy_stc_ipc_sema_t cy_semaData; + + cy_en_ipcsema_status_t retStatus = CY_IPC_SEMA_BAD_PARAM; + + if (ipcChannel >= CY_IPC_CHANNELS) + { + retStatus = CY_IPC_SEMA_BAD_PARAM; + } + else + { + if( (NULL == memPtr) && (0u == count)) + { + cy_semaIpcStruct = Cy_IPC_Drv_GetIpcBaseAddress(ipcChannel); + + retStatus = CY_IPC_SEMA_SUCCESS; + } + + /* Check for non Null pointers and count value */ + else if ((NULL != memPtr) && (0u != count)) + { + /* Check if semaphore count is a multiple of 32 */ + if( 0ul == (count & CY_IPC_SEMA_PER_WORD_MASK)) + { + cy_semaIpcStruct = Cy_IPC_Drv_GetIpcBaseAddress(ipcChannel); + + cy_semaData.maxSema = count; + cy_semaData.arrayPtr = memPtr; + + /* Initialize all semaphores to released */ + (void)memset(cy_semaData.arrayPtr, 0, (count /8u)); + + /* Make sure semaphores start out released. */ + /* Ignore the return value since it is OK if it was already released. */ + (void) Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION); + + /* Set the IPC Data with the pointer to the array. */ + if( CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_SendMsgPtr (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION, &cy_semaData)) + { + if(CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION)) + { + retStatus = CY_IPC_SEMA_SUCCESS; + } + else + { + /* IPC channel not released, still semaphored */ + retStatus = CY_IPC_SEMA_ERROR_LOCKED; + } + } + else + { + /* Could not acquire semaphore channel */ + retStatus = CY_IPC_SEMA_ERROR_LOCKED; + } + } + else + { + retStatus = CY_IPC_SEMA_BAD_PARAM; + } + } + else + { + retStatus = CY_IPC_SEMA_BAD_PARAM; + } + } + + return(retStatus); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Sema_Set +****************************************************************************//** +* +* This function tries to acquire a semaphore. If the +* semaphore is not available, this function returns immediately with +* CY_IPC_SEMA_LOCKED. +* +* It first acquires the IPC channel that is used for all the semaphores, sets +* the semaphore if it is cleared, then releases the IPC channel used for the +* semaphore. +* +* \param semaNumber +* The semaphore number to acquire. +* +* \param preemptable +* When this parameter is enabled the function can be preempted by another +* task or other forms of context switching in an RTOS environment. +* +* \note +* If preemptable is enabled (true), the user must ensure that there are +* no deadlocks in the system, which can be caused by an interrupt that occurs +* after the IPC channel is locked. Unless the user is ready to handle IPC +* channel locks correctly at the application level, set premptable to +* false. +* +* \return Status of the operation +* \retval CY_IPC_SEMA_SUCCESS: The semaphore was set successfully +* \retval CY_IPC_SEMA_LOCKED: The semaphore channel is busy or locked +* by another process +* \retval CY_IPC_SEMA_NOT_ACQUIRED: Semaphore was already set +* \retval CY_IPC_SEMA_OUT_OF_RANGE: The semaphore number is not valid +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Sema_Set +* +*******************************************************************************/ +cy_en_ipcsema_status_t Cy_IPC_Sema_Set(uint32_t semaNumber, bool preemptable) +{ + uint32_t semaIndex; + uint32_t semaMask; + uint32_t interruptState = 0ul; + + cy_stc_ipc_sema_t *semaStruct; + cy_en_ipcsema_status_t retStatus = CY_IPC_SEMA_LOCKED; + + /* Get pointer to structure */ + semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct); + + if (semaNumber < semaStruct->maxSema) + { + semaIndex = semaNumber / CY_IPC_SEMA_PER_WORD; + semaMask = (uint32_t)(1ul << (semaNumber - (semaIndex * CY_IPC_SEMA_PER_WORD) )); + + if (!preemptable) + { + interruptState = Cy_SysLib_EnterCriticalSection(); + } + + /* Check to make sure the IPC channel is released + If so, check if specific channel can be locked. */ + if(CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockAcquire (cy_semaIpcStruct)) + { + if((semaStruct->arrayPtr[semaIndex] & semaMask) == 0ul) + { + semaStruct->arrayPtr[semaIndex] |= semaMask; + retStatus = CY_IPC_SEMA_SUCCESS; + } + else + { + retStatus = CY_IPC_SEMA_NOT_ACQUIRED; + } + + /* Release, but do not trigger a release event */ + (void) Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION); + } + + if (!preemptable) + { + Cy_SysLib_ExitCriticalSection(interruptState); + } + } + else + { + retStatus = CY_IPC_SEMA_OUT_OF_RANGE; + } + + return(retStatus); +} + + +/******************************************************************************* +* Function Name: Cy_IPC_Sema_Clear +****************************************************************************//** +* +* This functions tries to releases a semaphore. +* +* It first acquires the IPC channel that is used for all the semaphores, clears +* the semaphore if it is set, then releases the IPC channel used for the +* semaphores. +* +* \param semaNumber +* The index of the semaphore to release. +* +* \param preemptable +* When this parameter is enabled the function can be preempted by another +* task or other forms of context switching in an RTOS environment. +* +* \note +* If preemptable is enabled (true), the user must ensure that there are +* no deadlocks in the system, which can be caused by an interrupt that occurs +* after the IPC channel is locked. Unless the user is ready to handle IPC +* channel locks correctly at the application level, set premptable to +* false. +* +* \return Status of the operation +* \retval CY_IPC_SEMA_SUCCESS: The semaphore was cleared successfully +* \retval CY_IPC_SEMA_NOT_ACQUIRED: The semaphore was already cleared +* \retval CY_IPC_SEMA_LOCKED: The semaphore channel was semaphored or busy +* \retval CY_IPC_SEMA_OUT_OF_RANGE: The semaphore number is not valid +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Sema_Clear +* +*******************************************************************************/ +cy_en_ipcsema_status_t Cy_IPC_Sema_Clear(uint32_t semaNumber, bool preemptable) +{ + uint32_t semaIndex; + uint32_t semaMask; + uint32_t interruptState = 0ul; + + cy_stc_ipc_sema_t *semaStruct; + cy_en_ipcsema_status_t retStatus = CY_IPC_SEMA_LOCKED; + + /* Get pointer to structure */ + semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct); + + if (semaNumber < semaStruct->maxSema) + { + semaIndex = semaNumber / CY_IPC_SEMA_PER_WORD; + semaMask = (uint32_t)(1ul << (semaNumber - (semaIndex * CY_IPC_SEMA_PER_WORD) )); + + if (!preemptable) + { + interruptState = Cy_SysLib_EnterCriticalSection(); + } + + /* Check to make sure the IPC channel is released + If so, check if specific channel can be locked. */ + if(CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockAcquire (cy_semaIpcStruct)) + { + if((semaStruct->arrayPtr[semaIndex] & semaMask) != 0ul) + { + semaStruct->arrayPtr[semaIndex] &= ~semaMask; + retStatus = CY_IPC_SEMA_SUCCESS; + } + else + { + retStatus = CY_IPC_SEMA_NOT_ACQUIRED; + } + + /* Release, but do not trigger a release event */ + (void) Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION); + } + + if (!preemptable) + { + Cy_SysLib_ExitCriticalSection(interruptState); + } + } + else + { + retStatus = CY_IPC_SEMA_OUT_OF_RANGE; + } + return(retStatus); +} + +/******************************************************************************* +* Function Name: Cy_IPC_Sema_Status +****************************************************************************//** +* +* This function returns the status of the semaphore. +* +* \param semaNumber +* The index of the semaphore to return status. +* +* \return Status of the operation +* \retval CY_IPC_SEMA_STATUS_LOCKED: The semaphore is in the set state. +* \retval CY_IPC_SEMA_STATUS_UNLOCKED: The semaphore is in the cleared state. +* \retval CY_IPC_SEMA_OUT_OF_RANGE: The semaphore number is not valid +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Sema_Status +* +*******************************************************************************/ +cy_en_ipcsema_status_t Cy_IPC_Sema_Status(uint32_t semaNumber) +{ + cy_en_ipcsema_status_t retStatus; + uint32_t semaIndex; + uint32_t semaMask; + cy_stc_ipc_sema_t *semaStruct; + + /* Get pointer to structure */ + semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct); + + if (semaNumber < semaStruct->maxSema) + { + /* Get the index into the semaphore array and calculate the mask */ + semaIndex = semaNumber / CY_IPC_SEMA_PER_WORD; + semaMask = (uint32_t)(1ul << (semaNumber - (semaIndex * CY_IPC_SEMA_PER_WORD) )); + + if((semaStruct->arrayPtr[semaIndex] & semaMask) != 0ul) + { + retStatus = CY_IPC_SEMA_STATUS_LOCKED; + } + else + { + retStatus = CY_IPC_SEMA_STATUS_UNLOCKED; + } + } + else + { + retStatus = CY_IPC_SEMA_OUT_OF_RANGE; + } + return(retStatus); +} + + +/******************************************************************************* +* Function Name: Cy_IPC_Sema_GetMaxSems +****************************************************************************//** +* +* This function returns the number of semaphores in the semaphores subsystem. +* +* \return +* Returns the semaphores quantity. +* +* \funcusage +* \snippet IPC_sut_01.cydsn/main_cm4.c snippet_Cy_IPC_Sema_GetMaxSems +* +*******************************************************************************/ +uint32_t Cy_IPC_Sema_GetMaxSems(void) +{ + cy_stc_ipc_sema_t *semaStruct; + + /* Get pointer to structure */ + semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct); + + return (semaStruct->maxSema); +} + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_sema.h b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_sema.h new file mode 100644 index 0000000000..fb0179c7b4 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/ipc/cy_ipc_sema.h @@ -0,0 +1,114 @@ +/***************************************************************************//** +* \file cy_ipc_sema.h +* \version 1.10.1 +* +* \brief +* Header file for IPC SEM functions +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#ifndef CY_IPC_SEMA_H +#define CY_IPC_SEMA_H + +/******************************************************************************/ +/* Include files */ +/******************************************************************************/ +#include "cy_ipc_drv.h" +#include + +/** +* \addtogroup group_ipc_sema IPC semaphores layer (IPC_SEMA) +* \{ +* The semaphores layer functions made use of a single IPC channel to allow +* multiple semaphores that can be used by system or user function calls. +* By default there are 128 semaphores provided, although the user may modify +* the default value to any number, limited only by SRAM. +* +* \defgroup group_ipc_sema_macros Macros +* Macro definitions are used in the driver +* +* \defgroup group_ipc_sema_functions Functions +* Functions are used in the driver +* +* \defgroup group_ipc_sema_enums Enumerated Types +* Enumerations are used in the driver +* \} +* +* \addtogroup group_ipc_sema_macros +* \{ +*/ + +/** Software PDL driver ID for IPC semaphore functions */ +#define CY_IPC_SEMA_RTN (0x0100ul) +/** Return prefix for IPC semaphore function status codes */ +#define CY_IPC_SEMA_ID_INFO (uint32_t)( CY_IPC_ID_INFO | CY_IPC_SEMA_RTN) +/** Return prefix for IPC semaphore function warning return values */ +#define CY_IPC_SEMA_ID_WARNING (uint32_t)( CY_IPC_ID_WARNING | CY_IPC_SEMA_RTN) +/** Return prefix for IPC semaphore function error return values */ +#define CY_IPC_SEMA_ID_ERROR (uint32_t)( CY_IPC_ID_ERROR | CY_IPC_SEMA_RTN) + +#define CY_IPC_SEMA_PER_WORD (uint32_t)32u /**< 32 semaphores per word */ + +/** \} group_ipc_sema_macros */ + +/** +* \addtogroup group_ipc_sema_enums +* \{ +*/ + +/** Return constants for IPC semaphores functions. */ +typedef enum +{ + /** No error has occurred */ + CY_IPC_SEMA_SUCCESS = (uint32_t)(0ul), + /** Semaphores IPC channel has already been locked */ + CY_IPC_SEMA_ERROR_LOCKED = (uint32_t)(CY_IPC_SEMA_ID_ERROR | 1ul), + /** Semaphores IPC channel is unlocked */ + CY_IPC_SEMA_ERROR_UNLOCKED = (uint32_t)(CY_IPC_SEMA_ID_ERROR | 2ul), + /** Semaphore API bad parameter */ + CY_IPC_SEMA_BAD_PARAM = (uint32_t)(CY_IPC_SEMA_ID_ERROR | 3ul), + /** Semaphore API return when semaphore number is out of the range */ + CY_IPC_SEMA_OUT_OF_RANGE = (uint32_t)(CY_IPC_SEMA_ID_ERROR | 4ul), + + /** Semaphore API return when IPC channel was not acquired */ + CY_IPC_SEMA_NOT_ACQUIRED = (uint32_t)(CY_IPC_SEMA_ID_INFO | 2ul), + /** Semaphore API return status when semaphore channel is busy or locked +* by another process */ + CY_IPC_SEMA_LOCKED = (uint32_t)(CY_IPC_SEMA_ID_INFO | 3ul), + /** Semaphore status return that the semaphore is set */ + CY_IPC_SEMA_STATUS_LOCKED = (uint32_t)(CY_IPC_SEMA_ID_INFO | 1ul), + /** Semaphore status return that the semaphore is cleared */ + CY_IPC_SEMA_STATUS_UNLOCKED = (uint32_t)(CY_IPC_SEMA_ID_INFO | 0ul) +} cy_en_ipcsema_status_t; + +/** \} group_ipc_sema_enums */ + +/** +* \addtogroup group_ipc_sema_functions +* \{ +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +cy_en_ipcsema_status_t Cy_IPC_Sema_Init (uint32_t ipcChannel, uint32_t count, uint32_t memPtr[]); +cy_en_ipcsema_status_t Cy_IPC_Sema_Set (uint32_t semaNumber, bool preemptable); +cy_en_ipcsema_status_t Cy_IPC_Sema_Clear (uint32_t semaNumber, bool preemptable); +cy_en_ipcsema_status_t Cy_IPC_Sema_Status (uint32_t semaNumber); +uint32_t Cy_IPC_Sema_GetMaxSems(void); + +#ifdef __cplusplus +} +#endif + +/** \} group_ipc_sema_functions */ + +#endif /* CY_IPC_SEMA_H */ + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/lpcomp/cy_lpcomp.c b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/lpcomp/cy_lpcomp.c new file mode 100644 index 0000000000..c0d13a8365 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/lpcomp/cy_lpcomp.c @@ -0,0 +1,627 @@ +/******************************************************************************* +* \file cy_lpcomp.c +* \version 1.10.1 +* +* \brief +* This file provides the driver code to the API for the Low Power Comparator +* component. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ +#include "cy_lpcomp.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +static cy_stc_lpcomp_context_t cy_lpcomp_context; + +/******************************************************************************* +* Function Name: Cy_LPComp_Init +****************************************************************************//** +* +* Initializes LPCOMP and returns the LPCOMP register address. +* +* \param *base +* LPCOMP registers structure pointer. +* +* \param *config +* The pointer to the configuration structure for PDL. +* +* \param channel +* The LPCOMP channel index. +* +* \return cy_en_lpcomp_status_t +* *base checking result. If the pointer is NULL, returns error. +* +*******************************************************************************/ +cy_en_lpcomp_status_t Cy_LPComp_Init(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, const cy_stc_lpcomp_config_t* config) +{ + cy_en_lpcomp_status_t ret = CY_LPCOMP_BAD_PARAM; + + CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel)); + CY_ASSERT_L3(CY_LPCOMP_IS_OUT_MODE_VALID(config->outputMode)); + CY_ASSERT_L3(CY_LPCOMP_IS_HYSTERESIS_VALID(config->hysteresis)); + CY_ASSERT_L3(CY_LPCOMP_IS_POWER_VALID(config->power)); + CY_ASSERT_L3(CY_LPCOMP_IS_INTR_MODE_VALID(config->intType)); + + if ((base != NULL) && (config != NULL)) + { + Cy_LPComp_GlobalEnable(base); + + if (CY_LPCOMP_CHANNEL_0 == channel) + { + base->CMP0_CTRL = _VAL2FLD(LPCOMP_CMP0_CTRL_HYST0, (uint32_t)config->hysteresis) | + _VAL2FLD(LPCOMP_CMP0_CTRL_DSI_BYPASS0, (uint32_t)config->outputMode) | + _VAL2FLD(LPCOMP_CMP0_CTRL_DSI_LEVEL0, (uint32_t)config->outputMode >> 1u); + } + else + { + base->CMP1_CTRL = _VAL2FLD(LPCOMP_CMP1_CTRL_HYST1, (uint32_t)config->hysteresis) | + _VAL2FLD(LPCOMP_CMP1_CTRL_DSI_BYPASS1, (uint32_t)config->outputMode) | + _VAL2FLD(LPCOMP_CMP1_CTRL_DSI_LEVEL1, (uint32_t)config->outputMode >> 1u); + } + + /* Save intType to use it in the Cy_LPComp_Enable() function */ + cy_lpcomp_context.intType[(uint8_t)channel - 1u] = config->intType; + + /* Save power to use it in the Cy_LPComp_Enable() function */ + cy_lpcomp_context.power[(uint8_t)channel - 1u] = config->power; + + ret = CY_LPCOMP_SUCCESS; + } + + return (ret); +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_Enable +****************************************************************************//** +* +* Enables the LPCOMP and sets the LPCOMP interrupt mode. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \param channel +* The LPCOMP channel index. +* +* \return None +* +*******************************************************************************/ +void Cy_LPComp_Enable(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel) +{ + cy_en_lpcomp_pwr_t powerSpeed; + + CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel)); + + powerSpeed = cy_lpcomp_context.power[(uint8_t)channel - 1u]; + + /* Set power */ + Cy_LPComp_SetPower(base, channel, powerSpeed); + + /* Make delay before enabling the comparator interrupt to prevent false triggering */ + if (CY_LPCOMP_MODE_ULP == powerSpeed) + { + Cy_SysLib_DelayUs(CY_LPCOMP_ULP_POWER_DELAY); + } + else if (CY_LPCOMP_MODE_LP == powerSpeed) + { + Cy_SysLib_DelayUs(CY_LPCOMP_LP_POWER_DELAY); + } + else + { + Cy_SysLib_DelayUs(CY_LPCOMP_NORMAL_POWER_DELAY); + } + + /* Enable the comparator interrupt */ + Cy_LPComp_SetInterruptTriggerMode(base, channel, cy_lpcomp_context.intType[(uint8_t)channel - 1u]); +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_Disable +****************************************************************************//** +* +* Disables the LPCOMP power and sets the interrupt mode to disabled. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \param channel +* The LPCOMP channel index. +* +* \return None +* +*******************************************************************************/ +void Cy_LPComp_Disable(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel) +{ + CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel)); + + /* Disable the comparator interrupt */ + Cy_LPComp_SetInterruptTriggerMode(base, channel, CY_LPCOMP_INTR_DISABLE); + + /* Set power off */ + Cy_LPComp_SetPower(base, channel, CY_LPCOMP_MODE_OFF); +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_SetInterruptTriggerMode +****************************************************************************//** +* +* Sets the interrupt edge-detect mode. +* This also controls the value provided on the output. +* \note Interrupts can be enabled after the block is enabled and the appropriate +* start-up time has elapsed: +* 3 us for the normal power mode; +* 6 us for the LP mode; +* 50 us for the ULP mode. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \param channel +* The LPCOMP channel index. +* +* \param intType +* Interrupt edge trigger selection +* CY_LPCOMP_INTR_DISABLE (=0) - Disabled, no interrupt will be detected +* CY_LPCOMP_INTR_RISING (=1) - Rising edge +* CY_LPCOMP_INTR_FALLING (=2) - Falling edge +* CY_LPCOMP_INTR_BOTH (=3) - Both rising and falling edges. +* +* \return None +* +*******************************************************************************/ +void Cy_LPComp_SetInterruptTriggerMode(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_int_t intType) +{ + CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel)); + CY_ASSERT_L3(CY_LPCOMP_IS_INTR_MODE_VALID(intType)); + + if (CY_LPCOMP_CHANNEL_0 == channel) + { + base->CMP0_CTRL = _CLR_SET_FLD32U(base->CMP0_CTRL, LPCOMP_CMP0_CTRL_INTTYPE0, (uint32_t)intType); + } + else + { + base->CMP1_CTRL = _CLR_SET_FLD32U(base->CMP1_CTRL, LPCOMP_CMP1_CTRL_INTTYPE1, (uint32_t)intType); + } + + /* Save interrupt type to use it in the Cy_LPComp_Enable() function */ + cy_lpcomp_context.intType[(uint8_t)channel - 1u] = intType; +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_SetPower +****************************************************************************//** +* +* Sets the drive power and speeds to one of the four settings. +* \note Interrupts can be enabled after the block is enabled and the appropriate +* start-up time has elapsed: +* 3 us for the normal power mode; +* 6 us for the LP mode; +* 50 us for the ULP mode. +* Otherwise, unexpected interrupts events can occur. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \param channel +* The LPCOMP channel index. +* +* \param power +* The power setting sets an operation mode of the component: +* CY_LPCOMP_OFF_POWER (=0) - Off power +* CY_LPCOMP_MODE_ULP (=1) - Slow/ultra low power +* CY_LPCOMP_MODE_LP (=2) - Medium/low power +* CY_LPCOMP_MODE_NORMAL(=3) - Fast/normal power +* +* \return None +* +*******************************************************************************/ +void Cy_LPComp_SetPower(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_pwr_t power) +{ + CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel)); + CY_ASSERT_L3(CY_LPCOMP_IS_POWER_VALID(power)); + + if (CY_LPCOMP_CHANNEL_0 == channel) + { + base->CMP0_CTRL = _CLR_SET_FLD32U(base->CMP0_CTRL, LPCOMP_CMP0_CTRL_MODE0, (uint32_t)power); + } + else + { + base->CMP1_CTRL = _CLR_SET_FLD32U(base->CMP1_CTRL, LPCOMP_CMP1_CTRL_MODE1, (uint32_t)power); + } +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_SetHysteresis +****************************************************************************//** +* +* Adds the 30mV hysteresis to the comparator. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \param channel +* The LPCOMP channel index. +* +* \param hysteresis +* Sets an operation mode of the component +* CY_LPCOMP_HYST_ENABLE (=1) - Enables HYST +* CY_LPCOMP_HYST_DISABLE(=0) - Disable HYST. +* +* \return None +* +*******************************************************************************/ +void Cy_LPComp_SetHysteresis(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_hyst_t hysteresis) +{ + CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel)); + CY_ASSERT_L3(CY_LPCOMP_IS_HYSTERESIS_VALID(hysteresis)); + + if (CY_LPCOMP_CHANNEL_0 == channel) + { + base->CMP0_CTRL = _CLR_SET_FLD32U(base->CMP0_CTRL, LPCOMP_CMP0_CTRL_HYST0, (uint32_t)hysteresis); + } + else + { + base->CMP1_CTRL = _CLR_SET_FLD32U(base->CMP1_CTRL , LPCOMP_CMP1_CTRL_HYST1, (uint32_t)hysteresis); + } +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_SetInputs +****************************************************************************//** +* +* Sets the comparator input sources. The comparator inputs can be connected +* to the dedicated GPIO pins or AMUXBUSA/AMUXBUSB. Additionally, the negative +* comparator input can be connected to the local VREF. +* At least one unconnected input causes a comparator undefined output. +* +* \note Connection to AMUXBUSA/AMUXBUSB requires closing the additional +* switches which are a part of the IO system. These switches can be configured +* using the HSIOM->AMUX_SPLIT_CTL[3] register. +* Refer to the appropriate Technical Reference Manual (TRM) of a device +* for a detailed description. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \param channel +* The LPCOMP channel index. +* +* \param inputP +* Positive input selection +* CY_LPCOMP_SW_GPIO (0x01u) +* CY_LPCOMP_SW_AMUXBUSA (0x02u) - Hi-Z in hibernate mode +* CY_LPCOMP_SW_AMUXBUSB (0x04u) - Hi-Z in the hibernate mode. +* +* \param inputN +* Negative input selection +* CY_LPCOMP_SW_GPIO (0x01u) +* CY_LPCOMP_SW_AMUXBUSA (0x02u) - Hi-Z in hibernate mode +* CY_LPCOMP_SW_AMUXBUSB (0x04u) - Hi-Z in hibernate mode +* CY_LPCOMP_SW_LOCAL_VREF (0x08u) - the negative input only for a crude REF. +* +* \return None +* +*******************************************************************************/ +void Cy_LPComp_SetInputs(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_inputs_t inputP, cy_en_lpcomp_inputs_t inputN) +{ + uint32_t input; + + CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel)); + CY_ASSERT_L3(CY_LPCOMP_IS_INPUT_P_VALID(inputP)); + CY_ASSERT_L3(CY_LPCOMP_IS_INPUT_N_VALID(inputN)); + + switch(inputP) + { + case CY_LPCOMP_SW_AMUXBUSA: + { + input = (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_AP0_Msk : LPCOMP_CMP1_SW_CMP1_AP1_Msk; + HSIOM->AMUX_SPLIT_CTL[3] = _CLR_SET_FLD32U(HSIOM->AMUX_SPLIT_CTL[3], CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_SR, 3u); + break; + } + case CY_LPCOMP_SW_AMUXBUSB: + { + input = (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_BP0_Msk : LPCOMP_CMP1_SW_CMP1_BP1_Msk; + HSIOM->AMUX_SPLIT_CTL[3] = _CLR_SET_FLD32U(HSIOM->AMUX_SPLIT_CTL[3], CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_SR, 3u); + break; + } + default: + { + input = (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_IP0_Msk : LPCOMP_CMP1_SW_CMP1_IP1_Msk; + break; + } + } + + switch(inputN) + { + case CY_LPCOMP_SW_AMUXBUSA: + { + input |= (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_AN0_Msk : LPCOMP_CMP1_SW_CMP1_AN1_Msk; + HSIOM->AMUX_SPLIT_CTL[3] = _CLR_SET_FLD32U(HSIOM->AMUX_SPLIT_CTL[3], CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_SR, 3u); + break; + } + case CY_LPCOMP_SW_AMUXBUSB: + { + input |= (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_BN0_Msk : LPCOMP_CMP1_SW_CMP1_BN1_Msk; + HSIOM->AMUX_SPLIT_CTL[3] = _CLR_SET_FLD32U(HSIOM->AMUX_SPLIT_CTL[3], CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_SR, 3u); + break; + } + case CY_LPCOMP_SW_LOCAL_VREF: + { + input |= (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_VN0_Msk : LPCOMP_CMP1_SW_CMP1_VN1_Msk; + break; + } + default: + { + input |= (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_IN0_Msk : LPCOMP_CMP1_SW_CMP1_IN1_Msk; + break; + } + } + + if (CY_LPCOMP_CHANNEL_0 == channel) + { + base->CMP0_SW_CLEAR = CY_LPCOMP_CMP0_SW_POS_Msk | CY_LPCOMP_CMP0_SW_NEG_Msk; + base->CMP0_SW = input; + } + else + { + base->CMP1_SW_CLEAR = CY_LPCOMP_CMP1_SW_POS_Msk | CY_LPCOMP_CMP1_SW_NEG_Msk; + base->CMP1_SW = input; + } +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_SetOutputMode +****************************************************************************//** +* +* Sets the type of the comparator DSI output. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \param channel +* The LPCOMP channel index. +* +* \param outType +* Interrupt edge trigger selection +* CY_LPCOMP_OUT_PULSE (=0) - the DSI output with the pulse option, no bypass +* CY_LPCOMP_OUT_DIRECT (=1) - the bypass mode, the direct output of the comparator +* CY_LPCOMP_OUT_SYNC (=2) - DSI output with the level option, it is similar to the +* bypass mode but it is 1 cycle slow than the bypass. +* [DSI_LEVELx : DSI_BYPASSx] = [Bit11 : Bit10] +* 0 : 0 = 0x00 -> Pulse (PULSE) +* 1 : 0 = 0x02 -> Level (SYNC) +* x : 1 = 0x01 -> Bypass (Direct). +* +* \return None +* +*******************************************************************************/ +void Cy_LPComp_SetOutputMode(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_out_t outType) +{ + CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel)); + CY_ASSERT_L3(CY_LPCOMP_IS_OUT_MODE_VALID(outType)); + + if (CY_LPCOMP_CHANNEL_0 == channel) + { + base->CMP0_CTRL = _CLR_SET_FLD32U(base->CMP0_CTRL, CY_LPCOMP_CMP0_OUTPUT_CONFIG, (uint32_t)outType); + } + else + { + base->CMP1_CTRL = _CLR_SET_FLD32U(base->CMP1_CTRL, CY_LPCOMP_CMP1_OUTPUT_CONFIG, (uint32_t)outType); + } +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_DeepSleepCallback +****************************************************************************//** +* +* This function checks the current power mode of LPComp and then disables the +* LPComp block if there is no wake-up source from LPComp in the deep-sleep mode. +* It stores the state of the LPComp enable and then disables the LPComp block +* before going to the low power modes, and recovers the LPComp power state after +* wake-up using the stored value. +* +* \param *callbackParams +* The \ref cy_stc_syspm_callback_params_t structure with the callback +* parameters which consists of mode, base and context fields: +* *base - LPComp register structure pointer; +* *context - Context for the call-back function; +* mode +* CY_SYSPM_CHECK_READY - No action for this state. +* CY_SYSPM_CHECK_FAIL - No action for this state. +* CY_SYSPM_BEFORE_TRANSITION - Checks the LPComp interrupt mask and the power +* mode, and then disables or enables the LPComp block +* according to the condition. +* Stores the LPComp state to recover the state after +* wake up. +* CY_SYSPM_AFTER_TRANSITION - Enables the LPComp block, if it was disabled +* before the sleep mode. +* +* \return +* \ref cy_en_syspm_status_t +* +*******************************************************************************/ +cy_en_syspm_status_t Cy_LPComp_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams) +{ + cy_en_syspm_status_t ret = CY_SYSPM_FAIL; + LPCOMP_Type *locBase = (LPCOMP_Type *) (callbackParams->base); + static uint32_t enabled_status; + + switch(callbackParams->mode) + { + case CY_SYSPM_CHECK_READY: + { + ret = CY_SYSPM_SUCCESS; + } + break; + + case CY_SYSPM_CHECK_FAIL: + { + ret = CY_SYSPM_SUCCESS; + } + break; + + case CY_SYSPM_BEFORE_TRANSITION: + { + /* Save the LPComp the enabled/disabled status. */ + enabled_status = _FLD2VAL(LPCOMP_CONFIG_ENABLED, locBase->CONFIG); + + if (0u != enabled_status) + { + /* Disable the LPComp block when there is no wake-up source from any channel. */ + if( !(((_FLD2VAL(LPCOMP_CMP0_CTRL_MODE0, locBase->CMP0_CTRL) == (uint32_t)CY_LPCOMP_MODE_ULP) && + _FLD2BOOL(LPCOMP_INTR_MASK_COMP0_MASK, locBase->INTR_MASK)) || + ((_FLD2VAL(LPCOMP_CMP1_CTRL_MODE1, locBase->CMP1_CTRL) == (uint32_t)CY_LPCOMP_MODE_ULP) && + _FLD2BOOL(LPCOMP_INTR_MASK_COMP1_MASK, locBase->INTR_MASK))) ) + + { + /* Disable the LPComp block to avoid leakage. */ + Cy_LPComp_GlobalDisable(locBase); + } + else + { + /* Set LPComp the status to the not changed state. */ + enabled_status = 0u; + } + } + else + { + /* The LPComp block was already disabled and + * the system is allowed to go to the low power mode. + */ + } + + ret = CY_SYSPM_SUCCESS; + } + break; + + case CY_SYSPM_AFTER_TRANSITION: + { + /* Enable LPComp to operate if it was enabled + * before entering to the low power mode. + */ + if (0u != enabled_status) + { + Cy_LPComp_GlobalEnable(locBase); + } + else + { + /* The LPComp block was disabled before calling this API + * with mode = CY_SYSPM_CHECK_READY. + */ + } + + ret = CY_SYSPM_SUCCESS; + } + break; + + default: + break; + } + + return (ret); +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_HibernateCallback +****************************************************************************//** +* +* This function checks the current power mode of LPComp and then disable the +* LPComp block, if there is no wake-up source from LPComp in the hibernate mode. +* +* \param *callbackParams +* The \ref cy_stc_syspm_callback_params_t structure with the callback +* parameters which consists of mode, base and context fields: +* *base - LPComp register structure pointer; +* *context - Context for the call-back function; +* mode +* CY_SYSPM_CHECK_READY - No action for this state. +* CY_SYSPM_CHECK_FAIL - No action for this state. +* CY_SYSPM_BEFORE_TRANSITION - Checks the wake-up source from the hibernate mode +* of the LPComp block, and then disables or enables +* the LPComp block according to the condition. +* +* \return +* \ref cy_en_syspm_status_t +* +*******************************************************************************/ +cy_en_syspm_status_t Cy_LPComp_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams) +{ + cy_en_syspm_status_t ret = CY_SYSPM_FAIL; + LPCOMP_Type *locBase = (LPCOMP_Type *) (callbackParams->base); + static uint32_t enabled_status; + + switch(callbackParams->mode) + { + case CY_SYSPM_CHECK_READY: + { + ret = CY_SYSPM_SUCCESS; + } + break; + + case CY_SYSPM_CHECK_FAIL: + { + ret = CY_SYSPM_SUCCESS; + } + break; + + case CY_SYSPM_BEFORE_TRANSITION: + { + /* Save the LPComp the enabled/disabled status. */ + enabled_status = _FLD2VAL(LPCOMP_CONFIG_ENABLED, locBase->CONFIG); + + if (0u != enabled_status) + { + /* Disable the LPComp block when there is no wake-up source from any channel. */ + if( !(((_FLD2VAL(LPCOMP_CMP0_CTRL_MODE0, locBase->CMP0_CTRL) == (uint32_t)CY_LPCOMP_MODE_ULP) && + _FLD2BOOL(CY_LPCOMP_WAKEUP_PIN0, SRSS->PWR_HIBERNATE)) || + ((_FLD2VAL(LPCOMP_CMP1_CTRL_MODE1, locBase->CMP1_CTRL) == (uint32_t)CY_LPCOMP_MODE_ULP) && + _FLD2BOOL(CY_LPCOMP_WAKEUP_PIN1, SRSS->PWR_HIBERNATE))) ) + + { + /* Disable the LPComp block to avoid leakage. */ + Cy_LPComp_GlobalDisable(locBase); + } + else + { + /* Set LPComp the status to the not changed state. */ + enabled_status = 0u; + } + } + else + { + /* The LPComp block was already disabled and + * the system is allowed to go to the low power mode. + */ + } + + ret = CY_SYSPM_SUCCESS; + } + break; + + default: + break; + } + + return (ret); +} + +#if defined(__cplusplus) +} +#endif + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/lpcomp/cy_lpcomp.h b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/lpcomp/cy_lpcomp.h new file mode 100644 index 0000000000..1e57e7da0e --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/lpcomp/cy_lpcomp.h @@ -0,0 +1,717 @@ +/***************************************************************************//** +* \file cy_lpcomp.h +* \version 1.10.1 +* +* This file provides constants and parameter values for the Low Power Comparator driver. +* +******************************************************************************** +* \copyright +* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +/** +* \defgroup group_lpcomp Low Power Comparator (LPComp) +* \{ +* Provides access to the low-power comparators implemented using the fixed-function +* LP comparator block that is present in PSoC 6. +* +* These comparators can perform fast analog signal comparison of internal +* and external analog signals in all system power modes. Low-power comparator +* output can be inspected by the CPU, used as an interrupt/wakeup source to the +* CPU when in low-power mode (Sleep, Low-Power Sleep, or Deep-Sleep), used as +* a wakeup source to system resources when in Hibernate mode, or fed to DSI as +* an asynchronous or synchronous signal (level or pulse). +* +* \section group_lpcomp_section_Configuration_Considerations Configuration Considerations +* To set up an LPComp, the inputs, the output, the mode, the interrupts and +* other configuration parameters should be configured. Power the LPComp to operate. +* +* The sequence recommended for the LPComp operation: +* +* 1) To initialize the driver, call the Cy_LPComp_Init() function providing +* the filled cy_stc_lpcomp_config_t structure, the LPComp channel number, +* and the LPCOMP registers structure pointer. +* +* 2) Optionally, configure the interrupt requests if the interrupt event +* triggering is needed. Use the Cy_LPComp_SetInterruptMask() function with +* the parameter for the mask available in the configuration file. +* Additionally, enable the Global interrupts and initialize the referenced +* interrupt by setting the priority and the interrupt vector using +* the \ref Cy_SysInt_Init() function of the sysint driver. +* +* 3) Configure the inputs and the output using the \ref Cy_GPIO_Pin_Init() +* functions of the GPIO driver. +* The High Impedance Analog drive mode is for the inputs and +* the Strong drive mode is for the output. +* Use the Cy_LPComp_SetInputs() function to connect the comparator inputs +* to the dedicated IO pins, AMUXBUSA/AMUXBUSB or Vref: +* \image html lpcomp_inputs.png +* +* 4) Power on the comparator using the Cy_LPComp_Enable() function. +* +* 5) The comparator output can be monitored using +* the Cy_LPComp_GetCompare() function or using the LPComp interrupt +* (if the interrupt is enabled). +* +* \note The interrupt is not cleared automatically. +* It is the user's responsibility to do that. +* The interrupt is cleared by writing a 1 in the corresponding interrupt +* register bit position. The preferred way to clear interrupt sources +* is using the Cy_LPComp_ClearInterrupt() function. +* +* \note Individual comparator interrupt outputs are ORed together +* as a single asynchronous interrupt source before it is sent out and +* used to wake up the system in the low-power mode. +* For PSoC 6 devices, the individual comparator interrupt is masked +* by the INTR_MASK register. The masked result is captured in +* the INTR_MASKED register. +* Writing a 1 to the INTR register bit will clear the interrupt. +* +* \section group_lpcomp_lp Low Power Support +* The LPComp provides the callback functions to facilitate +* the low-power mode transition. The callback +* \ref Cy_LPComp_DeepSleepCallback must be called during execution +* of \ref Cy_SysPm_DeepSleep; \ref Cy_LPComp_HibernateCallback must be +* called during execution of \ref Cy_SysPm_Hibernate. +* To trigger the callback execution, the callback must be registered +* before calling the mode transition function. +* Refer to \ref group_syspm driver for more +* information about low-power mode transitions. +* +* \section group_lpcomp_more_information More Information +* +* Refer to the appropriate device technical reference manual (TRM) for +* a detailed description of the registers. +* +* \section group_lpcomp_MISRA MISRA-C Compliance +* +* +* +* +* +* +* +* +* +* +* +* +* +*
MISRA RuleRule Class (Required/Advisory)Rule DescriptionDescription of Deviation(s)
11.4AA cast should not be performed between a pointer to object type and +* a different pointer to object type. +* The pointer to the buffer memory is void to allow handling different +* different data types: uint8_t (4-8 bits) or uint16_t (9-16 bits). +* The cast operation is safe because the configuration is verified +* before operation is performed. +* The function \ref Cy_LPComp_DeepSleepCallback is a callback of +* the \ref cy_en_syspm_status_t type. The cast operation safety in this +* function becomes the user's responsibility because the pointers are +* initialized when a callback is registered in the SysPm driver.
+* +* \section group_lpcomp_Changelog Changelog +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
VersionChangesReason for Change
1.10.1Added Low Power Callback sectionDocumentation update and clarification
1.10The CY_WEAK keyword is removed from Cy_LPComp_DeepSleepCallback() +* and Cy_LPComp_HibernateCallback() functions
+* Added input parameter validation to the API functions.
1.0Initial version
+* +* \defgroup group_lpcomp_macros Macros +* \defgroup group_lpcomp_functions Functions +* \{ +* \defgroup group_lpcomp_functions_syspm_callback Low Power Callback +* \} +* \defgroup group_lpcomp_data_structures Data Structures +* \defgroup group_lpcomp_enums Enumerated Types +*/ + +#ifndef CY_LPCOMP_PDL_H +#define CY_LPCOMP_PDL_H + +/******************************************************************************/ +/* Include files */ +/******************************************************************************/ + +#include +#include +#include "cy_device_headers.h" +#include "syslib/cy_syslib.h" +#include "syspm/cy_syspm.h" + +#ifndef CY_IP_MXLPCOMP + #error "The LPCOMP driver is not supported on this device" +#endif + +/* C binding of definitions if building with C++ compiler */ +#ifdef __cplusplus +extern "C" +{ +#endif + +/** +* \addtogroup group_lpcomp_macros +* \{ +*/ + +/** Driver major version */ +#define CY_LPCOMP_DRV_VERSION_MAJOR 1 + +/** Driver minor version */ +#define CY_LPCOMP_DRV_VERSION_MINOR 10 + +/****************************************************************************** +* API Constants +******************************************************************************/ + +/**< LPCOMP PDL ID */ +#define CY_LPCOMP_ID CY_PDL_DRV_ID(0x23u) + +/** The LPCOMP's number of channels. */ +#define CY_LPCOMP_MAX_CHANNEL_NUM (2u) + +/** LPCOMP's comparator 1 interrupt mask. */ +#define CY_LPCOMP_COMP0 (0x01u) +/** LPCOMP's comparator 2 interrupt mask. */ +#define CY_LPCOMP_COMP1 (0x02u) + +/** \cond INTERNAL_MACROS */ + + +/****************************************************************************** +* Registers Constants +******************************************************************************/ + +#define CY_LPCOMP_MODE_ULP_Pos (0x0uL) +#define CY_LPCOMP_MODE_ULP_Msk (0x1uL) + +#define CY_LPCOMP_INTR_Pos (LPCOMP_INTR_COMP0_Pos) +#define CY_LPCOMP_INTR_Msk (LPCOMP_INTR_COMP0_Msk | LPCOMP_INTR_COMP1_Msk) + +#define CY_LPCOMP_CMP0_SW_POS_Msk (LPCOMP_CMP0_SW_CMP0_IP0_Msk | \ + LPCOMP_CMP0_SW_CMP0_AP0_Msk | \ + LPCOMP_CMP0_SW_CMP0_BP0_Msk) +#define CY_LPCOMP_CMP0_SW_NEG_Msk (LPCOMP_CMP0_SW_CMP0_IN0_Msk | \ + LPCOMP_CMP0_SW_CMP0_AN0_Msk | \ + LPCOMP_CMP0_SW_CMP0_BN0_Msk | \ + LPCOMP_CMP0_SW_CMP0_VN0_Msk) +#define CY_LPCOMP_CMP1_SW_POS_Msk (LPCOMP_CMP1_SW_CMP1_IP1_Msk | \ + LPCOMP_CMP1_SW_CMP1_AP1_Msk | \ + LPCOMP_CMP1_SW_CMP1_BP1_Msk) +#define CY_LPCOMP_CMP1_SW_NEG_Msk (LPCOMP_CMP1_SW_CMP1_IN1_Msk | \ + LPCOMP_CMP1_SW_CMP1_AN1_Msk | \ + LPCOMP_CMP1_SW_CMP1_BN1_Msk | \ + LPCOMP_CMP1_SW_CMP1_VN1_Msk) + +#define CY_LPCOMP_CMP0_OUTPUT_CONFIG_Pos LPCOMP_CMP0_CTRL_DSI_BYPASS0_Pos +#define CY_LPCOMP_CMP1_OUTPUT_CONFIG_Pos LPCOMP_CMP1_CTRL_DSI_BYPASS1_Pos + +#define CY_LPCOMP_CMP0_OUTPUT_CONFIG_Msk (LPCOMP_CMP0_CTRL_DSI_BYPASS0_Msk | \ + LPCOMP_CMP0_CTRL_DSI_LEVEL0_Msk) + +#define CY_LPCOMP_CMP1_OUTPUT_CONFIG_Msk (LPCOMP_CMP1_CTRL_DSI_BYPASS1_Msk | \ + LPCOMP_CMP1_CTRL_DSI_LEVEL1_Msk) + +#define CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_SR_Pos HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_Pos + +#define CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_SR_Msk (HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_Msk | \ + HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SR_Msk) + +#define CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_SR_Pos HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_Pos + +#define CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_SR_Msk (HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_Msk | \ + HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SR_Msk) + +#define CY_LPCOMP_REF_CONNECTED (1u) + +#define CY_LPCOMP_WAKEUP_PIN0_Msk CY_SYSPM_WAKEUP_LPCOMP0 +#define CY_LPCOMP_WAKEUP_PIN1_Msk CY_SYSPM_WAKEUP_LPCOMP1 + +/* Internal constants for Cy_LPComp_Enable() */ +#define CY_LPCOMP_NORMAL_POWER_DELAY (3u) +#define CY_LPCOMP_LP_POWER_DELAY (6u) +#define CY_LPCOMP_ULP_POWER_DELAY (50u) + +/** \endcond */ +/** \} group_lpcomp_macros */ + +/** +* \addtogroup group_lpcomp_enums +* \{ +*/ + +/****************************************************************************** + * Enumerations + *****************************************************************************/ +/** The LPCOMP output modes. */ +typedef enum +{ + CY_LPCOMP_OUT_PULSE = 0u, /**< The LPCOMP DSI output with the pulse option, no bypass. */ + CY_LPCOMP_OUT_DIRECT = 1u, /**< The LPCOMP bypass mode, the direct output of a comparator. */ + CY_LPCOMP_OUT_SYNC = 2u /**< The LPCOMP DSI output with the level option, it is similar + to the bypass mode but it is 1 cycle slow than the bypass. */ +} cy_en_lpcomp_out_t; + +/** The LPCOMP hysteresis modes. */ +typedef enum +{ + CY_LPCOMP_HYST_ENABLE = 1u, /**< The LPCOMP enable hysteresis. */ + CY_LPCOMP_HYST_DISABLE = 0u /**< The LPCOMP disable hysteresis. */ +} cy_en_lpcomp_hyst_t; + +/** The LPCOMP's channel number. */ +typedef enum +{ + CY_LPCOMP_CHANNEL_0 = 0x1u, /**< The LPCOMP Comparator 0. */ + CY_LPCOMP_CHANNEL_1 = 0x2u /**< The LPCOMP Comparator 1. */ +} cy_en_lpcomp_channel_t; + +/** The LPCOMP interrupt modes. */ +typedef enum +{ + CY_LPCOMP_INTR_DISABLE = 0u, /**< The LPCOMP interrupt disabled, no interrupt will be detected. */ + CY_LPCOMP_INTR_RISING = 1u, /**< The LPCOMP interrupt on the rising edge. */ + CY_LPCOMP_INTR_FALLING = 2u, /**< The LPCOMP interrupt on the falling edge. */ + CY_LPCOMP_INTR_BOTH = 3u /**< The LPCOMP interrupt on both rising and falling edges. */ +} cy_en_lpcomp_int_t; + +/** The LPCOMP power-mode selection. */ +typedef enum +{ + CY_LPCOMP_MODE_OFF = 0u, /**< The LPCOMP's channel power-off. */ + CY_LPCOMP_MODE_ULP = 1u, /**< The LPCOMP's channel ULP mode. */ + CY_LPCOMP_MODE_LP = 2u, /**< The LPCOMP's channel LP mode. */ + CY_LPCOMP_MODE_NORMAL = 3u /**< The LPCOMP's channel normal mode. */ +} cy_en_lpcomp_pwr_t; + +/** The LPCOMP inputs. */ +typedef enum +{ + CY_LPCOMP_SW_GPIO = 0x01u, /**< The LPCOMP input connects to GPIO pin. */ + CY_LPCOMP_SW_AMUXBUSA = 0x02u, /**< The LPCOMP input connects to AMUXBUSA. */ + CY_LPCOMP_SW_AMUXBUSB = 0x04u, /**< The LPCOMP input connects to AMUXBUSB. */ + CY_LPCOMP_SW_LOCAL_VREF = 0x08u /**< The LPCOMP input connects to local VREF. */ +} cy_en_lpcomp_inputs_t; + +/** The LPCOMP error codes. */ +typedef enum +{ + CY_LPCOMP_SUCCESS = 0x00u, /**< Successful */ + CY_LPCOMP_BAD_PARAM = CY_LPCOMP_ID | CY_PDL_STATUS_ERROR | 0x01u, /**< One or more invalid parameters */ + CY_LPCOMP_TIMEOUT = CY_LPCOMP_ID | CY_PDL_STATUS_ERROR | 0x02u, /**< Operation timed out */ + CY_LPCOMP_INVALID_STATE = CY_LPCOMP_ID | CY_PDL_STATUS_ERROR | 0x03u, /**< Operation not setup or is in an improper state */ + CY_LPCOMP_UNKNOWN = CY_LPCOMP_ID | CY_PDL_STATUS_ERROR | 0xFFu, /**< Unknown failure */ +} cy_en_lpcomp_status_t; + +/** \} group_lpcomp_enums */ + +/** +* \addtogroup group_lpcomp_data_structures +* \{ +*/ + +/****************************************************************************** + * Structures + *****************************************************************************/ + +/** The LPCOMP configuration structure. */ +typedef struct { + cy_en_lpcomp_out_t outputMode; /**< The LPCOMP's outputMode: Direct output, + Synchronized output or Pulse output */ + cy_en_lpcomp_hyst_t hysteresis; /**< Enables or disables the LPCOMP's hysteresis */ + cy_en_lpcomp_pwr_t power; /**< Sets the LPCOMP power mode */ + cy_en_lpcomp_int_t intType; /**< Sets the LPCOMP interrupt mode */ +} cy_stc_lpcomp_config_t; + +/** \cond CONTEXT_STRUCTURE */ + +typedef struct { + cy_en_lpcomp_int_t intType[CY_LPCOMP_MAX_CHANNEL_NUM]; + cy_en_lpcomp_pwr_t power[CY_LPCOMP_MAX_CHANNEL_NUM]; +} cy_stc_lpcomp_context_t; + +/** \endcond */ + +/** \} group_lpcomp_data_structures */ + +/** \cond INTERNAL_MACROS */ + +/****************************************************************************** + * Macros + *****************************************************************************/ +#define CY_LPCOMP_IS_CHANNEL_VALID(channel) (((channel) == CY_LPCOMP_CHANNEL_0) || \ + ((channel) == CY_LPCOMP_CHANNEL_1)) +#define CY_LPCOMP_IS_OUT_MODE_VALID(mode) (((mode) == CY_LPCOMP_OUT_PULSE) || \ + ((mode) == CY_LPCOMP_OUT_DIRECT) || \ + ((mode) == CY_LPCOMP_OUT_SYNC)) +#define CY_LPCOMP_IS_HYSTERESIS_VALID(hyst) (((hyst) == CY_LPCOMP_HYST_ENABLE) || \ + ((hyst) == CY_LPCOMP_HYST_DISABLE)) +#define CY_LPCOMP_IS_INTR_MODE_VALID(intr) (((intr) == CY_LPCOMP_INTR_DISABLE) || \ + ((intr) == CY_LPCOMP_INTR_RISING) || \ + ((intr) == CY_LPCOMP_INTR_FALLING) || \ + ((intr) == CY_LPCOMP_INTR_BOTH)) +#define CY_LPCOMP_IS_POWER_VALID(power) (((power) == CY_LPCOMP_MODE_OFF) || \ + ((power) == CY_LPCOMP_MODE_ULP) || \ + ((power) == CY_LPCOMP_MODE_LP) || \ + ((power) == CY_LPCOMP_MODE_NORMAL)) +#define CY_LPCOMP_IS_INTR_VALID(intr) (((intr) == CY_LPCOMP_COMP0) || \ + ((intr) == CY_LPCOMP_COMP1) || \ + ((intr) == (CY_LPCOMP_COMP0 | CY_LPCOMP_COMP1))) +#define CY_LPCOMP_IS_INPUT_P_VALID(input) (((input) == CY_LPCOMP_SW_GPIO) || \ + ((input) == CY_LPCOMP_SW_AMUXBUSA) || \ + ((input) == CY_LPCOMP_SW_AMUXBUSB)) +#define CY_LPCOMP_IS_INPUT_N_VALID(input) (((input) == CY_LPCOMP_SW_GPIO) || \ + ((input) == CY_LPCOMP_SW_AMUXBUSA) || \ + ((input) == CY_LPCOMP_SW_AMUXBUSB) || \ + ((input) == CY_LPCOMP_SW_LOCAL_VREF)) + +/** \endcond */ + +/** +* \addtogroup group_lpcomp_functions +* \{ +*/ + +/****************************************************************************** +* Functions +*******************************************************************************/ + +cy_en_lpcomp_status_t Cy_LPComp_Init(LPCOMP_Type *base, cy_en_lpcomp_channel_t channel, const cy_stc_lpcomp_config_t *config); +void Cy_LPComp_Enable(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel); +void Cy_LPComp_Disable(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel); +__STATIC_INLINE void Cy_LPComp_GlobalEnable(LPCOMP_Type *base); +__STATIC_INLINE void Cy_LPComp_GlobalDisable(LPCOMP_Type *base); +__STATIC_INLINE void Cy_LPComp_UlpReferenceEnable(LPCOMP_Type *base); +__STATIC_INLINE void Cy_LPComp_UlpReferenceDisable(LPCOMP_Type *base); +__STATIC_INLINE uint32_t Cy_LPComp_GetCompare(LPCOMP_Type const * base, cy_en_lpcomp_channel_t channel); +void Cy_LPComp_SetPower(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_pwr_t power); +void Cy_LPComp_SetHysteresis(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_hyst_t hysteresis); +void Cy_LPComp_SetInputs(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_inputs_t inputP, cy_en_lpcomp_inputs_t inputN); +void Cy_LPComp_SetOutputMode(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_out_t outType); +void Cy_LPComp_SetInterruptTriggerMode(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_int_t intType); +__STATIC_INLINE uint32_t Cy_LPComp_GetInterruptStatus(LPCOMP_Type const * base); +__STATIC_INLINE void Cy_LPComp_ClearInterrupt(LPCOMP_Type* base, uint32_t interrupt); +__STATIC_INLINE void Cy_LPComp_SetInterrupt(LPCOMP_Type* base, uint32_t interrupt); +__STATIC_INLINE uint32_t Cy_LPComp_GetInterruptMask(LPCOMP_Type const * base); +__STATIC_INLINE void Cy_LPComp_SetInterruptMask(LPCOMP_Type* base, uint32_t interrupt); +__STATIC_INLINE uint32_t Cy_LPComp_GetInterruptStatusMasked(LPCOMP_Type const * base); +__STATIC_INLINE void Cy_LPComp_ConnectULPReference(LPCOMP_Type *base, cy_en_lpcomp_channel_t channel); +/** \addtogroup group_lpcomp_functions_syspm_callback +* The driver supports SysPm callback for Deep Sleep and Hibernate transition. +* \{ +*/ +cy_en_syspm_status_t Cy_LPComp_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams); +cy_en_syspm_status_t Cy_LPComp_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams); +/** \} */ + + +/******************************************************************************* +* Function Name: Cy_LPComp_GlobalEnable +****************************************************************************//** +* +* Activates the IP of the LPCOMP hardware block. This API should be enabled +* before operating any channel of comparators. +* Note: Interrupts can be enabled after the block is enabled and the appropriate +* start-up time has elapsed: +* 3 us for the normal power mode; +* 6 us for the LP mode; +* 50 us for the ULP mode. +* +* \param *base +* The structure of the channel pointer. +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_LPComp_GlobalEnable(LPCOMP_Type* base) +{ + base->CONFIG |= LPCOMP_CONFIG_ENABLED_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_GlobalDisable +****************************************************************************//** +* +* Deactivates the IP of the LPCOMP hardware block. +* (Analog in power down, open all switches, all clocks off). +* +* \param *base +* The structure of the channel pointer. +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_LPComp_GlobalDisable(LPCOMP_Type *base) +{ + base->CONFIG &= (uint32_t) ~LPCOMP_CONFIG_ENABLED_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_UlpReferenceEnable +****************************************************************************//** +* +* Enables the local reference-generator circuit. +* +* \param *base +* The structure of the channel pointer. +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_LPComp_UlpReferenceEnable(LPCOMP_Type *base) +{ + base->CONFIG |= LPCOMP_CONFIG_LPREF_EN_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_UlpReferenceDisable +****************************************************************************//** +* +* Disables the local reference-generator circuit. +* +* \param *base +* The structure of the channel pointer. +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_LPComp_UlpReferenceDisable(LPCOMP_Type *base) +{ + base->CONFIG &= (uint32_t) ~LPCOMP_CONFIG_LPREF_EN_Msk; +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_GetCompare +****************************************************************************//** +* +* This function returns a nonzero value when the voltage connected to the +* positive input is greater than the negative input voltage. +* +* \param *base +* The LPComp register structure pointer. +* +* \param channel +* The LPComp channel index. +* +* \return LPComp compare result. +* The value is a nonzero value when the voltage connected to the positive +* input is greater than the negative input voltage. +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_LPComp_GetCompare(LPCOMP_Type const * base, cy_en_lpcomp_channel_t channel) +{ + uint32_t result; + + CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel)); + + if (CY_LPCOMP_CHANNEL_0 == channel) + { + result = _FLD2VAL(LPCOMP_STATUS_OUT0, base->STATUS); + } + else + { + result = _FLD2VAL(LPCOMP_STATUS_OUT1, base->STATUS); + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_SetInterruptMask +****************************************************************************//** +* +* Configures which bits of the interrupt request register will trigger an +* interrupt event. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \param interrupt +* uint32_t interruptMask: Bit Mask of interrupts to set. +* Bit 0: COMP0 Interrupt Mask +* Bit 1: COMP1 Interrupt Mask +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_LPComp_SetInterruptMask(LPCOMP_Type* base, uint32_t interrupt) +{ + CY_ASSERT_L2(CY_LPCOMP_IS_INTR_VALID(interrupt)); + + base->INTR_MASK |= interrupt; +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_GetInterruptMask +****************************************************************************//** +* +* Returns an interrupt mask. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \return bit mapping information +* Bit 0: COMP0 Interrupt Mask +* Bit 1: COMP1 Interrupt Mask +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_LPComp_GetInterruptMask(LPCOMP_Type const * base) +{ + return (base->INTR_MASK); +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_GetInterruptStatusMasked +****************************************************************************//** +* +* Returns an interrupt request register masked by an interrupt mask. +* Returns the result of the bitwise AND operation between the corresponding +* interrupt request and mask bits. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \return bit mapping information +* Bit 0: COMP0 Interrupt Masked +* Bit 1: COMP1 Interrupt Masked +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_LPComp_GetInterruptStatusMasked(LPCOMP_Type const * base) +{ + return (base->INTR_MASKED); +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_GetInterruptStatus +****************************************************************************//** +* +* Returns the status of 2 different LPCOMP interrupt requests. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \return bit mapping information +* Bit 0: COMP0 Interrupt status +* Bit 1: COMP1 Interrupt status +* +*******************************************************************************/ +__STATIC_INLINE uint32_t Cy_LPComp_GetInterruptStatus(LPCOMP_Type const * base) +{ + return (_FLD2VAL(CY_LPCOMP_INTR, base->INTR)); +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_ClearInterrupt +****************************************************************************//** +* +* Clears LPCOMP interrupts by setting each bit. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \param interrupt +* Bit 0: COMP0 Interrupt status +* Bit 1: COMP1 Interrupt status +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_LPComp_ClearInterrupt(LPCOMP_Type* base, uint32_t interrupt) +{ + CY_ASSERT_L2(CY_LPCOMP_IS_INTR_VALID(interrupt)); + base->INTR |= interrupt; + (void) LPCOMP->INTR; +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_SetInterrupt +****************************************************************************//** +* +* Sets a software interrupt request. +* This function is used in the case of combined interrupt signal from the global +* signal reference. This function from either component instance can be used +* to trigger either or both software interrupts. It sets the INTR_SET interrupt mask. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \param interrupt +* Bit 0: COMP0 Interrupt status +* Bit 1: COMP1 Interrupt status +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_LPComp_SetInterrupt(LPCOMP_Type* base, uint32_t interrupt) +{ + CY_ASSERT_L2(CY_LPCOMP_IS_INTR_VALID(interrupt)); + base->INTR_SET = interrupt; +} + + +/******************************************************************************* +* Function Name: Cy_LPComp_ConnectULPReference +****************************************************************************//** +* +* Connects the local reference generator output to the comparator negative input. +* +* \param *base +* The LPCOMP register structure pointer. +* +* \param channel +* The LPCOMP channel index. +* +* \return None +* +*******************************************************************************/ +__STATIC_INLINE void Cy_LPComp_ConnectULPReference(LPCOMP_Type *base, cy_en_lpcomp_channel_t channel) +{ + CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel)); + + if (CY_LPCOMP_CHANNEL_0 == channel) + { + base->CMP0_SW_CLEAR = CY_LPCOMP_CMP0_SW_NEG_Msk; + base->CMP0_SW = _CLR_SET_FLD32U(base->CMP0_SW, LPCOMP_CMP0_SW_CMP0_VN0, CY_LPCOMP_REF_CONNECTED); + } + else + { + base->CMP1_SW_CLEAR = CY_LPCOMP_CMP1_SW_NEG_Msk; + base->CMP1_SW = _CLR_SET_FLD32U(base->CMP1_SW, LPCOMP_CMP1_SW_CMP1_VN1, CY_LPCOMP_REF_CONNECTED); + } +} + +/** \} group_lpcomp_functions */ + +#ifdef __cplusplus +} +#endif + +#endif /* CY_LPCOMP_PDL_H */ + +/** \} group_lpcomp */ + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/lvd/cy_lvd.c b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/lvd/cy_lvd.c new file mode 100644 index 0000000000..3f49ae3d6e --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/lvd/cy_lvd.c @@ -0,0 +1,62 @@ +/***************************************************************************//** +* \file cy_lvd.c +* \version 1.0.1 +* +* The source code file for the LVD driver. +* +******************************************************************************** +* \copyright +* Copyright 2017-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +#include "cy_lvd.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/******************************************************************************* +* Function Name: Cy_LVD_DeepSleepCallback +****************************************************************************//** +* +* When this function is registered by \ref Cy_SysPm_RegisterCallback - it +* automatically enables the LVD after wake up from Deep-Sleep mode. +* +* \param callbackParams The pointer to the callback parameters structure, +* see \ref cy_stc_syspm_callback_params_t. +* +* \return the SysPm callback status \ref cy_en_syspm_status_t. +* +*******************************************************************************/ +cy_en_syspm_status_t Cy_LVD_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams) +{ + cy_en_syspm_status_t ret = CY_SYSPM_SUCCESS; + + switch(callbackParams->mode) + { + case CY_SYSPM_CHECK_READY: + case CY_SYSPM_CHECK_FAIL: + case CY_SYSPM_BEFORE_TRANSITION: + break; + + case CY_SYSPM_AFTER_TRANSITION: + Cy_LVD_Enable(); + break; + + default: + ret = CY_SYSPM_FAIL; + break; + } + + return(ret); +} + + +#ifdef __cplusplus +} +#endif + + +/* [] END OF FILE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/lvd/cy_lvd.h b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/lvd/cy_lvd.h new file mode 100644 index 0000000000..5c9d529006 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/device/drivers/peripheral/lvd/cy_lvd.h @@ -0,0 +1,433 @@ +/***************************************************************************//** +* \file cy_lvd.h +* \version 1.0.1 +* +* The header file of the LVD driver. +* +******************************************************************************** +* \copyright +* Copyright 2017-2018, Cypress Semiconductor Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 +*******************************************************************************/ + +/** +* \addtogroup group_lvd +* \{ +* The LVD driver provides an API to manage the Low Voltage Detection block. +* The LVD block provides a status of currently observed VDDD voltage +* and triggers an interrupt when the observed voltage crosses an adjusted +* threshold. +* +* \section group_lvd_configuration_considerations Configuration Considerations +* To set up an LVD, configure the voltage threshold by the +* \ref Cy_LVD_SetThreshold function, ensure that the LVD block itself and LVD +* interrupt are disabled (by the \ref Cy_LVD_Disable and +* \ref Cy_LVD_ClearInterruptMask functions correspondingly) before changing the +* threshold to prevent propagating a false interrupt. +* Then configure interrupts by the \ref Cy_LVD_SetInterruptConfig function, do +* not forget to initialise an interrupt handler (the interrupt source number +* is srss_interrupt_IRQn). +* Then enable LVD by the \ref Cy_LVD_Enable function, then wait for at least 20us +* to get the circuit stabilized and clear the possible false interrupts by the +* \ref Cy_LVD_ClearInterrupt, and finally the LVD interrupt can be enabled by +* the \ref Cy_LVD_SetInterruptMask function. +* +* For example: +* \snippet lvd_1_0_sut_00.cydsn/main_cm4.c Cy_LVD_Snippet +* +* Note that the LVD circuit is available only in Active, LPACTIVE, Sleep, and +* LPSLEEP power modes. If an LVD is required in Deep-Sleep mode, then the device +* should be configured to periodically wake up from deep sleep using a +* Deep-Sleep wakeup source. This makes sure a LVD check is performed during +* Active/LPACTIVE mode. +* +* \section group_lvd_more_information More Information +* See the LVD chapter of the device technical reference manual (TRM). +* +* \section group_lvd_MISRA MISRA-C Compliance +* The LVD driver has the following specific deviations: +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
MISRA RuleRule Class (Required/Advisory)Rule DescriptionDescription of Deviation(s)
10.3RA composite expression of 'essentially unsigned' type (%1s) is being +* cast to a different type category, '%2s'.The value got from the bitfield physically can't exceed the enumeration +* that describes this bitfield. So the code is safety by design.
16.7AThe object addressed by the pointer parameter '%s' is not modified and +* so the pointer could be of type 'pointer to const'.The pointer parameter is not used or modified, as there is no need +* to do any actions with it. However, such parameter is +* required to be presented in the function, because the +* \ref Cy_LVD_DeepSleepCallback is a callback +* of \ref cy_en_syspm_status_t type. +* The SysPM driver callback function type requires implementing the +* function with the next parameters and return value:
+* cy_en_syspm_status_t (*Cy_SysPmCallback) +* (cy_stc_syspm_callback_params_t *callbackParams);
+* +* \section group_lvd_changelog Changelog +* +* +* +* +* +* +* +* +* +* +* +* +*
VersionChangesReason of Change
1.0.1Added Low Power Callback sectionDocumentation update and clarification
1.0Initial Version
+* +* \defgroup group_lvd_macros Macros +* \defgroup group_lvd_functions Functions +* \{ +* \defgroup group_lvd_functions_syspm_callback Low Power Callback +* \} +* \defgroup group_lvd_enums Enumerated Types +*/ + + +#if !defined CY_LVD_H +#define CY_LVD_H + +#include "syspm/cy_syspm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup group_lvd_macros +* \{ +*/ + +/** The driver major version */ +#define CY_LVD_DRV_VERSION_MAJOR 1 + +/** The driver minor version */ +#define CY_LVD_DRV_VERSION_MINOR 0 + +/** The LVD driver identifier */ +#define CY_LVD_ID (CY_PDL_DRV_ID(0x39U)) + +/** Interrupt mask for \ref Cy_LVD_GetInterruptStatus(), + \ref Cy_LVD_GetInterruptMask() and + \ref Cy_LVD_GetInterruptStatusMasked() */ +#define CY_LVD_INTR (SRSS_SRSS_INTR_HVLVD1_Msk) + +/** \} group_lvd_macros */ + + +/** \addtogroup group_lvd_enums +* \{ +*/ + + +/** + * LVD reference voltage select. + */ +typedef enum +{ + CY_LVD_THRESHOLD_1_2_V = 0x0U, /**