diff --git a/.astyleignore b/.astyleignore index 54b1117..18b0693 100644 --- a/.astyleignore +++ b/.astyleignore @@ -19,6 +19,7 @@ ^features/unsupported/ ^hal/storage_abstraction ^platform/cxxsupport +^platform/tests/UNITTESTS ^events/tests/UNITTESTS ^rtos/source/TARGET_CORTEX/rtx4 ^rtos/source/TARGET_CORTEX/rtx5 diff --git a/TESTS/mbed_platform/CircularBuffer/main.cpp b/TESTS/mbed_platform/CircularBuffer/main.cpp deleted file mode 100644 index 74c4816..0000000 --- a/TESTS/mbed_platform/CircularBuffer/main.cpp +++ /dev/null @@ -1,502 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 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 "utest/utest.h" -#include "unity/unity.h" -#include "greentea-client/test_env.h" - -#include "mbed.h" - -using namespace utest::v1; - -/* Structure for complex type. */ -typedef struct { - int a; - char b; - int c; -} COMPLEX_TYPE; - -/* Function to check if complex type object holds specified values.*/ -bool comp_is_equal(COMPLEX_TYPE *object, int a, char b, int c) -{ - if (object->a == a && object->b == b && object->c == c) { - return true; - } - - return false; -} - -/* Function to set complex type object fields.*/ -void comp_set(COMPLEX_TYPE *object, int a, char b, int c) -{ - object->a = a; - object->b = b; - object->c = c; -} - -/* Test circular buffer - input does not exceed capacity. - * - * Given is a circular buffer with the capacity equal to N (BufferSize). - * When circular buffer is filled with N elements. - * Then all elements are read from the circular buffer in the FIFO order. - * - */ -template -void test_input_does_not_exceed_capacity_push_max_pop_max() -{ - CircularBuffer cb; - T data = 0; - - for (uint32_t i = 0; i < BufferSize; i++) { - data = (0xAA + i); - cb.push(data); - TEST_ASSERT_EQUAL(i + 1, cb.size()); - } - - for (uint32_t i = 0; i < BufferSize; i++) { - TEST_ASSERT_TRUE(cb.pop(data)); - TEST_ASSERT_EQUAL(0xAA + i, data); - TEST_ASSERT_EQUAL(BufferSize - i - 1, cb.size()); - } -} - -/* Test circular buffer - input does not exceed capacity. - * - * Given is a circular buffer with the capacity equal to N (BufferSize). - * When circular buffer is filled as follows: (2 * N - 2) times 2 elements are pushed and 1 element is popped. - * Then all elements are read from the circular buffer in the FIFO order. - * - */ -template -void test_input_does_not_exceed_capacity_push_2_pop_1() -{ - CircularBuffer cb; - static const int num_of_elem_push = (2 * BufferSize - 2); - T push_buffer = 0; - T pop_buffer = 0; - - /* Push 2 elements and pop one element in each cycle. */ - for (uint32_t i = 0; i < num_of_elem_push; i += 2) { - push_buffer = (0xAA + i); - cb.push(push_buffer); - push_buffer++; - cb.push(push_buffer); - TEST_ASSERT_EQUAL(i / 2 + 2, cb.size()); - - TEST_ASSERT_TRUE(cb.pop(pop_buffer)); - TEST_ASSERT_EQUAL(0xAA + i / 2, pop_buffer); - TEST_ASSERT_EQUAL(i / 2 + 1, cb.size()); - } - - /* Pop the rest. */ - for (uint32_t i = 0; i < (num_of_elem_push / 2); i++) { - TEST_ASSERT_TRUE(cb.pop(pop_buffer)); - TEST_ASSERT_EQUAL(0xAA + num_of_elem_push / 2 + i, pop_buffer); - TEST_ASSERT_EQUAL(num_of_elem_push / 2 - 1 - i, cb.size()); - - } -} - -/* Test circular buffer - input exceeds capacity. - * - * Given is a circular buffer with the capacity equal to N (BufferSize). - * When circular buffer is filled with N + 1 elements. - * Then first pushed element is lost (overwritten by the last element) and - * elements are read from the circular buffer in the FIFO order. - * - */ -template -void test_input_exceeds_capacity_push_max_plus_1_pop_max() -{ - CircularBuffer cb; - static const int num_of_elem_push = (BufferSize + 1); - T data = 0; - - for (uint32_t i = 0; i < num_of_elem_push; i++) { - data = (0xAA + i); - cb.push(data); - if (i < BufferSize) { - TEST_ASSERT_EQUAL(i + 1, cb.size()); - } else { - TEST_ASSERT_EQUAL(BufferSize, cb.size()); - } - - } - - for (uint32_t i = 0; i < (BufferSize - 1); i++) { - TEST_ASSERT_TRUE(cb.pop(data)); - TEST_ASSERT_EQUAL(0xAA + i + 1, data); - TEST_ASSERT_EQUAL(BufferSize - 1 - i, cb.size()); - } - - /* First element should be overwritten. */ - TEST_ASSERT_TRUE(cb.pop(data)); - TEST_ASSERT_EQUAL((0xAA + num_of_elem_push - 1), data); - TEST_ASSERT_EQUAL(0, cb.size()); -} - -/* Test circular buffer - input exceeds capacity. - * - * Given is a circular buffer with the capacity equal to N (BufferSize). - * When circular buffer is filled as follows: (2 * N) times 2 elements are pushed and 1 element is popped. - * Then first pushed element is lost (overwritten by the last element) and - * elements are read from the circular buffer in the FIFO order. - * - */ -template -void test_input_exceeds_capacity_push_2_pop_1() -{ - CircularBuffer cb; - static const int num_of_elem_push = (2 * BufferSize); - T push_buffer = 0; - T pop_buffer = 0; - - /* Push 2 elements and pop one element in each cycle. */ - for (uint32_t i = 0; i < num_of_elem_push; i += 2) { - push_buffer = (0xAA + i); - cb.push(push_buffer); - push_buffer++; - cb.push(push_buffer); - if ((i / 2 + 1) < BufferSize) { - TEST_ASSERT_EQUAL(i / 2 + 2, cb.size()); - } else { - TEST_ASSERT_EQUAL(BufferSize, cb.size()); - } - - TEST_ASSERT_TRUE(cb.pop(pop_buffer)); - if ((i / 2 + 1) < BufferSize) { - TEST_ASSERT_EQUAL(i / 2 + 1, cb.size()); - } else { - TEST_ASSERT_EQUAL(BufferSize - 1, cb.size()); - } - - /* First element has been overwritten. */ - if (i == (num_of_elem_push - 2)) { - TEST_ASSERT_EQUAL(0xAA + i / 2 + 1, pop_buffer); - } else { - TEST_ASSERT_EQUAL(0xAA + i / 2, pop_buffer); - } - } - - /* Pop the rest - one element has been overwritten. */ - for (uint32_t i = 0; i < (num_of_elem_push / 2 - 1); i++) { - TEST_ASSERT_TRUE(cb.pop(pop_buffer)); - TEST_ASSERT_EQUAL(0xAA + num_of_elem_push / 2 + i + 1, pop_buffer); - } -} - -/* Test circular buffer - input exceeds capacity (complex type). - * - * Given is a circular buffer with the capacity equal to N (BufferSize). - * When circular buffer is filled as follows: (2 * N) times 2 elements are pushed and 1 element is popped. - * Then first pushed element is lost (overwritten by the last element) and - * elements are read from the circular buffer in the FIFO order. - * - */ -template -void test_input_exceeds_capacity_push_2_pop_1_complex_type() -{ - CircularBuffer cb; - static const int num_of_elem_push = (2 * BufferSize); - COMPLEX_TYPE push_buffer = {0}; - COMPLEX_TYPE pop_buffer = {0}; - - /* Push 2 elements and pop one element in each cycle. */ - for (uint32_t i = 0; i < num_of_elem_push; i += 2) { - comp_set(&push_buffer, 0xAA + i, 0xBB + i, 0xCC + i); - cb.push(push_buffer); - comp_set(&push_buffer, 0xAA + i + 1, 0xBB + i + 1, 0xCC + i + 1); - cb.push(push_buffer); - if ((i / 2 + 1) < BufferSize) { - TEST_ASSERT_EQUAL(i / 2 + 2, cb.size()); - } else { - TEST_ASSERT_EQUAL(BufferSize, cb.size()); - } - - TEST_ASSERT_TRUE(cb.pop(pop_buffer)); - if ((i / 2 + 1) < BufferSize) { - TEST_ASSERT_EQUAL(i / 2 + 1, cb.size()); - } else { - TEST_ASSERT_EQUAL(BufferSize - 1, cb.size()); - } - - /* First element has been overwritten. */ - if (i == (num_of_elem_push - 2)) { - const bool result = comp_is_equal(&pop_buffer, 0xAA + 1 + i / 2, 0xBB + 1 + i / 2, 0xCC + 1 + i / 2); - TEST_ASSERT_TRUE(result); - } else { - const bool result = comp_is_equal(&pop_buffer, 0xAA + i / 2, 0xBB + i / 2, 0xCC + i / 2); - TEST_ASSERT_TRUE(result); - } - } - - /* Pop the rest - one element has been overwritten. */ - for (uint32_t i = 0; i < (num_of_elem_push / 2 - 1); i++) { - TEST_ASSERT_TRUE(cb.pop(pop_buffer)); - const bool result = comp_is_equal(&pop_buffer, 0xAA + num_of_elem_push / 2 + i + 1, - 0xBB + num_of_elem_push / 2 + i + 1, 0xCC + num_of_elem_push / 2 + i + 1); - TEST_ASSERT_TRUE(result); - } -} - -/* Test circular buffer - test pop(), peek(), empty(), full(), size() after CircularBuffer creation. - * - * Given is a circular buffer. - * When circular buffer is created. - * Then circular buffer is empty: - * - empty() returns true, - * - pop() function returns false, - * - peek() function returns false, - * - full() function returns false, - * - size() function returns 0, - * - */ -void test_pop_empty_full_size_after_creation() -{ - CircularBuffer cb; - int data = 0; - - TEST_ASSERT_TRUE(cb.empty()); - TEST_ASSERT_FALSE(cb.pop(data)); - TEST_ASSERT_FALSE(cb.peek(data)); - TEST_ASSERT_FALSE(cb.full()); - TEST_ASSERT_EQUAL(0, cb.size()); -} - -/* Test circular buffer - test empty() function. - * - * Given is a circular buffer with the capacity equal to N (BufferSize). - * When operations on circular buffer are performed (push, pop). - * Then empty() function returns true if buffer is empty, false otherwise. - * - */ -template -void test_empty() -{ - CircularBuffer cb; - T data = 0; - - /* Push max elements. */ - for (uint32_t i = 0; i < BufferSize; i++) { - cb.push(data); - TEST_ASSERT_FALSE(cb.empty()); - } - - /* Push next 2*BufferSize elements (overwrite entries). */ - for (uint32_t i = 0; i < (2 * BufferSize); i++) { - cb.push(data); - TEST_ASSERT_FALSE(cb.empty()); - } - - /* Pop (BufferSize - 1) elements (leave one). */ - for (uint32_t i = 0; i < (BufferSize - 1); i++) { - TEST_ASSERT_TRUE(cb.pop(data)); - TEST_ASSERT_FALSE(cb.empty()); - } - - /* Take one which is left. */ - TEST_ASSERT_TRUE(cb.pop(data)); - TEST_ASSERT_TRUE(cb.empty()); - - /* Add one element to the empty buffer. */ - cb.push(data); - TEST_ASSERT_FALSE(cb.empty()); -} - -/* Test circular buffer - test full() function. - * - * Given is a circular buffer with the capacity equal to N (BufferSize). - * When operations on circular buffer are performed (push, pop). - * Then full() function returns true if buffer is full, false otherwise. - * - */ -template -void test_full() -{ - CircularBuffer cb; - T data = 0; - - /* Push max elements - 1. */ - for (uint32_t i = 0; i < (BufferSize - 1); i++) { - cb.push(data); - TEST_ASSERT_FALSE(cb.full()); - } - - /* Push one element - buffer should be full now. */ - cb.push(data); - TEST_ASSERT_TRUE(cb.full()); - - /* Push next 2*BufferSize elements (overwrite entries). */ - for (uint32_t i = 0; i < (2 * BufferSize); i++) { - cb.push(data); - TEST_ASSERT_TRUE(cb.full()); - } - - /* Pop all elements. */ - for (uint32_t i = 0; i < BufferSize; i++) { - TEST_ASSERT_TRUE(cb.pop(data)); - TEST_ASSERT_FALSE(cb.full()); - } -} - -/* Test circular buffer - test reset() function. - * - * Given is a circular buffer with the capacity equal to N (BufferSize). - * When reset operation is performed on circular buffer. - * Then circular buffer is cleared. - * - */ -template -void test_reset() -{ - CircularBuffer cb; - T data = 0xAA; - - /* Push max elements. */ - for (uint32_t i = 0; i < BufferSize; i++) { - cb.push(data); - } - - TEST_ASSERT_TRUE(cb.full()); - TEST_ASSERT_FALSE(cb.empty()); - TEST_ASSERT_EQUAL(BufferSize, cb.size()); - - cb.reset(); - - TEST_ASSERT_FALSE(cb.full()); - TEST_ASSERT_TRUE(cb.empty()); - TEST_ASSERT_FALSE(cb.pop(data)); - TEST_ASSERT_EQUAL(0, cb.size()); - - /* Check if after reset push and pop operations work. */ - for (uint32_t i = 0; i < BufferSize; i++) { - cb.push(data); - data++; - } - - for (uint32_t i = 0; i < BufferSize; i++) { - cb.pop(data); - TEST_ASSERT_EQUAL(0xAA + i, data); - } -} - -/* Test circular buffer - creation of circular buffer with max buffer size consistent with counter type. - * - * Given is a circular buffer. - * When circular buffer is created with buffer size equal to 255 and counter type equal to unsigned char. - * Then circular buffer is successfully created. - * - */ -void test_counter_type_buffer_size() -{ - CircularBuffer cb; - int data = 100; - - /* Perform some operations. */ - cb.push(data); - data = 0; - cb.pop(data); - TEST_ASSERT_EQUAL(100, data); -} - -/* Test circular buffer - peek should not update buffer data. - * - * When circular buffer peek operation is performed along with - * push and pop, it should not update the buffer data elements. - * Elements read using pop/peek operation should match. - * - */ -void test_peek_no_pop() -{ - CircularBuffer cb; - int data = 0; - int peek_data = 0; - - for (uint32_t i = 0; i < 3; i++) { - data = (0xAA + i); - cb.push(data); - cb.peek(peek_data); - TEST_ASSERT_EQUAL(i + 1, cb.size()); - } - - for (uint32_t i = 0; i < 3; i++) { - TEST_ASSERT_TRUE(cb.peek(peek_data)); - TEST_ASSERT_EQUAL(0xAA + i, peek_data); - TEST_ASSERT_TRUE(cb.pop(data)); - TEST_ASSERT_EQUAL(0xAA + i, data); - TEST_ASSERT_EQUAL(3 - i - 1, cb.size()); - } -} - -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; -} - -Case cases[] = { - Case("Input does not exceed capacity(1) push max, pop max.", - test_input_does_not_exceed_capacity_push_max_pop_max, greentea_failure_handler), - Case("Input does not exceed capacity(3) push max, pop max.", - test_input_does_not_exceed_capacity_push_max_pop_max, greentea_failure_handler), - - Case("Input does not exceed capacity(5) push 2, pop 1.", - test_input_does_not_exceed_capacity_push_2_pop_1, greentea_failure_handler), - Case("Input does not exceed capacity(10) push 2, pop 1.", - test_input_does_not_exceed_capacity_push_2_pop_1, greentea_failure_handler), - - Case("Input exceeds capacity(1) push max+1, pop max.", - test_input_exceeds_capacity_push_max_plus_1_pop_max, greentea_failure_handler), - Case("Input exceeds capacity(3) push max+1, pop max.", - test_input_exceeds_capacity_push_max_plus_1_pop_max, greentea_failure_handler), - - Case("Input exceeds capacity(5) push 2, pop 1.", - test_input_exceeds_capacity_push_2_pop_1, greentea_failure_handler), - Case("Input exceeds capacity(10) push 2, pop 1.", - test_input_exceeds_capacity_push_2_pop_1, greentea_failure_handler), - - Case("empty() returns true when buffer(3 elements) is empty.", test_empty, greentea_failure_handler), - Case("empty() returns true when buffer(5 elements) is empty.", test_empty, greentea_failure_handler), - - Case("full() returns true when buffer(3 elements) is full.", test_full, greentea_failure_handler), - Case("full() returns true when buffer(5 elements) is full.", test_full, greentea_failure_handler), - - Case("reset() clears the buffer.", test_reset, greentea_failure_handler), - - Case("Test pop(), peek(), empty(), full(), size() after CircularBuffer creation.", - test_pop_empty_full_size_after_creation, greentea_failure_handler), - - Case("Test CounterType/BufferSize boarder case.", test_counter_type_buffer_size, greentea_failure_handler), - - Case("Input exceeds capacity(5) push 2, pop 1 - complex type.", - test_input_exceeds_capacity_push_2_pop_1_complex_type<5, unsigned short>, greentea_failure_handler), - - Case("peek() return data without popping the element.", test_peek_no_pop, greentea_failure_handler), -}; - -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(15, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); - -int main() -{ - return Harness::run(specification); -} diff --git a/TESTS/mbed_platform/FileHandle/TestFile.h b/TESTS/mbed_platform/FileHandle/TestFile.h deleted file mode 100644 index c99d8cc..0000000 --- a/TESTS/mbed_platform/FileHandle/TestFile.h +++ /dev/null @@ -1,160 +0,0 @@ -/* mbed Microcontroller Library - * 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_TESTFILEHANDLE_H -#define MBED_TESTFILEHANDLE_H - -#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 mbed::FileHandle { -public: - TestFile(): _pos(0), _end(0) {} - ~TestFile() {} - - enum FunctionName { - fnNone, fnRead, fnWrite, fnSeek, fnClose, fnIsatty, fnTruncate - }; - - virtual ssize_t read(void *buffer, size_t size) - { - ssize_t read; - _fnCalled = fnRead; - - for (read = 0; (size_t)read < size; read++) { - if (POS_IS_VALID(_pos)) { - ((uint8_t *)buffer)[read] = _data[_pos++]; - } else { - break; - } - } // for - return read; - } - - virtual ssize_t write(const void *buffer, size_t size) - { - ssize_t written; - _fnCalled = fnWrite; - - for (written = 0; (size_t)written < size; written++) { - if (NEW_POS_IS_VALID(_pos)) { - _data[_pos++] = ((uint8_t *)buffer)[written]; - } else { - if (0 == written) { - return -ENOSPC; - } - break; - } - if (_end < _pos) { - _end++; - } - } // for - return written; - } - - virtual off_t seek(off_t offset, int whence) - { - _fnCalled = fnSeek; - int32_t new_pos = INVALID_POS; - - switch (whence) { - case SEEK_SET: - new_pos = offset; - break; - - case SEEK_CUR: - new_pos = _pos + offset; - break; - - case SEEK_END: - new_pos = _end - offset; - break; - - default: - // nothing todo - break; - } - - if (SEEK_POS_IS_VALID(new_pos)) { - _pos = new_pos; - } else { - return -EINVAL; - } - - return _pos; - } - - virtual int close() - { - _fnCalled = fnClose; - return 0; - } - - virtual off_t size() - { - return _end; - } - - virtual int truncate(off_t length) - { - _fnCalled = fnTruncate; - if (!NEW_POS_IS_VALID(length)) { - return -EINVAL; - } - while (_end < length) { - _data[_end++] = 0; - } - _end = length; - return 0; - } - - - static void resetFunctionCallHistory() - { - _fnCalled = fnNone; - } - - static bool functionCalled(FunctionName name) - { - return (name == _fnCalled); - } - - static FunctionName getFunctionCalled() - { - return _fnCalled; - } - -private: - - // stores last function call name - static FunctionName _fnCalled; - - // file storage - uint8_t _data[FILE_SIZE]; - - int32_t _pos, _end; -}; - -template -typename TestFile::FunctionName TestFile::_fnCalled; - - -#endif // MBED_TESTFILEHANDLE_H diff --git a/TESTS/mbed_platform/FileHandle/main.cpp b/TESTS/mbed_platform/FileHandle/main.cpp deleted file mode 100644 index 4efd8f4..0000000 --- a/TESTS/mbed_platform/FileHandle/main.cpp +++ /dev/null @@ -1,574 +0,0 @@ -/* mbed Microcontroller Library - * 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 "greentea-client/test_env.h" -#include "utest/utest.h" -#include "unity/unity.h" -#include "TestFile.h" -#include "mbed.h" - -using utest::v1::Case; - - -/** Test fopen and fclose - * - * Given a file to be opened - * - * When the file is open - * Then returned file descriptor is valid - * - * When the file is closed - * Then underneath retargeting layer function is called - * and the fclose function return with succeed - * - */ -void test_fopen_fclose() -{ - std::FILE *file; - const uint32_t FS = 5; - TestFile fh; - - file = fdopen(&fh, "w+"); - TEST_ASSERT_NOT_NULL(file); - - TestFile::resetFunctionCallHistory(); - int ret = std::fclose(file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnClose)); - TEST_ASSERT_EQUAL_INT(0, ret); -} - - -/** Test fwrite and fread - * - * Given already opened file - * - * When write some data to file - * Then underneath retargeting layer write function is called - * fwrite return number of successfully written elements - * when not all elements were written stream error is set - * - * When read previously written data from file - * Then underneath retargeting layer read function is called - * fread return number of successfully read elements - * read data match previously written - * when read less then expected stream eof is set - * - */ -void test_fwrite_fread() -{ - std::FILE *file; - const uint32_t FS = 5; - TestFile fh; - char read_buf[16]; - const char *str1 = "abc"; - const char *str2 = "def"; - const uint32_t str1_size = strlen(str1); - const uint32_t str2_size = strlen(str2); - std::size_t write_ret; - std::size_t read_ret; - - file = fdopen(&fh, "w+"); - TEST_ASSERT_NOT_NULL(file); - std::setbuf(file, NULL); - - // write 3; expected written 3 - TestFile::resetFunctionCallHistory(); - write_ret = std::fwrite(str1, 1, str1_size, file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); - TEST_ASSERT_EQUAL_INT(str1_size, write_ret); - - // write 3; expected written 2 - TestFile::resetFunctionCallHistory(); - write_ret = std::fwrite(str2, 1, str2_size, file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); -#if !defined(__MICROLIB) - TEST_ASSERT_TRUE(std::ferror(file) != 0); -#endif - std::clearerr(file); - - // ARMCC/IAR returns 0 here instead of number of elements successfully written !!! - TEST_ASSERT_TRUE(write_ret >= 0 && write_ret <= (str2_size - 1)); - - // write 3; expected written 0 - TestFile::resetFunctionCallHistory(); - write_ret = std::fwrite(str1, 1, str1_size, file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); -#if !defined(__MICROLIB) - TEST_ASSERT_TRUE(std::ferror(file) != 0); -#endif - TEST_ASSERT_EQUAL_INT(0, write_ret); - - std::rewind(file); - - // read 3; expected read 3 - TestFile::resetFunctionCallHistory(); - read_ret = std::fread(read_buf, 1, str1_size, file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); - TEST_ASSERT_EQUAL_INT(str1_size, read_ret); - TEST_ASSERT_EQUAL_INT(0, strncmp(str1, read_buf, str1_size)); - - // read 3; expected read 2 - TestFile::resetFunctionCallHistory(); - read_ret = std::fread(read_buf, 1, str2_size, file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); -#if !defined(__MICROLIB) - TEST_ASSERT_TRUE(std::feof(file) != 0); -#endif - std::clearerr(file); - TEST_ASSERT_EQUAL_INT(str2_size - 1, read_ret); - TEST_ASSERT_EQUAL_INT(0, strncmp(str2, read_buf, str2_size - 1)); - - // read 3; expected read 0 - TestFile::resetFunctionCallHistory(); - read_ret = std::fread(read_buf, 1, str2_size, file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); -#if !defined(__MICROLIB) - TEST_ASSERT_TRUE(std::feof(file) != 0); -#endif - TEST_ASSERT_EQUAL_INT(0, read_ret); - - std::fclose(file); -} - - - -/** Test fputc and fgetc - * - * Given already opened file - * - * When write some data to file - * Then underneath retargeting layer write function is called - * fputc return written element - * on failure, returns EOF and stream error is sets - * - * When read previously written data from file - * Then underneath retargeting layer read function is called - * fgetc return read element - * read data match previously written - * on failure, returns EOF and stream error/eof is sets respectively - * - */ -void test_fputc_fgetc() -{ - std::FILE *file; - const uint32_t FS = 3; - TestFile fh; - char char_buf[3] = {'a', 'b', 'c' }; - int ret; - - file = fdopen(&fh, "w+"); - TEST_ASSERT_NOT_NULL(file); - std::setbuf(file, NULL); - - // write 1; expected written 1 - TestFile::resetFunctionCallHistory(); - ret = std::fputc(char_buf[0], file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); - TEST_ASSERT_EQUAL_INT(char_buf[0], ret); - - // write 1; expected written 1 - TestFile::resetFunctionCallHistory(); - ret = std::fputc(char_buf[1], file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); - TEST_ASSERT_EQUAL_INT(char_buf[1], ret); - - // write 1; expected written 1 - TestFile::resetFunctionCallHistory(); - ret = std::fputc(char_buf[2], file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); - TEST_ASSERT_EQUAL_INT(char_buf[2], ret); - - // write 1; expected written 0 - TestFile::resetFunctionCallHistory(); - ret = std::fputc(char_buf[0], file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); -#if !defined(__MICROLIB) - TEST_ASSERT_TRUE(std::ferror(file) != 0); -#endif - TEST_ASSERT_EQUAL_INT(EOF, ret); - - std::rewind(file); - - // read 1; expected read 1 - TestFile::resetFunctionCallHistory(); - ret = std::fgetc(file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); - TEST_ASSERT_EQUAL_INT(char_buf[0], ret); - - // read 1; expected read 1 - TestFile::resetFunctionCallHistory(); - ret = std::fgetc(file); - TEST_ASSERT_EQUAL_INT(char_buf[1], ret); - - // read 1; expected read 1 - TestFile::resetFunctionCallHistory(); - ret = std::fgetc(file); - TEST_ASSERT_EQUAL_INT(char_buf[2], ret); - - // read 1; expected read 0 - TestFile::resetFunctionCallHistory(); - ret = std::fgetc(file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); -#if !defined(__MICROLIB) - TEST_ASSERT_TRUE(std::feof(file) != 0); -#endif - TEST_ASSERT_EQUAL_INT(EOF, ret); - - std::fclose(file); -} - -/** Test fputs and fgets - * - * Given already opened file - * - * When write some data to file - * Then underneath retargeting layer write function is called - * on success, returns a non-negative value - * on failure, returns EOF and set stream error - * - * When read previously written data from file - * Then underneath retargeting layer read function is called - * fgets return valid buffer, and read data match previously written - * when read less then expected stream EOF is set - * on failure, stream error is sets - * - */ -void test_fputs_fgets() -{ - std::FILE *file; - const uint32_t FS = 5; - TestFile fh; - const char *str1 = "abc"; - const char *str2 = "def"; - const uint32_t str1_size = strlen(str1); - const uint32_t str2_size = strlen(str2); - char read_buf[16]; - int fputs_ret; - char *fgets_ret; - - file = fdopen(&fh, "w+"); - TEST_ASSERT_NOT_NULL(file); - std::setbuf(file, NULL); - - // write 3; expected written 3 - TestFile::resetFunctionCallHistory(); - fputs_ret = std::fputs(str1, file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); - TEST_ASSERT_TRUE(fputs_ret >= 0); - - // write 3; expected written 2 - TestFile::resetFunctionCallHistory(); - fputs_ret = std::fputs(str2, file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); -#if !defined(__MICROLIB) - TEST_ASSERT_TRUE(std::ferror(file) != 0); -#endif - std::clearerr(file); - TEST_ASSERT_EQUAL_INT(EOF, fputs_ret); - - // write 3; expected written 0 - TestFile::resetFunctionCallHistory(); - fputs_ret = std::fputs(str1, file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); -#if !defined(__MICROLIB) - TEST_ASSERT_TRUE(std::ferror(file) != 0); -#endif - TEST_ASSERT_EQUAL_INT(EOF, fputs_ret); - - std::rewind(file); - - // read 3; expected read 3 - TestFile::resetFunctionCallHistory(); - fgets_ret = std::fgets(read_buf, str1_size + 1, file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); - TEST_ASSERT_EQUAL_INT(read_buf, fgets_ret); - TEST_ASSERT_EQUAL_INT(0, strncmp(read_buf, str1, str1_size)); - - // read 3; expected read 2 - TestFile::resetFunctionCallHistory(); - fgets_ret = std::fgets(read_buf, str2_size + 1, file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); -#if !defined(__MICROLIB) - TEST_ASSERT_TRUE(std::feof(file) != 0); -#endif - std::clearerr(file); - TEST_ASSERT_EQUAL_INT(read_buf, fgets_ret); - TEST_ASSERT_EQUAL_INT(0, strncmp(read_buf, str2, str2_size - 2)); - - // read 3; expected read 0 - TestFile::resetFunctionCallHistory(); - fgets_ret = std::fgets(read_buf, str2_size + 1, file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); -#if !defined(__MICROLIB) - TEST_ASSERT_TRUE(std::feof(file) != 0); -#endif - TEST_ASSERT_EQUAL_INT(NULL, fgets_ret); - - std::fclose(file); -} - -/** Test fprintf and fscanf - * - * Given already opened file - * - * When write some data to file - * Then underneath retargeting layer write function is called - * fprintf return number of written components - * fprintf return negative value if an error occurred and set stream error - * - * When read previously written data from file - * Then underneath retargeting layer read function is called - * fscanf return number of read components, and read data match previously written - * when read less then expected stream EOF is set - * on failure, stream error is sets - * - */ -void test_fprintf_fscanf() -{ - std::FILE *file; - const uint32_t FS = 5; - TestFile fh; - const char *str1 = "abc"; - const char *str2 = "def"; - const uint32_t str1_size = strlen(str1); - const uint32_t str2_size = strlen(str2); - char read_buf[16]; - int fprintf_ret; - int fscanf_ret; - - file = fdopen(&fh, "w+"); - TEST_ASSERT_NOT_NULL(file); - std::setbuf(file, NULL); - - // write 3; expected written 3 - TestFile::resetFunctionCallHistory(); - fprintf_ret = fprintf(file, "%s", str1); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); - TEST_ASSERT_EQUAL_INT(str1_size, fprintf_ret); - -#if !defined(__MICROLIB) - // feof() and ferror() functions are not supported in Microlib. - // write 3; expected written 2 - TestFile::resetFunctionCallHistory(); - fprintf_ret = fprintf(file, "%s", str2); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); - TEST_ASSERT_TRUE(std::ferror(file) != 0); - std::clearerr(file); - TEST_ASSERT_TRUE(fprintf_ret < 0); - - // write 3; expected written 0 - TestFile::resetFunctionCallHistory(); - fprintf_ret = fprintf(file, "%s", str2); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); - TEST_ASSERT_TRUE(std::ferror(file) != 0); - TEST_ASSERT_TRUE(fprintf_ret < 0); -#else - // Writing remaining available file space of 2 characters - // to make further fscanf() test to pass. - // write 2; expected written 2 - TestFile::resetFunctionCallHistory(); - fprintf_ret = 0; - fprintf_ret += fprintf(file, "%c", str2[0]); - fprintf_ret += fprintf(file, "%c", str2[1]); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); - TEST_ASSERT_EQUAL_INT(2, fprintf_ret); -#endif - std::rewind(file); - - // read 3; expected read 3 - TestFile::resetFunctionCallHistory(); - fscanf_ret = fscanf(file, "%3s", read_buf); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); - TEST_ASSERT_EQUAL_INT(1, fscanf_ret); - TEST_ASSERT_EQUAL_INT(0, strncmp(read_buf, str1, str1_size)); - - // read 3; expected read 2 - TestFile::resetFunctionCallHistory(); - fscanf_ret = fscanf(file, "%3s", read_buf); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); -#if !defined(__MICROLIB) - TEST_ASSERT_TRUE(std::feof(file) != 0); - std::clearerr(file); -#endif - TEST_ASSERT_EQUAL_INT(1, fscanf_ret); - TEST_ASSERT_EQUAL_INT(0, strncmp(read_buf, str2, str2_size - 1)); - - // read 3; expected read 0 - TestFile::resetFunctionCallHistory(); - fscanf_ret = fscanf(file, "%3s", read_buf); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); -#if !defined(__MICROLIB) - TEST_ASSERT_TRUE(std::feof(file) != 0); -#endif - TEST_ASSERT_EQUAL_INT(EOF, fscanf_ret); - - std::fclose(file); -} - -/** Test fseek and ftell - * - * ARM library is quite good at optimising out unnecessary calls to underlying - * seek, so only test real non empty files. - * - * Given already opened file is not empty - * - * When set the file position indicator via fseek - * Then underneath retargeting layer seek function is called - * fseek return with succeed and ftell return already set position - * Check actual character read or written. - * - */ -void test_fseek_ftell() -{ - std::FILE *file; - long ftell_ret; - int fssek_ret; - const uint32_t FS = 128; - TestFile fh; - - file = fdopen(&fh, "w+"); - TEST_ASSERT_NOT_NULL(file); - std::setbuf(file, NULL); - - TestFile::resetFunctionCallHistory(); - ftell_ret = std::ftell(file); - TEST_ASSERT_EQUAL(0, ftell_ret); - - const char *str = "Hello world"; - const std::size_t size = std::strlen(str); - - std::fwrite(str, 1, size, file); - - TestFile::resetFunctionCallHistory(); - ftell_ret = std::ftell(file); - TEST_ASSERT_EQUAL(size, ftell_ret); - - TestFile::resetFunctionCallHistory(); - fssek_ret = std::fseek(file, 5, SEEK_SET); - TEST_ASSERT_EQUAL(0, fssek_ret); - ftell_ret = std::ftell(file); - TEST_ASSERT_EQUAL(5, ftell_ret); - int c = std::fgetc(file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); - TEST_ASSERT_EQUAL(c, str[5]); - - TestFile::resetFunctionCallHistory(); - fssek_ret = std::fseek(file, -6, SEEK_CUR); - TEST_ASSERT_EQUAL(0, fssek_ret); - ftell_ret = std::ftell(file); - TEST_ASSERT_EQUAL(0, ftell_ret); - c = std::fgetc(file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); - TEST_ASSERT_EQUAL(c, str[0]); - - TestFile::resetFunctionCallHistory(); - fssek_ret = std::fseek(file, 0, SEEK_END); - TEST_ASSERT_EQUAL(0, fssek_ret); - ftell_ret = std::ftell(file); - TEST_ASSERT_EQUAL(size, ftell_ret); - c = std::fputc('!', file); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); - TEST_ASSERT_EQUAL(c, '!'); - TEST_ASSERT_EQUAL(fh.size(), size + 1); - - std::fclose(file); -} - -/** Test ftruncate and fstat (st_size) - * - * Check we get EBADF for illegal handles - * - * Given already opened file is empty - * - * Check initial size is returned as 0 - * Call ftruncate with negative value - check our EINVAL is passed back - * Call ftruncate with positive value to increase size - check no error return - * Check fstat st_size now reads back as the value we set. - * Call ftruncate with smaller positive value to decrease size - check no error return - * Check fstat st_size now reads back as the value we set. - */ -void test_ftruncate_fstat() -{ - int fildes; - int ret; - struct stat st; - const uint32_t FS = 128; - TestFile fh; - - ret = ftruncate(12345678, 24); - TEST_ASSERT_EQUAL(-1, ret); - TEST_ASSERT_EQUAL(EBADF, errno); - - ret = fstat(12345678, &st); - TEST_ASSERT_EQUAL(-1, ret); - TEST_ASSERT_EQUAL(EBADF, errno); - - fildes = bind_to_fd(&fh); - TEST_ASSERT_TRUE(fildes >= 0); - - ret = fstat(fildes, &st); - TEST_ASSERT_EQUAL(0, ret); - TEST_ASSERT_EQUAL(0, st.st_size); - - TestFile::resetFunctionCallHistory(); - ret = ftruncate(fildes, -3); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnTruncate)); - TEST_ASSERT_EQUAL(-1, ret); - TEST_ASSERT_EQUAL(EINVAL, errno); - - TestFile::resetFunctionCallHistory(); - ret = ftruncate(fildes, 24); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnTruncate)); - TEST_ASSERT_EQUAL(0, ret); - - ret = fstat(fildes, &st); - TEST_ASSERT_EQUAL(0, ret); - TEST_ASSERT_EQUAL(24, st.st_size); - - ret = ftruncate(fildes, 12); - TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnTruncate)); - TEST_ASSERT_EQUAL(0, ret); - - ret = fstat(fildes, &st); - TEST_ASSERT_EQUAL(0, ret); - TEST_ASSERT_EQUAL(12, st.st_size); - - close(fildes); -} - -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 fopen/fclose", test_fopen_fclose), - Case("Test fwrite/fread", test_fwrite_fread), - Case("Test fputc/fgetc", test_fputc_fgetc), - Case("Test fputs/fgets", test_fputs_fgets), - Case("Test fprintf/fscanf", test_fprintf_fscanf), - Case("Test fseek/ftell", test_fseek_ftell), - Case("Test ftruncate/fstat", test_ftruncate_fstat) -}; - -utest::v1::Specification specification(test_setup, cases); - -int main() -{ - return !utest::v1::Harness::run(specification); -} diff --git a/TESTS/mbed_platform/SharedPtr/main.cpp b/TESTS/mbed_platform/SharedPtr/main.cpp deleted file mode 100644 index f1321ee..0000000 --- a/TESTS/mbed_platform/SharedPtr/main.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* mbed Microcontroller Library - * 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 "mbed.h" -#include "greentea-client/test_env.h" -#include "utest/utest.h" -#include "unity/unity.h" - -#include "platform/SharedPtr.h" - -using utest::v1::Case; - -struct TestStruct { - TestStruct() - { - s_count++; - value = 42; - } - - ~TestStruct() - { - s_count--; - value = 0; - } - - int value; - static int s_count; -}; - -int TestStruct::s_count = 0; - -/** - * Test that a shared pointer correctly manages the lifetime of the underlying raw pointer - */ -void test_single_sharedptr_lifetime() -{ - // Sanity-check value of counter - TEST_ASSERT_EQUAL(0, TestStruct::s_count); - - // Create and destroy shared pointer in given scope - { - SharedPtr s_ptr(new TestStruct); - TEST_ASSERT_EQUAL(1, TestStruct::s_count); - } - - // Destroy shared pointer - TEST_ASSERT_EQUAL(0, TestStruct::s_count); -} - -/** - * Test that multiple instances of shared pointers correctly manage the reference count - * to release the object at the correct point - */ -void test_instance_sharing() -{ - SharedPtr s_ptr1(nullptr); - - // Sanity-check value of counter - TEST_ASSERT_EQUAL(0, TestStruct::s_count); - - // Create and destroy shared pointer in given scope - { - SharedPtr s_ptr2(new TestStruct); - TEST_ASSERT_EQUAL(1, TestStruct::s_count); - s_ptr1 = s_ptr2; - TEST_ASSERT_EQUAL(1, TestStruct::s_count); - } - - TEST_ASSERT_EQUAL(1, TestStruct::s_count); - - s_ptr1 = nullptr; - - // Destroy shared pointer - TEST_ASSERT_EQUAL(0, TestStruct::s_count); -} - -/** - * Test whether comparison operators operate as expected, both between - * shared pointers managing the same object, - * and a shared pointer and underlying raw pointer - */ -void test_equality_comparators() -{ - TestStruct *raw_ptr1 = new TestStruct; - TestStruct *raw_ptr2 = new TestStruct; - SharedPtr s_ptr1_1(raw_ptr1); - SharedPtr s_ptr1_2 = s_ptr1_1; - SharedPtr s_ptr2(raw_ptr2); - - // Pointers that should be deemed equal - TEST_ASSERT_TRUE(s_ptr1_1 == raw_ptr1); // Shared pointer / Raw pointer - TEST_ASSERT_TRUE(s_ptr1_1 == s_ptr1_2); // Shared pointer / Shared pointer - - // Pointers that should be deemed different - TEST_ASSERT_TRUE(s_ptr1_1 != raw_ptr2); // Shared pointer / Raw pointer - TEST_ASSERT_TRUE(s_ptr1_1 != s_ptr2); // Shared pointer / Shared pointer -} - -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 single shared pointer instance", test_single_sharedptr_lifetime), - Case("Test instance sharing across multiple shared pointers", test_instance_sharing), - Case("Test equality comparators", test_equality_comparators) -}; - -utest::v1::Specification specification(test_setup, cases); - -int main() -{ - return !utest::v1::Harness::run(specification); -} diff --git a/TESTS/mbed_platform/SingletonPtr/main.cpp b/TESTS/mbed_platform/SingletonPtr/main.cpp deleted file mode 100644 index 9a59bda..0000000 --- a/TESTS/mbed_platform/SingletonPtr/main.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 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 "mbed.h" -#include "greentea-client/test_env.h" -#include "utest/utest.h" -#include "unity/unity.h" - -using utest::v1::Case; - - -class InstanceTest { -public: - InstanceTest() - { - _instance_counter++; - } - - static int get_instance_counter() - { - return _instance_counter; - } - -private: - static int _instance_counter; -}; - -int InstanceTest::_instance_counter = 0; - - -SingletonPtr singleton; - - -/** Test SingletonPtr lazy initialization - * - * Given a global singleton of type SingletonPtr - * When before first singleton use - * Then underneath object is yet not created - */ -void test_lazy_initialization() -{ - TEST_ASSERT_MESSAGE(InstanceTest::get_instance_counter() == 0, "Initialized before first use!!!"); -} - -/** Test SingletonPtr single instance - * - * Given a singleton of type SingletonPtr - * - * When after first singleton use - * Then underneath object was created exactly once - * - * When after second singleton use - * Then underneath object was created exactly once - * and both (ref1 and ref2) are references to same instance - * - */ -void test_single_instance() -{ - InstanceTest *ref1 = singleton.get(); - TEST_ASSERT_NOT_NULL(ref1); - - TEST_ASSERT_EQUAL_INT(1, InstanceTest::get_instance_counter()); - - InstanceTest *ref2 = singleton.get(); - TEST_ASSERT_NOT_NULL(ref2); - - TEST_ASSERT_EQUAL_INT(1, InstanceTest::get_instance_counter()); - - // same instance - TEST_ASSERT_EQUAL_PTR(ref1, ref2); -} - -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 lazy initialization", test_lazy_initialization), - Case("Test single instance", test_single_instance), -}; - -utest::v1::Specification specification(test_setup, cases); - -int main() -{ - return !utest::v1::Harness::run(specification); -} diff --git a/TESTS/mbed_platform/Stream/main.cpp b/TESTS/mbed_platform/Stream/main.cpp deleted file mode 100644 index 7aa4b51..0000000 --- a/TESTS/mbed_platform/Stream/main.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* mbed Microcontroller Library - * 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 "greentea-client/test_env.h" -#include "utest/utest.h" -#include "unity/unity.h" -#include "mbed.h" -#include "Stream.h" - -/* This test suite verifies that write/read/write/read sequence can be - * successfully executed on the Stream objects. - * - * A qute from C99 standard, paragraph 7.19.5.3, point 6: - * - * When a file is opened with update mode ('+' as the second or third character in the - * above list of mode argument values), both input and output may be performed on the - * associated stream. However, output shall not be directly followed by input without an - * intervening call to the fflush function or to a file positioning function (fseek, - * fsetpos, or rewind), and input shall not be directly followed by output without an - * intervening call to a file positioning function, unless the input operation encounters end- - * of-file. - */ - -using utest::v1::Case; - -const char FMT[] = "Foo%02ibar."; -const size_t FORMATTED_STR_SIZE = 3 + 2 + 4 + 1; -// The test Stream instance has to be able to store two printf() output strings. -const size_t LOOPBACK_BUFF_SIZE = 2 * FORMATTED_STR_SIZE; - -class Loopback : public Stream { -public: - Loopback(const char *name = NULL) : Stream(name) - { - // The `fgets()` stops reading after a newline or EOF. - // Fill the buffer with newlines to simplify fgets() usage in this test. - memset(_buff, '\n', LOOPBACK_BUFF_SIZE); - _p_index = 0; - _g_index = 0; - } - - virtual ~Loopback() - { - } - - int test_vprintf(const char *fmt, ...) - { - int rc = -1; - std::va_list args; - va_start(args, fmt); - rc = vprintf(fmt, args); - va_end(args); - return rc; - } - - int test_vscanf(const char *fmt, ...) - { - int rc = EOF; - std::va_list args; - va_start(args, fmt); - rc = vscanf(fmt, args); - va_end(args); - return rc; - } - -protected: - virtual int _putc(int c) - { - if (_p_index >= LOOPBACK_BUFF_SIZE) { - return -1; - } - _buff[_p_index++] = (int8_t)c; - return c; - } - - virtual int _getc() - { - if (_g_index >= LOOPBACK_BUFF_SIZE) { - return -1; - } - return _buff[_g_index++]; - } - -private: - int8_t _buff[LOOPBACK_BUFF_SIZE]; - size_t _p_index; - size_t _g_index; -}; - -/* Test intermixed Stream::putc() / Stream::getc(). - * - * Given a Stream object, - * when a write/read/write/read sequence is executed - * with the use of Stream::putc() and Stream::getc() methods, - * then all operations succeed. - */ -void test_putc_getc() -{ - char char_buff[2] = {'a', 'b'}; - Loopback loop("loopback"); - int ret; - - ret = loop.putc(char_buff[0]); - TEST_ASSERT_EQUAL_INT(char_buff[0], ret); - ret = loop.getc(); - TEST_ASSERT_EQUAL_INT(char_buff[0], ret); - ret = loop.putc(char_buff[1]); - TEST_ASSERT_EQUAL_INT(char_buff[1], ret); - ret = loop.getc(); - TEST_ASSERT_EQUAL_INT(char_buff[1], ret); -} - -/* Test intermixed Stream::puts() / Stream::gets(). - * - * Given a Stream object, - * when a write/read/write/read sequence is executed, - * with the use of Stream::puts() and Stream::gets() methods, - * then all operations succeed. - */ -void test_puts_gets() -{ - const size_t STR_LEN = 3; - const size_t STR_SIZE = STR_LEN + 1; // +1 for '\0' - char strings[2][STR_SIZE] = {"Foo", "Bar"}; - const size_t GETS_BUFF_SIZE = STR_LEN + 2; // +1 for '\n' (gets() stops AFTER a '\n'), +1 for '\0' - char g_buff[GETS_BUFF_SIZE] = {}; - Loopback loop("loopback"); - int p_rc; - char *g_rc; - - p_rc = loop.puts(strings[0]); - TEST_ASSERT(p_rc >= 0); - g_rc = loop.gets(g_buff, GETS_BUFF_SIZE); - TEST_ASSERT_EQUAL_PTR(g_buff, g_rc); - - p_rc = loop.puts(strings[1]); - TEST_ASSERT(p_rc >= 0); - g_rc = loop.gets(g_buff, GETS_BUFF_SIZE); - TEST_ASSERT_EQUAL_PTR(g_buff, g_rc); -} - -/* Test intermixed Stream::printf() / Stream::scanf(). - * - * Given a Stream object, - * when a write/read/write/read sequence is executed, - * with the use of Stream::printf() and Stream::scanf() methods, - * then all operations succeed. - */ -void test_printf_scanf() -{ - Loopback loop("loopback"); - int p_val, g_val, rc; - - p_val = 42; - g_val = p_val + 1; - rc = loop.printf(FMT, p_val); - TEST_ASSERT(rc > 0); - rc = loop.scanf(FMT, &g_val); - TEST_ASSERT(rc == 1); - TEST_ASSERT_EQUAL_INT(p_val, g_val); - - p_val += 5; - g_val = p_val + 1; - rc = loop.printf(FMT, p_val); - TEST_ASSERT(rc > 0); - rc = loop.scanf(FMT, &g_val); - TEST_ASSERT(rc == 1); - TEST_ASSERT_EQUAL_INT(p_val, g_val); -} - -/* Test intermixed Stream::vprintf() / Stream::vscanf(). - * - * Given a Stream object, - * when a write/read/write/read sequence is executed, - * with the use of Stream::vprintf() and Stream::vscanf() methods, - * then all operations succeed. - */ -void test_vprintf_vscanf() -{ - Loopback loop("loopback"); - int p_val, g_val, rc; - - p_val = 42; - g_val = p_val + 1; - rc = loop.test_vprintf(FMT, p_val); - TEST_ASSERT(rc > 0); - rc = loop.test_vscanf(FMT, &g_val); - TEST_ASSERT(rc == 1); - TEST_ASSERT_EQUAL_INT(p_val, g_val); - - p_val += 5; - g_val = p_val + 1; - rc = loop.test_vprintf(FMT, p_val); - TEST_ASSERT(rc > 0); - rc = loop.test_vscanf(FMT, &g_val); - TEST_ASSERT(rc == 1); - TEST_ASSERT_EQUAL_INT(p_val, g_val); -} - -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), - Case("Test puts/gets", test_puts_gets), - Case("Test printf/scanf", test_printf_scanf), - Case("Test vprintf/vscanf", test_vprintf_vscanf) -}; - -utest::v1::Specification specification(test_setup, cases); - -int main() -{ - return !utest::v1::Harness::run(specification); -} diff --git a/TESTS/mbed_platform/Transaction/main.cpp b/TESTS/mbed_platform/Transaction/main.cpp deleted file mode 100644 index 3b327d0..0000000 --- a/TESTS/mbed_platform/Transaction/main.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* mbed Microcontroller Library - * 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 "mbed.h" -#include "greentea-client/test_env.h" -#include "utest/utest.h" -#include "unity/unity.h" -#include "platform/Transaction.h" - -using utest::v1::Case; - -static void dummy_callback(int) -{ - /* do nothing. */ -} - -/** Test Transaction class - creation with initialisation - * - * Given is Transaction class. - * When object of the Transaction class is created and initialised. - * Then get_object() returns object's instance for the transaction and get_transaction() returns the transaction. - * - */ -template -void test_Transaction_init() -{ - Type object; - const size_t tx_buffer_size = 24; - const size_t rx_buffer_size = 16; - const uint32_t event_id = 123; - const uint8_t word_width = 8; - unsigned char tx_buffer[tx_buffer_size]; - unsigned char rx_buffer[rx_buffer_size]; - const event_callback_t &callback = dummy_callback; - transaction_t transaction_data = - { tx_buffer, tx_buffer_size, rx_buffer, rx_buffer_size, event_id, callback, word_width }; - - Transaction test_transaction(&object, transaction_data); - - TEST_ASSERT_EQUAL(&object, test_transaction.get_object()); - - TEST_ASSERT_EQUAL((void *)tx_buffer, test_transaction.get_transaction()->tx_buffer); - TEST_ASSERT_EQUAL((void *)rx_buffer, test_transaction.get_transaction()->rx_buffer); - TEST_ASSERT_EQUAL(tx_buffer_size, test_transaction.get_transaction()->tx_length); - TEST_ASSERT_EQUAL(rx_buffer_size, test_transaction.get_transaction()->rx_length); - TEST_ASSERT_EQUAL(event_id, test_transaction.get_transaction()->event); - TEST_ASSERT_EQUAL(word_width, test_transaction.get_transaction()->width); -#if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE - TEST_ASSERT_TRUE(callback == test_transaction.get_transaction()->callback); -#else - TEST_ASSERT_FALSE(nullptr == test_transaction.get_transaction()->callback) -#endif -} - -/** Test Transaction class - creation without initialisation - * - * Given is Transaction class. - * When object of the Transaction class is created. - * Then this operation is successful. - * - */ -template -void test_Transaction_empty() -{ - Type object; - - Transaction test_transaction; - - /* Just indicate successful execution of the test case. */ - TEST_ASSERT_TRUE(true); -} - -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 Transaction - init ", test_Transaction_init), - Case("Test Transaction - init ", test_Transaction_init), - Case("Test Transaction - no init ", test_Transaction_empty), - Case("Test Transaction - no init ", test_Transaction_empty), -}; - -utest::v1::Specification specification(test_setup, cases); - -int main() -{ - return !utest::v1::Harness::run(specification); -} diff --git a/TESTS/mbed_platform/atomic/main.cpp b/TESTS/mbed_platform/atomic/main.cpp deleted file mode 100644 index ed22373..0000000 --- a/TESTS/mbed_platform/atomic/main.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 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 "mbed.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest/utest.h" - -#include - -#if !MBED_CONF_RTOS_PRESENT -#error [NOT_SUPPORTED] test not supported -#else - -#define THREAD_STACK 512 - -using utest::v1::Case; - -namespace { - -using mstd::atomic; - -/* Lock-free operations will be much faster - keep runtime down */ -#define ADD_UNLOCKED_ITERATIONS (SystemCoreClock / 1000) -#define ADD_LOCKED_ITERATIONS (SystemCoreClock / 8000) - -template -static inline long add_iterations(A &a) -{ - return a.is_lock_free() ? ADD_UNLOCKED_ITERATIONS : ADD_LOCKED_ITERATIONS; -} - -template -struct add_incrementer { - static void op(A *ptr) - { - for (long i = add_iterations(*ptr); i > 0; i--) { - ++(*ptr); - } - } -}; - -template -struct add_release_incrementer { - static void op(A *ptr) - { - for (long i = add_iterations(*ptr); i > 0; i--) { - ptr->fetch_add(1, mstd::memory_order_release); - } - } -}; - -template -struct sub_incrementer { - static void op(A *ptr) - { - for (long i = add_iterations(*ptr); i > 0; i--) { - ptr->fetch_sub(-1); - } - } -}; - -template -struct bitops_incrementer { - static void op(A *ptr) - { - for (long i = add_iterations(*ptr); i > 0; i--) { - (*ptr) += 1; - (*ptr) &= -1; - (*ptr) |= 0; - } - } -}; - -template -struct weak_incrementer { - static void op(A *ptr) - { - for (long i = add_iterations(*ptr); i > 0; i--) { - typename A::value_type val = ptr->load(); - do { - } while (!ptr->compare_exchange_weak(val, val + 1)); - } - } -}; - -template -struct strong_incrementer { - static void op(A *ptr) - { - for (long i = add_iterations(*ptr); i > 0; i--) { - typename A::value_type val = ptr->load(); - do { - } while (!ptr->compare_exchange_strong(val, val + 1)); - } - } -}; - - - -/* - * Run multiple threads incrementing each data item - * ADD_ITERATIONS times, and at the end, check that - * each item is * ADD_ITERATIONS. - * Items are adjacent to catch any interference. - * - * Using core_util_atomic_ templates, and exercising - * load and store briefly. - */ -template class Fn> -void test_atomic_add() -{ - struct { - volatile T nonatomic1; - atomic atomic1; - volatile atomic atomic2; // use volatile just to exercise the templates' volatile methods - volatile T nonatomic2; - } data = { 0, { 0 }, { 1 }, 0 }; // test initialisation - - TEST_ASSERT_EQUAL(sizeof(T), sizeof data.nonatomic1); - TEST_ASSERT_EQUAL(sizeof(T), sizeof data.atomic1); - TEST_ASSERT_EQUAL(4 * sizeof(T), sizeof data); - - // test store - data.atomic2 = 0; - - Thread t1(osPriorityNormal, THREAD_STACK); - Thread t2(osPriorityNormal, THREAD_STACK); - Thread t3(osPriorityNormal, THREAD_STACK); - Thread t4(osPriorityNormal, THREAD_STACK); - - TEST_ASSERT_EQUAL(osOK, t1.start(callback(Fn::op, &data.atomic1))); - TEST_ASSERT_EQUAL(osOK, t2.start(callback(Fn::op, &data.atomic1))); - TEST_ASSERT_EQUAL(osOK, t3.start(callback(Fn::op, &data.atomic2))); - TEST_ASSERT_EQUAL(osOK, t4.start(callback(Fn::op, &data.atomic2))); - - for (long i = ADD_UNLOCKED_ITERATIONS; i > 0; i--) { - data.nonatomic1++; - data.nonatomic2++; - } - - t1.join(); - t2.join(); - t3.join(); - t4.join(); - - TEST_ASSERT_EQUAL(T(ADD_UNLOCKED_ITERATIONS), data.nonatomic1); - TEST_ASSERT_EQUAL(T(2 * add_iterations(data.atomic1)), data.atomic1); - TEST_ASSERT_EQUAL(T(2 * add_iterations(data.atomic2)), data.atomic2); - TEST_ASSERT_EQUAL(T(ADD_UNLOCKED_ITERATIONS), data.nonatomic2); -} - -// This should fit into a uint32_t container, and there -// will be 1 byte of padding to ignore. -struct small { - uint8_t a; - uint8_t b; - uint8_t c; -}; - -// An 11-byte weird structure. Should work with critical sections. -struct large { - uint8_t a; - uint8_t b; - uint8_t c; - uint8_t dummy[8]; -}; - -template -void struct_incrementer_a(A *data) -{ - for (long i = add_iterations(*data); i > 0; i--) { - typename A::value_type curval = *data, newval; - do { - newval = curval; - newval.a++; - } while (!data->compare_exchange_weak(curval, newval)); - } -} - -template -void struct_incrementer_b(A *data) -{ - for (long i = add_iterations(*data); i > 0; i--) { - typename A::value_type curval = *data, newval; - do { - newval = curval; - newval.b++; - } while (!data->compare_exchange_weak(curval, newval)); - } -} - -template -void test_atomic_struct() -{ - TEST_ASSERT_EQUAL(N, sizeof(atomic)); - - // Small structures don't have value constructor implemented; - atomic data; - atomic_init(&data, T{0, 0, 0}); - - Thread t1(osPriorityNormal, THREAD_STACK); - Thread t2(osPriorityNormal, THREAD_STACK); - - TEST_ASSERT_EQUAL(osOK, t1.start(callback(struct_incrementer_a >, &data))); - TEST_ASSERT_EQUAL(osOK, t2.start(callback(struct_incrementer_b >, &data))); - - for (long i = add_iterations(data); i > 0; i--) { - T curval = data, newval; - do { - newval = curval; - newval.c++; - } while (!data.compare_exchange_weak(curval, newval)); - } - - t1.join(); - t2.join(); - - T final_val = data; - - TEST_ASSERT_EQUAL(uint8_t(add_iterations(data)), final_val.a); - TEST_ASSERT_EQUAL(uint8_t(add_iterations(data)), final_val.b); - TEST_ASSERT_EQUAL(uint8_t(add_iterations(data)), final_val.c); -} - -} // namespace - -utest::v1::status_t test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(60, "default_auto"); - return utest::v1::verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("Test atomic add 8-bit", test_atomic_add), - Case("Test atomic add 16-bit", test_atomic_add), - Case("Test atomic add 32-bit", test_atomic_add), - Case("Test atomic add 64-bit", test_atomic_add), - Case("Test atomic add signed 8-bit", test_atomic_add), - Case("Test atomic add signed 16-bit", test_atomic_add), - Case("Test atomic add signed 32-bit", test_atomic_add), - Case("Test atomic add signed 64-bit", test_atomic_add), - Case("Test atomic add release 32-bit", test_atomic_add), - Case("Test atomic sub 8-bit", test_atomic_add), - Case("Test atomic sub 16-bit", test_atomic_add), - Case("Test atomic sub 32-bit", test_atomic_add), - Case("Test atomic sub 64-bit", test_atomic_add), - Case("Test atomic bitops 8-bit", test_atomic_add), - Case("Test atomic bitops 16-bit", test_atomic_add), - Case("Test atomic bitops 32-bit", test_atomic_add), - Case("Test atomic bitops 64-bit", test_atomic_add), - Case("Test atomic compare exchange weak 8-bit", test_atomic_add), - Case("Test atomic compare exchange weak 16-bit", test_atomic_add), - Case("Test atomic compare exchange weak 32-bit", test_atomic_add), - Case("Test atomic compare exchange weak 64-bit", test_atomic_add), - Case("Test atomic compare exchange strong 8-bit", test_atomic_add), - Case("Test atomic compare exchange strong 16-bit", test_atomic_add), - Case("Test atomic compare exchange strong 32-bit", test_atomic_add), - Case("Test atomic compare exchange strong 64-bit", test_atomic_add), - Case("Test small atomic custom structure", test_atomic_struct), - Case("Test large atomic custom structure", test_atomic_struct) -}; - -utest::v1::Specification specification(test_setup, cases); - -int main() -{ - return !utest::v1::Harness::run(specification); -} - -#endif // !MBED_CONF_RTOS_PRESENT diff --git a/TESTS/mbed_platform/crash_reporting/main.cpp b/TESTS/mbed_platform/crash_reporting/main.cpp deleted file mode 100644 index 5f93f73..0000000 --- a/TESTS/mbed_platform/crash_reporting/main.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* mbed Microcontroller Library - * 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 "mbed.h" -#include "mbed_error.h" -#include "mbed_crash_data_offsets.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" - -#if !MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED -#error [NOT_SUPPORTED] crash_reporting test not supported -#else - -#define MSG_VALUE_DUMMY "0" -#define MSG_VALUE_LEN 32 -#define MSG_KEY_LEN 64 - -#define MSG_KEY_DEVICE_READY "crash_reporting_ready" -#define MSG_KEY_DEVICE_ERROR "crash_reporting_inject_error" - -static mbed_error_ctx saved_error_ctx = {0}; - -void mbed_error_reboot_callback(mbed_error_ctx *error_context) -{ - - TEST_ASSERT_EQUAL_PTR(error_context, &MBED_CRASH_DATA); - memcpy(&saved_error_ctx, error_context, sizeof(mbed_error_ctx)); - mbed_reset_reboot_error_info(); - - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_OUT_OF_MEMORY, saved_error_ctx.error_status); - TEST_ASSERT_EQUAL_UINT(1, saved_error_ctx.error_reboot_count); - - //Send the ready msg to host to indicate test pass - greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_DUMMY); -} - -void test_crash_reporting() -{ - //Clear any previous status - mbed_reset_reboot_error_info(); - - // Report readiness - greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_DUMMY); - printf("\nMessage sent: %s\n", MSG_KEY_DEVICE_READY); - - static char _key[MSG_KEY_LEN + 1] = { }; - static char _value[MSG_VALUE_LEN + 1] = { }; - - printf("\nWaiting for crash inject error message: %s\n", MSG_KEY_DEVICE_ERROR); - greentea_parse_kv(_key, _value, MSG_KEY_LEN, MSG_VALUE_LEN); - printf("\nCrash inject error message received\n"); - - if (strcmp(_key, MSG_KEY_DEVICE_ERROR) == 0) { - printf("\nForcing error\n"); - MBED_ERROR1(MBED_ERROR_OUT_OF_MEMORY, "Executing crash reporting test.", 0xDEADBAD); - TEST_ASSERT_MESSAGE(0, "crash_reporting() error call failed."); - } - TEST_ASSERT_MESSAGE(0, "Unexpected message received."); -} - -int main(void) -{ - GREENTEA_SETUP(40, "crash_reporting"); - test_crash_reporting(); - GREENTEA_TESTSUITE_RESULT(0); - - return 0; -} - -#endif // !MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED diff --git a/TESTS/mbed_platform/critical_section/main.cpp b/TESTS/mbed_platform/critical_section/main.cpp deleted file mode 100644 index 0fec9d1..0000000 --- a/TESTS/mbed_platform/critical_section/main.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 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 "mbed.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest/utest.h" - - -using utest::v1::Case; - - -bool callback_called; - -void tiemout_callback(void) -{ - core_util_atomic_store(&callback_called, true); -} - -template -void critical_section_raii_recursive(Timeout &timeout) -{ - static uint32_t depth = 0; - CriticalSectionLock cs; - - depth++; - TEST_ASSERT_TRUE(core_util_in_critical_section()); - - if (depth < N) { - critical_section_raii_recursive(timeout); - } else { - // max depth reached - do the test - const us_timestamp_t timeout_time_us = 1; - const int wait_time_us = timeout_time_us * 100; - - timeout.attach_us(callback(tiemout_callback), timeout_time_us); - wait_us(wait_time_us); - } - TEST_ASSERT_TRUE(core_util_in_critical_section()); - TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called)); -} - - -/** Template for tests - - Test C API of critical section - Given a Timeout with callback attached - When before critical section - Then interrupts are enabled and timeout callback is fired - When inside critical section - Then interrupts are disabled and timeout callback is blocked - When after critical section - Then interrupts are enabled and timeout callback is fired - - Test C API of critical section - nested lock - Given a Timeout with callback attached - When before critical section - Then interrupts are enabled and timeout callback is fired - When inside nested critical section - Then interrupts are disabled and timeout callback is blocked - When after critical section - Then interrupts are enabled and timeout callback is fired - */ -template -void test_C_API(void) -{ - Timeout timeout; - const us_timestamp_t timeout_time_us = 1; - const int wait_time_us = timeout_time_us * 100; - - TEST_ASSERT_FALSE(core_util_in_critical_section()); - - core_util_atomic_store(&callback_called, false); - timeout.attach_us(callback(tiemout_callback), timeout_time_us); - wait_us(wait_time_us); - TEST_ASSERT_TRUE(core_util_atomic_exchange(&callback_called, false)); - - for (int i = 0; i < N; i++) { - core_util_critical_section_enter(); - TEST_ASSERT_TRUE(core_util_in_critical_section()); - } - - timeout.attach_us(callback(tiemout_callback), timeout_time_us); - wait_us(wait_time_us); - TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called)); - TEST_ASSERT_TRUE(core_util_in_critical_section()); - - for (int i = 0; i < N - 1; i++) { - core_util_critical_section_exit(); - TEST_ASSERT_TRUE(core_util_in_critical_section()); - TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called)); - } - - core_util_critical_section_exit(); - TEST_ASSERT_FALSE(core_util_in_critical_section()); - TEST_ASSERT_TRUE(core_util_atomic_load(&callback_called)); -} - -/** Template for tests - - Test C++ API of critical section constructor/destructor - Given a Timeout with callback attached - When before critical section - Then interrupts are enabled and timeout callback is fired - When inside critical section - Then interrupts are disabled and timeout callback is blocked - When after critical section - Then interrupts are enabled and timeout callback is fired - - Test C++ API of critical section constructor/destructor - nested lock - Given a Timeout with callback attached - When before critical section - Then interrupts are enabled and timeout callback is fired - When inside nested critical section - Then interrupts are disabled and timeout callback is blocked - When after critical section - Then interrupts are enabled and timeout callback is fired - */ -template -void test_CPP_API_constructor_destructor(void) -{ - Timeout timeout; - const us_timestamp_t timeout_time_us = 1; - const int wait_time_us = timeout_time_us * 100; - - TEST_ASSERT_FALSE(core_util_in_critical_section()); - - core_util_atomic_store(&callback_called, false); - timeout.attach_us(callback(tiemout_callback), timeout_time_us); - wait_us(wait_time_us); - TEST_ASSERT_TRUE(core_util_atomic_exchange(&callback_called, false)); - - critical_section_raii_recursive(timeout); - - TEST_ASSERT_FALSE(core_util_in_critical_section()); - TEST_ASSERT_TRUE(core_util_atomic_load(&callback_called)); -} - -/** Template for tests - - Test C++ API of critical section enable/disable - Given a Timeout with attached callback - When before critical section - Then interrupts are enabled and timeout callback is fired - When inside critical section - Then interrupts are disabled and timeout callback is blocked - When after critical section - Then interrupts are enabled and timeout callback is fired - - Test C++ API of critical section enable/disable - nested lock - Given a Timeout with attached callback - When before critical section - Then interrupts are enabled and timeout callback is fired - When inside nested critical section - Then interrupts are disabled and timeout callback is blocked - When after critical section - Then interrupts are enabled and timeout callback is fired - */ -template -void test_CPP_API_enable_disable(void) -{ - Timeout timeout; - const us_timestamp_t timeout_time_us = 1; - const int wait_time_us = timeout_time_us * 100; - - TEST_ASSERT_FALSE(core_util_in_critical_section()); - - core_util_atomic_store(&callback_called, false); - timeout.attach_us(callback(tiemout_callback), timeout_time_us); - wait_us(wait_time_us); - TEST_ASSERT_TRUE(core_util_atomic_exchange(&callback_called, false)); - - for (int i = 0; i < N; i++) { - CriticalSectionLock::enable(); - TEST_ASSERT_TRUE(core_util_in_critical_section()); - } - - timeout.attach_us(callback(tiemout_callback), timeout_time_us); - wait_us(wait_time_us); - TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called)); - TEST_ASSERT_TRUE(core_util_in_critical_section()); - - for (int i = 0; i < N - 1; i++) { - CriticalSectionLock::disable(); - TEST_ASSERT_TRUE(core_util_in_critical_section()); - TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called)); - } - - CriticalSectionLock::disable(); - TEST_ASSERT_FALSE(core_util_in_critical_section()); - TEST_ASSERT_TRUE(core_util_atomic_load(&callback_called)); -} - - -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 critical section C API", test_C_API<1>), - Case("Test critical section C API nested lock", test_C_API<10>), - Case("Test critical section C++ API constructor/destructor", test_CPP_API_constructor_destructor<1>), - Case("Test critical section C++ API constructor/destructor nested lock", test_CPP_API_constructor_destructor<10>), - Case("Test critical section C++ API enable/disable", test_CPP_API_enable_disable<1>), - Case("Test critical section C++ API enable/disable nested lock", test_CPP_API_enable_disable<10>) -}; - -utest::v1::Specification specification(test_setup, cases); - -int main() -{ - return !utest::v1::Harness::run(specification); -} diff --git a/TESTS/mbed_platform/error_handling/main.cpp b/TESTS/mbed_platform/error_handling/main.cpp deleted file mode 100644 index cb97eb0..0000000 --- a/TESTS/mbed_platform/error_handling/main.cpp +++ /dev/null @@ -1,380 +0,0 @@ -/* mbed Microcontroller Library - * 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 "greentea-client/test_env.h" -#include "utest/utest.h" -#include "unity/unity.h" -#include "mbed.h" -#include -#include "HeapBlockDevice.h" - -using utest::v1::Case; - -/** Test error count and reset functionality - */ -void test_error_count_and_reset() -{ - int count = 7; - - //Log multiple errors and get the error count and make sure its 15 - for (int i = 0; i < count; i++) { - MBED_WARNING1(MBED_ERROR_OUT_OF_MEMORY, "Out of memory", i); - } - - TEST_ASSERT_EQUAL_INT(count, mbed_get_error_count()); - - //clear the errors and error count to 0 - mbed_clear_all_errors(); - - //Now the error count should be 0 - TEST_ASSERT_EQUAL_INT(0, mbed_get_error_count()); - -} - -/** Test error type encoding and test capturing of system, custom, posix errors - * and ensure the status/error code/type/error value is correct - */ -void test_error_capturing() -{ - uint32_t error_value = 0xAA11BB22; - mbed_error_ctx error_ctx = {0}; - - //first clear all errors and start afresh - - MBED_WARNING1(MBED_ERROR_OUT_OF_RESOURCES, "System type error", 0x1100); - mbed_error_status_t lastError = mbed_get_last_error(); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_TYPE_SYSTEM, MBED_GET_ERROR_TYPE(lastError)); - TEST_ASSERT_EQUAL_UINT(MBED_MODULE_UNKNOWN, MBED_GET_ERROR_MODULE(lastError)); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_CODE_OUT_OF_RESOURCES, MBED_GET_ERROR_CODE(lastError)); - - mbed_error_status_t error = MBED_MAKE_ERROR(MBED_MODULE_DRIVER_SERIAL, MBED_ERROR_CODE_OUT_OF_RESOURCES); - MBED_WARNING1(error, "Error Serial", 0xAA); - lastError = mbed_get_last_error(); - TEST_ASSERT_EQUAL_UINT(error, lastError); - - error = MBED_MAKE_CUSTOM_ERROR(MBED_MODULE_APPLICATION, MBED_ERROR_CODE_UNKNOWN); - MBED_WARNING1(error, "Custom Error Unknown", 0x1234); - lastError = mbed_get_last_error(); - TEST_ASSERT_EQUAL_UINT(error, lastError); - - MBED_WARNING1(MBED_ERROR_EPERM, "Posix Error Eperm", 0x1234); - lastError = mbed_get_last_error(); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_EPERM, lastError); - - error = MBED_MAKE_CUSTOM_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_CREATE_FAILED); - MBED_WARNING1(error, "Custom Error Type", error_value); - lastError = mbed_get_last_error(); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_TYPE_CUSTOM, MBED_GET_ERROR_TYPE(lastError)); - TEST_ASSERT_EQUAL_UINT(MBED_MODULE_PLATFORM, MBED_GET_ERROR_MODULE(lastError)); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_CODE_CREATE_FAILED, MBED_GET_ERROR_CODE(lastError)); - mbed_error_status_t status = mbed_get_last_error_info(&error_ctx); - TEST_ASSERT(status == MBED_SUCCESS); - TEST_ASSERT_EQUAL_UINT(error_value, error_ctx.error_value); - - error_value = 0xAABBCC; - MBED_WARNING1(MBED_ERROR_EACCES, "Posix Error", error_value); - lastError = mbed_get_last_error(); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_TYPE_POSIX, MBED_GET_ERROR_TYPE(lastError)); - TEST_ASSERT_EQUAL_UINT(MBED_MODULE_UNKNOWN, MBED_GET_ERROR_MODULE(lastError)); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_CODE_EACCES, MBED_GET_ERROR_CODE(lastError)); - status = mbed_get_last_error_info(&error_ctx); - TEST_ASSERT(status == MBED_SUCCESS); - TEST_ASSERT_EQUAL_UINT(error_value, error_ctx.error_value); - - error_value = 0; - error = MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_UNKNOWN); - MBED_WARNING1(error, "HAL Entity error", error_value); - lastError = mbed_get_last_error(); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_TYPE_SYSTEM, MBED_GET_ERROR_TYPE(lastError)); - TEST_ASSERT_EQUAL_UINT(MBED_MODULE_HAL, MBED_GET_ERROR_MODULE(lastError)); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_CODE_UNKNOWN, MBED_GET_ERROR_CODE(lastError)); - status = mbed_get_last_error_info(&error_ctx); - TEST_ASSERT(status == MBED_SUCCESS); - TEST_ASSERT_EQUAL_UINT(error_value, error_ctx.error_value); - - MBED_WARNING1(MBED_ERROR_MUTEX_LOCK_FAILED, "Mutex lock failed", 0x4455); - error = mbed_get_last_error(); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_MUTEX_LOCK_FAILED, error); - - error = mbed_get_first_error(); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_OUT_OF_RESOURCES, error); - -} - -/** Test error context capture - */ -void test_error_context_capture() -{ - uint32_t error_value = 0xABCD; - mbed_error_ctx error_ctx = {0}; - - MBED_WARNING1(MBED_ERROR_INVALID_ARGUMENT, "System type error", error_value); - mbed_error_status_t status = mbed_get_last_error_info(&error_ctx); - TEST_ASSERT(status == MBED_SUCCESS); - TEST_ASSERT_EQUAL_UINT(error_value, error_ctx.error_value); -#if defined(MBED_CONF_RTOS_PRESENT) - TEST_ASSERT_EQUAL_UINT((uint32_t)osThreadGetId(), error_ctx.thread_id); - - //Capture thread info and compare - osRtxThread_t *current_thread = osRtxInfo.thread.run.curr; - TEST_ASSERT_EQUAL_UINT((uint32_t)current_thread->thread_addr, error_ctx.thread_entry_address); - TEST_ASSERT_EQUAL_UINT((uint32_t)current_thread->stack_size, error_ctx.thread_stack_size); - TEST_ASSERT_EQUAL_UINT((uint32_t)current_thread->stack_mem, error_ctx.thread_stack_mem); -#if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED - TEST_ASSERT_EQUAL_STRING(MBED_FILENAME, error_ctx.error_filename); -#endif -#endif -} - -#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED -/** Test error logging functionality - */ -void test_error_logging() -{ - mbed_error_ctx error_ctx = {0}; - - //clear the current errors first - mbed_clear_all_errors(); - - //log 3 errors and retrieve them to ensure they are correct - MBED_WARNING1(MBED_ERROR_INVALID_ARGUMENT, "Invalid argument", 1); - MBED_WARNING1(MBED_ERROR_INVALID_SIZE, "Invalid size", 2); - MBED_WARNING1(MBED_ERROR_INVALID_FORMAT, "Invalid format", 3); - - mbed_error_status_t status = mbed_get_error_hist_info(0, &error_ctx); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_INVALID_ARGUMENT, error_ctx.error_status); - TEST_ASSERT_EQUAL_UINT(1, error_ctx.error_value); - - status = mbed_get_error_hist_info(1, &error_ctx); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_INVALID_SIZE, error_ctx.error_status); - TEST_ASSERT_EQUAL_UINT(2, error_ctx.error_value); - - status = mbed_get_error_hist_info(2, &error_ctx); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_INVALID_FORMAT, error_ctx.error_status); - TEST_ASSERT_EQUAL_UINT(3, error_ctx.error_value); - - //Log a bunch of errors to overflow the error log and retrieve them - MBED_WARNING1(MBED_ERROR_INVALID_ARGUMENT, "Invalid argument", 6); - MBED_WARNING1(MBED_ERROR_INVALID_SIZE, "Invalid size", 7); - MBED_WARNING1(MBED_ERROR_INVALID_FORMAT, "Invalid format", 8); - MBED_WARNING1(MBED_ERROR_NOT_READY, "Not ready error", 9); - - //Last 4 entries - MBED_WARNING1(MBED_ERROR_TIME_OUT, "Timeout error", 10); - MBED_WARNING1(MBED_ERROR_ALREADY_IN_USE, "Already in use error", 11); - MBED_WARNING1(MBED_ERROR_UNSUPPORTED, "Not supported", 12); - MBED_WARNING1(MBED_ERROR_ACCESS_DENIED, "Access denied", 13); - - status = mbed_get_error_hist_info(0, &error_ctx); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_TIME_OUT, error_ctx.error_status); - TEST_ASSERT_EQUAL_UINT(10, error_ctx.error_value); - - status = mbed_get_error_hist_info(1, &error_ctx); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_ALREADY_IN_USE, error_ctx.error_status); - TEST_ASSERT_EQUAL_UINT(11, error_ctx.error_value); - - status = mbed_get_error_hist_info(2, &error_ctx); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_UNSUPPORTED, error_ctx.error_status); - TEST_ASSERT_EQUAL_UINT(12, error_ctx.error_value); - - status = mbed_get_error_hist_info(3, &error_ctx); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_ACCESS_DENIED, error_ctx.error_status); - TEST_ASSERT_EQUAL_UINT(13, error_ctx.error_value); - - //Try an index which is invalid, we should get ERROR_INVALID_ARGUMENT back - status = mbed_get_error_hist_info(99, &error_ctx); - TEST_ASSERT_EQUAL_UINT(MBED_ERROR_INVALID_ARGUMENT, status); - -} - -#define NUM_TEST_THREADS 5 -#define THREAD_STACK_SIZE 512 - -//Error logger threads -void err_thread_func(mbed_error_status_t *error_status) -{ - MBED_WARNING1(*error_status, "Error from Multi-Threaded error logging test", *error_status); -} - - -/** Test error logging multithreaded - */ -void test_error_logging_multithread() -{ - uint8_t *dummy = new (std::nothrow) uint8_t[NUM_TEST_THREADS * THREAD_STACK_SIZE]; - TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory for test"); - delete[] dummy; - - mbed_error_ctx error_ctx = {0}; - int i; - Thread *errThread[NUM_TEST_THREADS]; - mbed_error_status_t error_status[NUM_TEST_THREADS] = { - MBED_ERROR_INVALID_ARGUMENT, MBED_ERROR_INVALID_DATA_DETECTED, MBED_ERROR_INVALID_FORMAT, MBED_ERROR_INVALID_SIZE, MBED_ERROR_INVALID_OPERATION - }; - - - for (i = 0; i < NUM_TEST_THREADS; i++) { - errThread[i] = new Thread(osPriorityNormal1, THREAD_STACK_SIZE, NULL, NULL); - errThread[i]->start(callback(err_thread_func, &error_status[i])); - } - ThisThread::sleep_for(2000); - for (i = 0; i < NUM_TEST_THREADS; i++) { - errThread[i]->join(); - } - - i = mbed_get_error_hist_count() - 1; - - for (; i >= 0; --i) { - mbed_error_status_t status = mbed_get_error_hist_info(i, &error_ctx); - if (status != MBED_SUCCESS) { - TEST_FAIL(); - } - - TEST_ASSERT_EQUAL_UINT((unsigned int)error_ctx.error_value, (unsigned int)error_ctx.error_status); - } -} -#endif - -#if defined(MBED_CONF_RTOS_PRESENT) -static Semaphore callback_sem; -void MyErrorHook(const mbed_error_ctx *error_ctx) -{ - callback_sem.release(); -} -#endif - -/** Test error hook - */ -#if defined(MBED_CONF_RTOS_PRESENT) -void test_error_hook() -{ - if (MBED_SUCCESS != mbed_set_error_hook(MyErrorHook)) { - TEST_FAIL(); - } - - MBED_WARNING1(MBED_ERROR_INVALID_ARGUMENT, "Test for error hook", 1234); - bool acquired = callback_sem.try_acquire_for(5000); - - TEST_ASSERT(acquired); -} -#endif - -#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED && defined(MBED_TEST_SIM_BLOCKDEVICE) - -// test configuration -#ifndef MBED_TEST_FILESYSTEM -#define MBED_TEST_FILESYSTEM LittleFileSystem -#endif - -#ifndef MBED_TEST_FILESYSTEM_DECL -#define MBED_TEST_FILESYSTEM_DECL MBED_TEST_FILESYSTEM fs("fs") -#endif - -#ifndef MBED_TEST_BLOCK_COUNT -#define MBED_TEST_BLOCK_COUNT 64 -#endif - -#ifndef MBED_TEST_SIM_BLOCKDEVICE_DECL -#define MBED_TEST_SIM_BLOCKDEVICE_DECL MBED_TEST_SIM_BLOCKDEVICE fd(MBED_TEST_BLOCK_COUNT*512, 1, 1, 512) -#endif - -// declarations -#define STRINGIZE(x) STRINGIZE2(x) -#define STRINGIZE2(x) #x -#define INCLUDE(x) STRINGIZE(x.h) - -#include INCLUDE(MBED_TEST_FILESYSTEM) -#include INCLUDE(MBED_TEST_SIM_BLOCKDEVICE) - -MBED_TEST_FILESYSTEM_DECL; -MBED_TEST_SIM_BLOCKDEVICE_DECL; - -/** Test save error log - */ -void test_save_error_log() -{ - //Log some errors - MBED_WARNING1(MBED_ERROR_TIME_OUT, "Timeout error", 1); - MBED_WARNING1(MBED_ERROR_ALREADY_IN_USE, "Already in use error", 2); - MBED_WARNING1(MBED_ERROR_UNSUPPORTED, "Not supported error", 3); - MBED_WARNING1(MBED_ERROR_ACCESS_DENIED, "Access denied error", 4); - MBED_WARNING1(MBED_ERROR_ITEM_NOT_FOUND, "Not found error", 5); - - int error = 0; - - error = MBED_TEST_FILESYSTEM::format(&fd); - if (error < 0) { - TEST_FAIL_MESSAGE("Failed formatting"); - } - - error = fs.mount(&fd); - if (error < 0) { - TEST_FAIL_MESSAGE("Failed mounting fs"); - } - - if (MBED_SUCCESS != mbed_save_error_hist("/fs/errors.log")) { - TEST_FAIL_MESSAGE("Failed saving error log"); - } - - FILE *error_file = fopen("/fs/errors.log", "r"); - if (error_file == NULL) { - TEST_FAIL_MESSAGE("Unable to find error log in fs"); - } - - char buff[64] = {0}; - while (!feof(error_file)) { - int size = fread(&buff[0], 1, 15, error_file); - fwrite(&buff[0], 1, size, stdout); - } - fclose(error_file); - - error = fs.unmount(); - if (error < 0) { - TEST_FAIL_MESSAGE("Failed unmounting fs"); - } -} - -#endif - -utest::v1::status_t test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(120, "default_auto"); - return utest::v1::verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("Test error counting and reset", test_error_count_and_reset), - Case("Test error encoding, value capture, first and last errors", test_error_capturing), - Case("Test error context capture", test_error_context_capture), -#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED - Case("Test error logging", test_error_logging), -#if MBED_CONF_RTOS_PRESENT - Case("Test error hook", test_error_hook), - Case("Test error handling multi-threaded", test_error_logging_multithread), -#endif //MBED_CONF_RTOS_PRESENT -#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED && defined(MBED_TEST_SIM_BLOCKDEVICE) - Case("Test error save log", test_save_error_log), -#endif //MBED_TEST_SIM_BLOCKDEVICE -#endif //MBED_CONF_ERROR_HIST_DISABLED -}; - -utest::v1::Specification specification(test_setup, cases); - -int main() -{ - return !utest::v1::Harness::run(specification); -} diff --git a/TESTS/mbed_platform/minimal-printf/compliance/README.md b/TESTS/mbed_platform/minimal-printf/compliance/README.md deleted file mode 100644 index 32c038e..0000000 --- a/TESTS/mbed_platform/minimal-printf/compliance/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Description - -This document describes how to run minimal-printf tests. - -## Running tests - -You can use the following command to run tests: - -`mbed test -m K64F -t GCC_ARM -n *printf* -v -c --app-config TESTS/mbed_platform/minimal-printf/compliance/test_config.json` diff --git a/TESTS/mbed_platform/minimal-printf/compliance/main.cpp b/TESTS/mbed_platform/minimal-printf/compliance/main.cpp deleted file mode 100644 index 1633ddc..0000000 --- a/TESTS/mbed_platform/minimal-printf/compliance/main.cpp +++ /dev/null @@ -1,1095 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 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. - */ - -#ifdef TARGET_LIKE_MBED -#include "mbed.h" -#endif -#include "mbed_printf.h" - -#include "utest/utest.h" -#include "unity/unity.h" -#include "greentea-client/test_env.h" - -#include -#include -#include -#include - -#ifndef ULLONG_MAX -#define ULLONG_MAX UINT64_MAX -#endif - -#ifndef LLONG_MAX -#define LLONG_MAX INT64_MAX -#endif - -#ifndef LLONG_MIN -#define LLONG_MIN INT64_MIN -#endif - -using namespace utest::v1; - -#define MAX_STRING_SIZE 100 -// Buffer used by test cases to store a test string -static char expected_string[MAX_STRING_SIZE]; - -#define BASE_10 10 -#define BASE_16 16 - -/** This function converts an integer into a string representing the integer in base 10 or base 16. - * - * @param value to be converted to a string. - * @param str is an array where to store the resulting null-terminated string. - * @param base used to represent the string. - * - * @return - * A pointer to the resulting null-terminated string, same as parameter str. - */ -static char *convert_to_string( - uint64_t value, - char str[], - int base = BASE_10, - bool is_negative = false) -{ - int i = 0; - - if (base != BASE_10 && base != BASE_16) { - MBED_ASSERT(0); - } - - if (value == 0) { - str[0] = '0'; - str[1] = '\0'; - return str; - } - - if (is_negative && ((long long) value < 0)) { - value = -value; - } - // Convert a value to a string stored in reverse order in memory. - while (value) { - int remainder = value % base; - str[i++] = (remainder > 9) ? (remainder - 10) + 'A' : remainder + '0'; - value = value / base; - } - - if (is_negative) { - str[i++] = '-'; - } - - str[i] = '\0'; - - // Reverse the string. - int start = 0; - int end = i - 1; - while (start < end) { - swap(*(str + start), *(str + end)); - start++; - end--; - } - return str; -} - -/** This function is using a global buffer to build the test string 'prefix + data + suffix' and - * returns its length. - * - * @param prefix is a null-terminated string. - * @param value to be converted to a string. - * @param base used to represent the string. - * @param suffix is a null-terminated string. - * @param is_negative is used to represent a positive or negative value - * - * @return - * string length - */ -static int make_test_string( - const char *prefix = nullptr, - long long value = 0, - int base = BASE_10, - const char *suffix = nullptr, - bool is_negative = false -) -{ - char *exp_str = &expected_string[0]; - int str_length = 0; - memset(exp_str, 0, MAX_STRING_SIZE); - if (prefix) { - str_length = strlen(prefix); - MBED_ASSERT(str_length < MAX_STRING_SIZE); - strncpy(exp_str, prefix, str_length); - } - - convert_to_string(value, &exp_str[str_length], base, is_negative); - if (suffix) { - str_length = strlen(exp_str); - MBED_ASSERT(strlen(suffix) < (MAX_STRING_SIZE - str_length)); - strncat(exp_str, suffix, str_length); - } - return strlen(exp_str); -} - -// Extract the prefix string which is all characters until '%'. -static void extract_prefix(const char *fmt, char *prefix) -{ - int i = 0; - while (fmt && prefix && fmt[i] != '%') { - prefix[i] = fmt[i]; - i++; - } -} - -static control_t test_printf_d(const size_t call_count) -{ - int result_baseline; - int result_minimal; - int result_file; - - /*************************************************************************/ - /*************************************************************************/ - result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MIN); - result_file = mbed_fprintf(stderr, "hhd: %hhd\r\n", SCHAR_MIN); - result_baseline = make_test_string("hhd: ", SCHAR_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MAX); - result_file = mbed_fprintf(stderr, "hhd: %hhd\r\n", SCHAR_MAX); - result_baseline = make_test_string("hhd: ", SCHAR_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MIN); - result_file = mbed_fprintf(stderr, "hd: %hd\r\n", SHRT_MIN); - result_baseline = make_test_string("hd: ", SHRT_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MAX); - result_file = mbed_fprintf(stderr, "hd: %hd\r\n", SHRT_MAX); - result_baseline = make_test_string("hd: ", SHRT_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("d: %d\r\n", INT_MIN); - result_file = mbed_fprintf(stderr, "d: %d\r\n", INT_MIN); - result_baseline = make_test_string("d: ", INT_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("d: %d\r\n", INT_MAX); - result_file = mbed_fprintf(stderr, "d: %d\r\n", INT_MAX); - result_baseline = make_test_string("d: ", INT_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("ld: %ld\r\n", LONG_MIN); - result_file = mbed_fprintf(stderr, "ld: %ld\r\n", LONG_MIN); - result_baseline = make_test_string("ld: ", LONG_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("ld: %ld\r\n", LONG_MAX); - result_file = mbed_fprintf(stderr, "ld: %ld\r\n", LONG_MAX); - result_baseline = make_test_string("ld: ", LONG_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MIN); - result_file = mbed_fprintf(stderr, "lld: %lld\r\n", LLONG_MIN); - result_baseline = make_test_string("lld: ", LLONG_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MAX); - result_file = mbed_fprintf(stderr, "lld: %lld\r\n", LLONG_MAX); - result_baseline = make_test_string("lld: ", LLONG_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - -#ifdef TARGET_LIKE_MBED - printf("%%jd not supported by mbed\r\n"); -#else - result_minimal = mbed_printf("jd: %jd\r\n", INT32_MIN); - result_file = mbed_fprintf(stderr, "jd: %jd\r\n", INT32_MIN); - result_baseline = make_test_string("jd: ", (intmax_t) INT32_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("jd: %jd\r\n", INT32_MAX); - result_file = mbed_fprintf(stderr, "jd: %jd\r\n", INT32_MAX); - result_baseline = make_test_string("jd: ", (intmax_t) INT32_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%zd not supported by mbed\r\n"); -#else - result_minimal = mbed_printf("zd: %zd\r\n", INT32_MIN); - result_file = mbed_fprintf(stderr, "zd: %zd\r\n", INT32_MIN); - result_baseline = make_test_string("zd: ", (ssize_t) INT32_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("zd: %zd\r\n", INT32_MAX); - result_file = mbed_fprintf(stderr, "zd: %zd\r\n", INT32_MAX); - result_baseline = make_test_string("zd: ", (ssize_t) INT32_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%td not supported by mbed\r\n"); -#else - result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MIN); - result_file = mbed_fprintf(stderr, "td: %td\r\n", PTRDIFF_MIN); - result_baseline = make_test_string("td: ", PTRDIFF_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MAX); - result_file = mbed_fprintf(stderr, "td: %td\r\n", PTRDIFF_MAX); - result_baseline = make_test_string("td: ", PTRDIFF_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); -#endif - - return CaseNext; -} - -static control_t test_printf_u(const size_t call_count) -{ - int result_baseline; - int result_minimal; - int result_file; - - /*************************************************************************/ - /*************************************************************************/ - result_minimal = mbed_printf("hhu: %hhu\r\n", 0); - result_file = mbed_fprintf(stderr, "hhu: %hhu\r\n", 0); - result_baseline = make_test_string("hhu: ", 0, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("hhu: %hhu\r\n", UCHAR_MAX); - result_file = mbed_fprintf(stderr, "hhu: %hhu\r\n", UCHAR_MAX); - result_baseline = make_test_string("hhu: ", UCHAR_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("hu: %hu\r\n", 0); - result_file = mbed_fprintf(stderr, "hu: %hu\r\n", 0); - result_baseline = make_test_string("hu: ", 0, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("hu: %hu\r\n", USHRT_MAX); - result_file = mbed_fprintf(stderr, "hu: %hu\r\n", USHRT_MAX); - result_baseline = make_test_string("hu: ", USHRT_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("u: %u\r\n", 0); - result_file = mbed_fprintf(stderr, "u: %u\r\n", 0); - result_baseline = make_test_string("u: ", 0, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("u: %u\r\n", UINT_MAX); - result_file = mbed_fprintf(stderr, "u: %u\r\n", UINT_MAX); - result_baseline = make_test_string("u: ", UINT_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("lu: %lu\r\n", 0UL); - result_file = mbed_fprintf(stderr, "lu: %lu\r\n", 0UL); - result_baseline = make_test_string("lu: ", 0UL, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("lu: %lu\r\n", ULONG_MAX); - result_file = mbed_fprintf(stderr, "lu: %lu\r\n", ULONG_MAX); - result_baseline = make_test_string("lu: ", ULONG_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("llu: %llu\r\n", 0ULL); - result_file = mbed_fprintf(stderr, "llu: %llu\r\n", 0ULL); - result_baseline = make_test_string("llu: ", 0ULL, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("llu: %llu\r\n", ULLONG_MAX); - result_file = mbed_fprintf(stderr, "llu: %llu\r\n", ULLONG_MAX); - result_baseline = make_test_string("llu: ", ULLONG_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - -#ifdef TARGET_LIKE_MBED - printf("%%ju not supported by mbed\r\n"); -#else - result_minimal = mbed_printf("ju: %ju\r\n", (uintmax_t) 0); - result_file = mbed_fprintf(stderr, "ju: %ju\r\n", (uintmax_t) 0); - result_baseline = make_test_string("ju: ", (uintmax_t) 0, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("ju: %ju\r\n", UINTMAX_MAX); - result_file = mbed_fprintf(stderr, "ju: %ju\r\n", UINTMAX_MAX); - result_baseline = make_test_string("ju: ", UINTMAX_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%zu not supported by mbed\r\n"); -#else - result_minimal = mbed_printf("zu: %zu\r\n", 0); - result_file = mbed_fprintf(stderr, "zu: %zu\r\n", 0); - result_baseline = make_test_string("zu: ", 0, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("zu: %zu\r\n", SIZE_MAX); - result_file = mbed_fprintf(stderr, "zu: %zu\r\n", SIZE_MAX); - result_baseline = make_test_string("zu: ", SIZE_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%tu not supported by mbed\r\n"); -#else - result_minimal = mbed_printf("tu: %tu\r\n", 0); - result_file = mbed_fprintf(stderr, "tu: %tu\r\n", 0); - result_baseline = make_test_string("tu: ", 0, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("tu: %tu\r\n", UINTPTR_MAX); - result_file = mbed_fprintf(stderr, "tu: %tu\r\n", UINTPTR_MAX); - result_baseline = make_test_string("tu: ", UINTPTR_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); -#endif - - return CaseNext; -} - -static control_t test_printf_x(const size_t call_count) -{ - int result_baseline; - int result_minimal; - int result_file; - - /*************************************************************************/ - /*************************************************************************/ - result_minimal = mbed_printf("hhX: %hhX\r\n", 0); - result_file = mbed_fprintf(stderr, "hhX: %hhX\r\n", 0); - result_baseline = make_test_string("hhX: ", 0, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("hhX: %hhX\r\n", UCHAR_MAX); - result_file = mbed_fprintf(stderr, "hhX: %hhX\r\n", UCHAR_MAX); - result_baseline = make_test_string("hhX: ", UCHAR_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("hX: %hX\r\n", 0); - result_file = mbed_fprintf(stderr, "hX: %hX\r\n", 0); - result_baseline = make_test_string("hX: ", 0, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("hX: %hX\r\n", USHRT_MAX); - result_file = mbed_fprintf(stderr, "hX: %hX\r\n", USHRT_MAX); - result_baseline = make_test_string("hX: ", USHRT_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("X: %X\r\n", 0); - result_file = mbed_fprintf(stderr, "X: %X\r\n", 0); - result_baseline = make_test_string("X: ", 0, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("X: %X\r\n", UINT_MAX); - result_file = mbed_fprintf(stderr, "X: %X\r\n", UINT_MAX); - result_baseline = make_test_string("X: ", UINT_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("lX: %lX\r\n", 0UL); - result_file = mbed_fprintf(stderr, "lX: %lX\r\n", 0UL); - result_baseline = make_test_string("lX: ", 0UL, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("lX: %lX\r\n", ULONG_MAX); - result_file = mbed_fprintf(stderr, "lX: %lX\r\n", ULONG_MAX); - result_baseline = make_test_string("lX: ", ULONG_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("llX: %llX\r\n", 0ULL); - result_file = mbed_fprintf(stderr, "llX: %llX\r\n", 0ULL); - result_baseline = make_test_string("llX: ", 0ULL, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("llX: %llX\r\n", ULLONG_MAX); - result_file = mbed_fprintf(stderr, "llX: %llX\r\n", ULLONG_MAX); - result_baseline = make_test_string("llX: ", ULLONG_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - -#ifdef TARGET_LIKE_MBED - printf("%%jX not supported by mbed\r\n"); -#else - result_minimal = mbed_printf("jX: %jX\r\n", (uintmax_t) 0); - result_file = mbed_fprintf(stderr, "jX: %jX\r\n", (uintmax_t) 0); - result_baseline = make_test_string("jX: ", (uintmax_t) 0, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("jX: %jX\r\n", UINTMAX_MAX); - result_file = mbed_fprintf(stderr, "jX: %jX\r\n", UINTMAX_MAX); - result_baseline = make_test_string("jX: ", UINTMAX_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%zX not supported by mbed\r\n"); -#else - result_minimal = mbed_printf("zX: %zX\r\n", 0); - result_file = mbed_fprintf(stderr, "zX: %zX\r\n", 0); - result_baseline = make_test_string("zX: ", 0, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("zX: %zX\r\n", SIZE_MAX); - result_file = mbed_fprintf(stderr, "zX: %zX\r\n", SIZE_MAX); - result_baseline = make_test_string("zX: ", SIZE_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%tX not supported by mbed\r\n"); -#else - result_minimal = mbed_printf("tX: %tX\r\n", 0); - result_file = mbed_fprintf(stderr, "tX: %tX\r\n", 0); - result_baseline = make_test_string("tX: ", 0, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - result_minimal = mbed_printf("tX: %tX\r\n", UINTPTR_MAX); - result_file = mbed_fprintf(stderr, "tX: %tX\r\n", UINTPTR_MAX); - result_baseline = make_test_string("tX: ", UINTPTR_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); -#endif - - result_minimal = mbed_printf("x: %x\r\n", 11259375); - result_baseline = make_test_string("x: ", 11259375, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - return CaseNext; -} - -static control_t test_printf_percent(const size_t call_count) -{ - int result_baseline; - int result_minimal; - int result_file; - char buffer_baseline[100] = {0}; - - result_minimal = mbed_printf("%% \r\n"); - result_file = mbed_fprintf(stderr, "%% \r\n"); - result_baseline = sprintf(buffer_baseline, "%% \r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_file); - - return CaseNext; -} - -/******************************************************************************/ -/* */ -/* SNPRINTF */ -/* */ -/******************************************************************************/ - -static control_t test_snprintf_d(const size_t call_count) -{ - char buffer_minimal[100]; - int result_baseline; - int result_minimal; - - /*************************************************************************/ - /*************************************************************************/ - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhd: %hhd\r\n", SCHAR_MIN); - result_baseline = make_test_string("hhd: ", SCHAR_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhd: %hhd\r\n", SCHAR_MAX); - result_baseline = make_test_string("hhd: ", SCHAR_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hd: %hd\r\n", SHRT_MIN); - result_baseline = make_test_string("hd: ", SHRT_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hd: %hd\r\n", SHRT_MAX); - result_baseline = make_test_string("hd: ", SHRT_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "d: %d\r\n", INT_MIN); - result_baseline = make_test_string("d: ", INT_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "d: %d\r\n", INT_MAX); - result_baseline = make_test_string("d: ", INT_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ld: %ld\r\n", LONG_MIN); - result_baseline = make_test_string("ld: ", LONG_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ld: %ld\r\n", LONG_MAX); - result_baseline = make_test_string("ld: ", LONG_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lld: %lld\r\n", LLONG_MIN); - result_baseline = make_test_string("lld: ", LLONG_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lld: %lld\r\n", LLONG_MAX); - result_baseline = make_test_string("lld: ", LLONG_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - -#ifdef TARGET_LIKE_MBED - printf("%%jd not supported by mbed\r\n"); -#else - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", (intmax_t) INT32_MIN); - result_baseline = make_test_string("jd: ", (intmax_t) INT32_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", (intmax_t) INT32_MAX); - result_baseline = make_test_string("jd: ", (intmax_t) INT32_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%zd not supported by mbed\r\n"); -#else - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", (ssize_t) INT32_MIN); - result_baseline = make_test_string("zd: ", (ssize_t) INT32_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", (ssize_t) INT32_MAX); - result_baseline = make_test_string("zd: ", (ssize_t) INT32_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%td not supported by mbed\r\n"); -#else - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "td: %td\r\n", PTRDIFF_MIN); - result_baseline = make_test_string("td: ", PTRDIFF_MIN, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "td: %td\r\n", PTRDIFF_MAX); - result_baseline = make_test_string("td: ", PTRDIFF_MAX, BASE_10, "\r\n", true); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - - int a = 2; - int b = 3; - result_minimal = mbed_snprintf(0, 0, "%d + %d = %d\n", a, b, a + b); - TEST_ASSERT_EQUAL_INT(10, result_minimal); - - return CaseNext; -} - -static control_t test_snprintf_u(const size_t call_count) -{ - char buffer_minimal[100]; - int result_baseline; - int result_minimal; - - /*************************************************************************/ - /*************************************************************************/ - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhu: %hhu\r\n", 0); - result_baseline = make_test_string("hhu: ", 0, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhu: %hhu\r\n", UCHAR_MAX); - result_baseline = make_test_string("hhu: ", UCHAR_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hu: %hu\r\n", 0); - result_baseline = make_test_string("hu: ", 0, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hu: %hu\r\n", USHRT_MAX); - result_baseline = make_test_string("hu: ", USHRT_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "u: %u\r\n", 0); - result_baseline = make_test_string("u: ", 0, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "u: %u\r\n", UINT_MAX); - result_baseline = make_test_string("u: ", UINT_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lu: %lu\r\n", 0UL); - result_baseline = make_test_string("lu: ", 0UL, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lu: %lu\r\n", ULONG_MAX); - result_baseline = make_test_string("lu: ", ULONG_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llu: %llu\r\n", 0ULL); - result_baseline = make_test_string("llu: ", 0ULL, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llu: %llu\r\n", ULLONG_MAX); - result_baseline = make_test_string("llu: ", ULLONG_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - -#ifdef TARGET_LIKE_MBED - printf("%%ju not supported by mbed\r\n"); -#else - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ju: %ju\r\n", (uintmax_t) 0); - result_baseline = make_test_string("ju: ", (uintmax_t) 0, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ju: %ju\r\n", UINTMAX_MAX); - result_baseline = make_test_string("ju: ", UINTMAX_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%zu not supported by mbed\r\n"); -#else - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zu: %zu\r\n", 0); - result_baseline = make_test_string("zu: ", 0, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zu: %zu\r\n", SIZE_MAX); - result_baseline = make_test_string("zu: ", SIZE_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%tu not supported by mbed\r\n"); -#else - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tu: %tu\r\n", 0); - result_baseline = make_test_string("tu: ", 0, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tu: %tu\r\n", UINTPTR_MAX); - result_baseline = make_test_string("tu: ", UINTPTR_MAX, BASE_10, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - - return CaseNext; -} - -static control_t test_snprintf_x(const size_t call_count) -{ - char buffer_minimal[100]; - int result_baseline; - int result_minimal; - - /*************************************************************************/ - /*************************************************************************/ - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhX: %hhX\r\n", 0); - result_baseline = make_test_string("hhX: ", 0, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhX: %hhX\r\n", UCHAR_MAX); - result_baseline = make_test_string("hhX: ", UCHAR_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hX: %hX\r\n", 0); - result_baseline = make_test_string("hX: ", 0, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hX: %hX\r\n", USHRT_MAX); - result_baseline = make_test_string("hX: ", USHRT_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "X: %X\r\n", 0); - result_baseline = make_test_string("X: ", 0, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "X: %X\r\n", UINT_MAX); - result_baseline = make_test_string("X: ", UINT_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lX: %lX\r\n", 0UL); - result_baseline = make_test_string("lX: ", 0UL, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lX: %lX\r\n", ULONG_MAX); - result_baseline = make_test_string("lX: ", ULONG_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llX: %llX\r\n", 0ULL); - result_baseline = make_test_string("llX: ", 0ULL, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llX: %llX\r\n", ULLONG_MAX); - result_baseline = make_test_string("llX: ", ULLONG_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - -#ifdef TARGET_LIKE_MBED - printf("%%jX not supported by mbed\r\n"); -#else - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jX: %jX\r\n", (uintmax_t) 0); - result_baseline = make_test_string("jX: ", (uintmax_t) 0, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jX: %jX\r\n", UINTMAX_MAX); - result_baseline = make_test_string("jX: ", UINTMAX_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%xX not supported by mbed\r\n"); -#else - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zX: %zX\r\n", 0); - result_baseline = make_test_string("zX: ", 0, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zX: %zX\r\n", SIZE_MAX); - result_baseline = make_test_string("zX: ", SIZE_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%tX not supported by mbed\r\n"); -#else - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tX: %tX\r\n", 0); - result_baseline = make_test_string("tX: ", 0, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tX: %tX\r\n", UINTPTR_MAX); - result_baseline = make_test_string("tX: ", UINTPTR_MAX, BASE_16, "\r\n"); - TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - - return CaseNext; -} - -static control_t test_snprintf_percent(const size_t call_count) -{ - char buffer_baseline[100]; - char buffer_minimal[100]; - int result_baseline; - int result_minimal; - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "%% \r\n"); - result_baseline = sprintf(buffer_baseline, "%% \r\n"); - TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - return CaseNext; -} - -static control_t test_snprintf_unsupported_specifier(const size_t call_count) -{ - char buffer_minimal[100]; - - TEST_ASSERT_NOT_EQUAL( - 0, - mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "%a \r\n", 5) - ); - TEST_ASSERT_EQUAL_STRING("%a \r\n", buffer_minimal); - - return CaseNext; -} - -#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT -static control_t test_printf_f(const size_t call_count) -{ - char buffer_baseline[100]; - int result_baseline; - int result_minimal; -#define CLEAN_BUFFER memset(buffer_baseline, 0x00, sizeof(buffer_baseline)) - /*************************************************************************/ - /*************************************************************************/ - double pi = 3.14159265359; - CLEAN_BUFFER; - result_minimal = mbed_printf("f: %f\r\n", 3.0089); - result_baseline = sprintf(buffer_baseline, "f: 3.008900\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - CLEAN_BUFFER; - result_minimal = mbed_printf("f: %f\r\n", 7.0); - result_baseline = sprintf(buffer_baseline, "f: 7.000000\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - CLEAN_BUFFER; - result_minimal = mbed_printf("f: %f\r\n", -1 * pi); - result_baseline = sprintf(buffer_baseline, "f: -3.141593\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - CLEAN_BUFFER; - result_minimal = mbed_printf("f: %f\r\n", 0.0); - result_baseline = sprintf(buffer_baseline, "f: 0.000000\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - CLEAN_BUFFER; - result_minimal = mbed_printf("f: %f\r\n", pi); - result_baseline = sprintf(buffer_baseline, "f: 3.141593\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - CLEAN_BUFFER; - result_minimal = mbed_printf("f: %f\r\n", 2.12345651); - result_baseline = sprintf(buffer_baseline, "f: 2.123457\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - CLEAN_BUFFER; - result_minimal = mbed_printf("f: %f\r\n", 2.12345649); - result_baseline = sprintf(buffer_baseline, "f: 2.123456\r\n"); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - return CaseNext; -} - -static control_t test_snprintf_f(const size_t call_count) -{ - char buffer_baseline[100]; - char buffer_minimal[100]; - int result_baseline; - int result_minimal; -#define CLEAN_BUFFER memset(buffer_baseline, 0x00, sizeof(buffer_baseline)) - /*************************************************************************/ - /*************************************************************************/ - - double pi = 3.14159265359; - CLEAN_BUFFER; - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", 3.0089); - result_baseline = sprintf(buffer_baseline, "f: 3.008900\r\n"); - TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - CLEAN_BUFFER; - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", 7.0); - result_baseline = sprintf(buffer_baseline, "f: 7.000000\r\n"); - TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - CLEAN_BUFFER; - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", -1 * pi); - result_baseline = sprintf(buffer_baseline, "f: -3.141593\r\n"); - TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - CLEAN_BUFFER; - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", 0.0); - result_baseline = sprintf(buffer_baseline, "f: 0.000000\r\n"); - TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - CLEAN_BUFFER; - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", pi); - result_baseline = sprintf(buffer_baseline, "f: 3.141593\r\n"); - TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - return CaseNext; -} -#endif - - -/* Generic buffer overflow test function. - * Template parameters: - * 'T' is the type being tested - * 'buf_size' is the buffer size used in tests - * 'base' is used to represent data in BASE_10 or BASE_16 numeral system - * Function parameters: - * 'fmt' is the format to use for sprintf - * 'data' is the data that will be printed - * 'is_negative' is true for negative number, false for positive number -*/ -template -static control_t test_snprintf_buffer_overflow_generic(const char *fmt, T data, bool is_negative = false) -{ - char buffer_baseline[buf_size]; - char buffer_minimal[buf_size]; - int result_baseline; - int result_minimal; - char prefix[buf_size] = { 0 }; - // fmt string has "format specifier: %format specifier" - // Extract the string preceding the first '%' from fmt. - extract_prefix(fmt, &prefix[0]); - result_baseline = make_test_string(prefix, data, base, nullptr, is_negative); - - /* empty buffer test */ - result_minimal = mbed_snprintf(buffer_minimal, 0, fmt, data); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - /* buffer isn't large enough, output needs to be truncated */ - result_minimal = mbed_snprintf(buffer_minimal, buf_size - 2, fmt, data); - snprintf(buffer_baseline, buf_size - 2, "%s", expected_string); - TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - /* buffer is one byte shorter than needed, string terminator must - be written and output must be truncated */ - result_minimal = mbed_snprintf(buffer_minimal, buf_size - 1, fmt, data); - snprintf(buffer_baseline, buf_size - 1, "%s", expected_string); - TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - /* buffer is just long enough */ - result_minimal = mbed_snprintf(buffer_minimal, buf_size, fmt, data); - snprintf(buffer_baseline, buf_size, "%s", expected_string); - TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - return CaseNext; -} - -/* Based on the generic buffer overflow function above, create tests for - each relevant data type. In each case, the buffer for printing will only - be large enough to fit the printed data. */ -static control_t test_snprintf_buffer_overflow_d(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("d: %d", -1024, true); -} - -static control_t test_snprintf_buffer_overflow_ld(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("ld: %ld", -1048576L, true); -} - -static control_t test_snprintf_buffer_overflow_lld(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("lld: %lld", -1099511627776LL, true); -} - -static control_t test_snprintf_buffer_overflow_u(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("u: %u", 1024); -} - -static control_t test_snprintf_buffer_overflow_lu(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("lu: %lu", 1048576UL); -} - -static control_t test_snprintf_buffer_overflow_llu(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("llu: %llu", 1099511627776ULL); -} - -static control_t test_snprintf_buffer_overflow_x(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("x: 0x%x", 0x400); -} - -static control_t test_snprintf_buffer_overflow_lx(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("lx: 0x%lx", 0x100000UL); -} - -static control_t test_snprintf_buffer_overflow_llx(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("llx: 0x%llx", 0x10000000000ULL); -} - -utest::v1::status_t greentea_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(30 * 60, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("printf %d", test_printf_d), - Case("snprintf %d", test_snprintf_d), - Case("printf %u", test_printf_u), - Case("snprintf %u", test_snprintf_u), - Case("printf %x", test_printf_x), - Case("snprintf %x", test_snprintf_x), - Case("printf %%", test_printf_percent), - Case("snprintf %%", test_snprintf_percent), - Case("snprintf unsupported specifier", test_snprintf_unsupported_specifier), -#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT - Case("printf %f", test_printf_f), - Case("snprintf %f", test_snprintf_f), -#endif - Case("snprintf buffer overflow %d", test_snprintf_buffer_overflow_d), - Case("snprintf buffer overflow %ld", test_snprintf_buffer_overflow_ld), - Case("snprintf buffer overflow %lld", test_snprintf_buffer_overflow_lld), - Case("snprintf buffer overflow %u", test_snprintf_buffer_overflow_u), - Case("snprintf buffer overflow %lu", test_snprintf_buffer_overflow_lu), - Case("snprintf buffer overflow %llu", test_snprintf_buffer_overflow_llu), - Case("snprintf buffer overflow %x", test_snprintf_buffer_overflow_x), - Case("snprintf buffer overflow %lx", test_snprintf_buffer_overflow_lx), - Case("snprintf buffer overflow %llx", test_snprintf_buffer_overflow_llx), -}; - -Specification specification(greentea_setup, cases, greentea_test_teardown_handler); - -int main() -{ - return !Harness::run(specification); -} diff --git a/TESTS/mbed_platform/minimal-printf/compliance/mbed_printf.c b/TESTS/mbed_platform/minimal-printf/compliance/mbed_printf.c deleted file mode 100644 index ac39371..0000000 --- a/TESTS/mbed_platform/minimal-printf/compliance/mbed_printf.c +++ /dev/null @@ -1,66 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 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 "mbed_printf_implementation.h" - -#include - - -int mbed_printf(const char *format, ...) -{ - va_list arguments; - va_start(arguments, format); - int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, stdout); - va_end(arguments); - - return result; -} - -int mbed_snprintf(char *buffer, size_t length, const char *format, ...) -{ - va_list arguments; - va_start(arguments, format); - int result = mbed_minimal_formatted_string(buffer, length, format, arguments, NULL); - va_end(arguments); - - return result; -} - -int mbed_vprintf(const char *format, va_list arguments) -{ - return mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, stdout); -} - -int mbed_vsnprintf(char *buffer, size_t length, const char *format, va_list arguments) -{ - return mbed_minimal_formatted_string(buffer, length, format, arguments, NULL); -} - -int mbed_fprintf(FILE *stream, const char *format, ...) -{ - va_list arguments; - va_start(arguments, format); - int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, stream); - va_end(arguments); - - return result; -} - -int mbed_vfprintf(FILE *stream, const char *format, va_list arguments) -{ - return mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, stream); -} diff --git a/TESTS/mbed_platform/minimal-printf/compliance/mbed_printf.h b/TESTS/mbed_platform/minimal-printf/compliance/mbed_printf.h deleted file mode 100644 index 7e9a8c7..0000000 --- a/TESTS/mbed_platform/minimal-printf/compliance/mbed_printf.h +++ /dev/null @@ -1,74 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2016 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_PRINTF_H -#define MBED_PRINTF_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Minimal printf - * - * Prints directly to stdio/UART without using malloc. - */ -int mbed_printf(const char *format, ...); - -/** - * Minimal snprintf - * - * Prints directly to buffer without using malloc. - */ -int mbed_snprintf(char *buffer, size_t length, const char *format, ...); - -/** - * Minimal printf - * - * Prints directly to stdio/UART without using malloc. - */ -int mbed_vprintf(const char *format, va_list arguments); - -/** - * Minimal snprintf - * - * Prints directly to buffer without using malloc. - */ -int mbed_vsnprintf(char *buffer, size_t length, const char *format, va_list arguments); - -/** - * Minimal fprintf - * - * Prints directly to file stream without using malloc. - */ -int mbed_fprintf(FILE *stream, const char *format, ...); - -/** - * Minimal vfprintf - * - * Prints directly to file stream without using malloc. - */ -int mbed_vfprintf(FILE *stream, const char *format, va_list arguments); - -#ifdef __cplusplus -} -#endif - -#endif // MBED_PRINTF_H diff --git a/TESTS/mbed_platform/minimal-printf/compliance/test_config.json b/TESTS/mbed_platform/minimal-printf/compliance/test_config.json deleted file mode 100644 index 084d441..0000000 --- a/TESTS/mbed_platform/minimal-printf/compliance/test_config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "target_overrides": { - "*": { - "platform.minimal-printf-enable-floating-point": true - } - } -} diff --git a/TESTS/mbed_platform/stats_cpu/main.cpp b/TESTS/mbed_platform/stats_cpu/main.cpp deleted file mode 100644 index 85c2a4a..0000000 --- a/TESTS/mbed_platform/stats_cpu/main.cpp +++ /dev/null @@ -1,121 +0,0 @@ - -/* mbed Microcontroller Library - * 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 "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest/utest.h" - -#include "mbed.h" - -#if !defined(MBED_CPU_STATS_ENABLED) || !DEVICE_LPTICKER || !DEVICE_SLEEP -#error [NOT_SUPPORTED] test not supported -#else - -using namespace utest::v1; - -DigitalOut led1(LED1); - -// Targets with these cores have their RAM enough size to create threads with bigger stacks -#if defined(__CORTEX_A9) || defined(__CORTEX_M23) || defined(__CORTEX_M33) || defined(__CORTEX_M7) -#define MAX_THREAD_STACK 512 -#else -#define MAX_THREAD_STACK 384 -#endif - -#define SAMPLE_TIME 1000 // msec -#define LOOP_TIME 2000 // msec - -static int32_t wait_time = 5000; - -static void busy_thread() -{ - volatile uint64_t i = ~0; - - while (i--) { - led1 = !led1; - wait_us(wait_time); - } -} - -void get_cpu_usage() -{ - static uint64_t prev_idle_time = 0; - mbed_stats_cpu_t stats; - - while (1) { - mbed_stats_cpu_get(&stats); - uint64_t diff = (stats.idle_time - prev_idle_time); - uint8_t usage = 100 - ((diff * 100) / (SAMPLE_TIME * 1000)); - prev_idle_time = stats.idle_time; - TEST_ASSERT_NOT_EQUAL(0, usage); - ThisThread::sleep_for(SAMPLE_TIME); - } -} - -void test_cpu_info(void) -{ - mbed_stats_cpu_t stats; - // Additional read to make sure timer is initialized - mbed_stats_cpu_get(&stats); - ThisThread::sleep_for(3); - mbed_stats_cpu_get(&stats); - TEST_ASSERT_NOT_EQUAL(0, stats.uptime); - TEST_ASSERT_NOT_EQUAL(0, stats.idle_time); - return; -} - -void test_cpu_load(void) -{ - - Thread thread(osPriorityNormal, MAX_THREAD_STACK); - Thread thread_stats(osPriorityNormal, MAX_THREAD_STACK); - - thread.start(busy_thread); - thread_stats.start(get_cpu_usage); - - // Steadily increase the system load - for (int count = 1; ; count++) { - ThisThread::sleep_for(LOOP_TIME); - if (wait_time <= 0) { - break; - } - wait_time -= 1000; // usec - } - thread.terminate(); - thread_stats.terminate(); -} - -Case cases[] = { - Case("Test CPU Info", test_cpu_info), - Case("Test CPU load", test_cpu_load) -}; - -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(20, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); - -int main() -{ - Harness::run(specification); -} - -#endif // !defined(MBED_CPU_STATS_ENABLED) || !DEVICE_LPTICKER || !DEVICE_SLEEP diff --git a/TESTS/mbed_platform/stats_heap/main.cpp b/TESTS/mbed_platform/stats_heap/main.cpp deleted file mode 100644 index 2e7dc98..0000000 --- a/TESTS/mbed_platform/stats_heap/main.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) 2013-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 - * - * 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 "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest/utest.h" -#include "mbed_stats.h" -#include -#include - -#if !defined(MBED_HEAP_STATS_ENABLED) -#error [NOT_SUPPORTED] test not supported -#else - -using namespace utest::v1; - -#define ALLOCATION_SIZE_DEFAULT 564 -#define ALLOCATION_SIZE_SMALL 124 -#define ALLOCATION_SIZE_LARGE 700 -#define ALLOCATION_SIZE_FAIL (1024 * 1024 *1024) - -typedef void *(*malloc_cb_t)(uint32_t size); - -static void *thunk_malloc(uint32_t size); -static void *thunk_calloc_1(uint32_t size); -static void *thunk_calloc_4(uint32_t size); -static void *thunk_realloc(uint32_t size); - -malloc_cb_t malloc_thunk_array[] = { - thunk_malloc, - thunk_calloc_1, - thunk_calloc_4, - thunk_realloc, -}; - -void test_case_malloc_free_size() -{ - mbed_stats_heap_t stats_start; - mbed_stats_heap_t stats_current; - void *data; - - mbed_stats_heap_get(&stats_start); - - for (uint32_t i = 0; i < sizeof(malloc_thunk_array) / sizeof(malloc_cb_t); i++) { - - // Allocate memory and assert size change - data = malloc_thunk_array[i](ALLOCATION_SIZE_DEFAULT); - TEST_ASSERT(data != NULL); - mbed_stats_heap_get(&stats_current); - uint32_t increase = stats_current.current_size - stats_start.current_size; - TEST_ASSERT_EQUAL_UINT32(ALLOCATION_SIZE_DEFAULT, increase); - 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); - } -} - -void test_case_allocate_zero() -{ - mbed_stats_heap_t stats_start; - mbed_stats_heap_t stats_current; - void *data; - - mbed_stats_heap_get(&stats_start); - - for (uint32_t i = 0; i < sizeof(malloc_thunk_array) / sizeof(malloc_cb_t); i++) { - - // Allocate memory and assert size change - data = malloc_thunk_array[i](0); - // Return can be NULL - mbed_stats_heap_get(&stats_current); - 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); - } -} - -void test_case_allocate_fail() -{ - mbed_stats_heap_t stats_start; - mbed_stats_heap_t stats_current; - void *data; - - mbed_stats_heap_get(&stats_start); - - for (uint32_t i = 0; i < sizeof(malloc_thunk_array) / sizeof(malloc_cb_t); i++) { - - // Trigger a failure by trying to allocate a buffer that won't fit - data = malloc_thunk_array[i](ALLOCATION_SIZE_FAIL); - TEST_ASSERT(data == NULL); - mbed_stats_heap_get(&stats_current); - 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_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); - } -} - -static void *thunk_malloc(uint32_t size) -{ - return malloc(size); -} - -static void *thunk_calloc_1(uint32_t size) -{ - return calloc(size / 1, 1); -} - -static void *thunk_calloc_4(uint32_t size) -{ - return calloc(size / 4, 4); -} - - -static void *thunk_realloc(uint32_t size) -{ - return realloc(NULL, size); -} - -void test_case_realloc_size() -{ - mbed_stats_heap_t stats_start; - mbed_stats_heap_t stats_current; - uint32_t increase; - void *data; - - mbed_stats_heap_get(&stats_start); - - // Allocate memory and assert size change - data = realloc(NULL, ALLOCATION_SIZE_DEFAULT); - TEST_ASSERT(data != NULL); - mbed_stats_heap_get(&stats_current); - increase = stats_current.current_size - stats_start.current_size; - TEST_ASSERT_EQUAL_UINT32(increase, ALLOCATION_SIZE_DEFAULT); - - // Decrease size and assert size change - data = realloc(data, ALLOCATION_SIZE_SMALL); - TEST_ASSERT(data != NULL); - mbed_stats_heap_get(&stats_current); - increase = stats_current.current_size - stats_start.current_size; - TEST_ASSERT_EQUAL_UINT32(increase, ALLOCATION_SIZE_SMALL); - - // Increase size and assert size change - data = realloc(data, ALLOCATION_SIZE_LARGE); - TEST_ASSERT(data != NULL); - mbed_stats_heap_get(&stats_current); - increase = stats_current.current_size - stats_start.current_size; - TEST_ASSERT_EQUAL_UINT32(increase, ALLOCATION_SIZE_LARGE); - - // 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); -} - -Case cases[] = { - Case("malloc and free size", test_case_malloc_free_size), - Case("allocate size zero", test_case_allocate_zero), - Case("allocation failure", test_case_allocate_fail), - Case("realloc size", test_case_realloc_size), -}; - -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(20, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); - -int main() -{ - Harness::run(specification); -} - -#endif // !defined(MBED_HEAP_STATS_ENABLED) diff --git a/TESTS/mbed_platform/stats_sys/main.cpp b/TESTS/mbed_platform/stats_sys/main.cpp deleted file mode 100644 index 2ed7424..0000000 --- a/TESTS/mbed_platform/stats_sys/main.cpp +++ /dev/null @@ -1,110 +0,0 @@ - -/* mbed Microcontroller Library - * 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 "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest/utest.h" - -#include "mbed.h" - -#if !defined(MBED_SYS_STATS_ENABLED) -#error [NOT_SUPPORTED] test not supported -#else - -using namespace utest::v1; - -void test_sys_info() -{ - mbed_stats_sys_t stats; - mbed_stats_sys_get(&stats); - - TEST_ASSERT_NOT_EQUAL(0, stats.os_version); -#if defined(__CORTEX_M) - TEST_ASSERT_NOT_EQUAL(0, stats.cpu_id); -#endif - -#if defined(__IAR_SYSTEMS_ICC__) - TEST_ASSERT_EQUAL(IAR, stats.compiler_id); -#elif defined(__ARMCC_VERSION) - TEST_ASSERT_EQUAL(ARM, stats.compiler_id); -#elif defined(__GNUC__) - TEST_ASSERT_EQUAL(GCC_ARM, stats.compiler_id); -#endif - TEST_ASSERT_NOT_EQUAL(0, stats.compiler_version); - - // RAM / ROM sizes should not be zero and should match the define -#if defined(MBED_ROM_START) && defined(MBED_ROM_SIZE) - TEST_ASSERT_NOT_EQUAL(0, stats.rom_size[0]); - TEST_ASSERT_EQUAL(MBED_ROM_SIZE, stats.rom_size[0]); - TEST_ASSERT_EQUAL(MBED_ROM_START, stats.rom_start[0]); -#endif -#if defined(MBED_RAM_START) && defined(MBED_RAM_SIZE) - TEST_ASSERT_NOT_EQUAL(0, stats.ram_size[0]); - TEST_ASSERT_EQUAL(MBED_RAM_START, stats.ram_start[0]); - TEST_ASSERT_EQUAL(MBED_RAM_SIZE, stats.ram_size[0]); -#endif -#if defined(MBED_RAM1_START) && defined(MBED_RAM1_SIZE) - TEST_ASSERT_NOT_EQUAL(0, stats.ram_size[1]); - TEST_ASSERT_EQUAL(MBED_RAM1_SIZE, stats.ram_size[1]); - TEST_ASSERT_EQUAL(MBED_RAM1_START, stats.ram_start[1]); -#endif -#if defined(MBED_RAM2_START) && defined(MBED_RAM2_SIZE) - TEST_ASSERT_NOT_EQUAL(0, stats.ram_size[2]); - TEST_ASSERT_EQUAL(MBED_RAM2_SIZE, stats.ram_size[2]); - TEST_ASSERT_EQUAL(MBED_RAM2_START, stats.ram_start[2]); -#endif -#if defined(MBED_RAM3_START) && defined(MBED_RAM3_SIZE) - TEST_ASSERT_NOT_EQUAL(0, stats.ram_size[3]); - TEST_ASSERT_EQUAL(MBED_RAM3_SIZE, stats.ram_size[3]); - TEST_ASSERT_EQUAL(MBED_RAM3_START, stats.ram_start[3]); -#endif -#if defined(MBED_ROM1_START) && defined(MBED_ROM1_SIZE) - TEST_ASSERT_NOT_EQUAL(0, stats.rom_size[1]); - TEST_ASSERT_EQUAL(MBED_ROM1_SIZE, stats.rom_size[1]); - TEST_ASSERT_EQUAL(MBED_ROM1_START, stats.rom_start[1]); -#endif -#if defined(MBED_ROM2_START) && defined(MBED_ROM2_SIZE) - TEST_ASSERT_NOT_EQUAL(0, stats.rom_size[2]); - TEST_ASSERT_EQUAL(MBED_ROM2_SIZE, stats.rom_size[2]); - TEST_ASSERT_EQUAL(MBED_ROM2_START, stats.rom_start[2]); -#endif -#if defined(MBED_ROM3_START) && defined(MBED_ROM3_SIZE) - TEST_ASSERT_NOT_EQUAL(0, stats.rom_size[3]); - TEST_ASSERT_EQUAL(MBED_ROM3_SIZE, stats.rom_size[3]); - TEST_ASSERT_EQUAL(MBED_ROM3_START, stats.rom_start[3]); -#endif -} - -Case cases[] = { - Case("Test Sys Info", test_sys_info) -}; - -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(20, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); - -int main() -{ - Harness::run(specification); -} - -#endif // !defined(MBED_SYS_STATS_ENABLED) diff --git a/TESTS/mbed_platform/stats_thread/main.cpp b/TESTS/mbed_platform/stats_thread/main.cpp deleted file mode 100644 index f1e386a..0000000 --- a/TESTS/mbed_platform/stats_thread/main.cpp +++ /dev/null @@ -1,179 +0,0 @@ - -/* mbed Microcontroller Library - * 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 "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest/utest.h" - -#include "mbed.h" - -#if !defined(MBED_THREAD_STATS_ENABLED) -#error [NOT_SUPPORTED] test not supported -#else - -using namespace utest::v1; - -static EventFlags ef; -static int32_t counter = 0; - -#define TEST_STACK_SIZE 320 -#define FLAG_SIGNAL_DEC 0x2 -#define MAX_THREAD_STATS 0x8 - -void decrement_on_event() -{ - uint32_t ret = ef.wait_all(FLAG_SIGNAL_DEC); - TEST_ASSERT_FALSE(ret & osFlagsError); - TEST_ASSERT_EQUAL(FLAG_SIGNAL_DEC, ret); - counter--; -} - -void increment_with_delay() -{ - while (1) { - counter++; - ThisThread::sleep_for(500); - } -} - -void test_case_single_thread_stats() -{ - mbed_stats_thread_t *stats = new mbed_stats_thread_t[MAX_THREAD_STATS]; - int old_count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); - Thread t1(osPriorityNormal, TEST_STACK_SIZE, NULL, "Th1"); - t1.start(increment_with_delay); - - // Read stats - int count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); - TEST_ASSERT_EQUAL(1, (count - old_count)); - - for (int i = 0; i < count; i++) { - if (0 == strcmp(stats[i].name, "Th1")) { - TEST_ASSERT_EQUAL(TEST_STACK_SIZE, stats[i].stack_size); - TEST_ASSERT_EQUAL(osPriorityNormal, stats[i].priority); - break; - } - } - - t1.terminate(); - delete[] stats; -} - -#define SINGLE_ELEMENT 1 -void test_case_less_count() -{ - // Default Mbed OS has 3 threads - mbed_stats_thread_t stats; - int count = mbed_stats_thread_get_each(&stats, SINGLE_ELEMENT); - TEST_ASSERT_EQUAL(SINGLE_ELEMENT, count); -} - -void test_case_multi_threads_blocked() -{ - mbed_stats_thread_t *stats = new mbed_stats_thread_t[MAX_THREAD_STATS]; - int old_count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); - - Thread t1(osPriorityNormal, TEST_STACK_SIZE, NULL, "Th1"); - Thread t2(osPriorityNormal1, TEST_STACK_SIZE, NULL, "Th2"); - t1.start(increment_with_delay); - t2.start(decrement_on_event); - - // Read stats - - int count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); - TEST_ASSERT_EQUAL(2, (count - old_count)); - for (int i = 0; i < count; i++) { - if (0 == strcmp(stats[i].name, "Th2")) { - TEST_ASSERT_EQUAL(TEST_STACK_SIZE, stats[i].stack_size); - TEST_ASSERT_EQUAL(osPriorityNormal1, stats[i].priority); - TEST_ASSERT_EQUAL(osThreadBlocked, stats[i].state); - } else if (0 == strcmp(stats[i].name, "Th1")) { - TEST_ASSERT_EQUAL(TEST_STACK_SIZE, stats[i].stack_size); - TEST_ASSERT_EQUAL(osPriorityNormal, stats[i].priority); - } - } - - // Signal blocked thread - uint32_t ret = ef.set(FLAG_SIGNAL_DEC); - TEST_ASSERT_FALSE(ret & osFlagsError); - - ThisThread::sleep_for(100); - - count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); - TEST_ASSERT_EQUAL(1, (count - old_count)); - - t1.terminate(); - delete[] stats; -} - -void test_case_multi_threads_terminate() -{ - mbed_stats_thread_t *stats = new mbed_stats_thread_t[MAX_THREAD_STATS]; - int old_count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); - - Thread t1(osPriorityNormal1, TEST_STACK_SIZE, NULL, "Th1"); - Thread t2(osPriorityNormal2, TEST_STACK_SIZE, NULL, "Th2"); - t2.start(increment_with_delay); - t1.start(decrement_on_event); - - // Read stats - - int count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); - TEST_ASSERT_EQUAL(2, (count - old_count)); - - for (int i = 0; i < count; i++) { - if (0 == strcmp(stats[i].name, "Th2")) { - TEST_ASSERT_EQUAL(TEST_STACK_SIZE, stats[i].stack_size); - TEST_ASSERT_EQUAL(osPriorityNormal2, stats[i].priority); - } else if (0 == strcmp(stats[i].name, "Th1")) { - TEST_ASSERT_EQUAL(TEST_STACK_SIZE, stats[i].stack_size); - TEST_ASSERT_EQUAL(osPriorityNormal1, stats[i].priority); - TEST_ASSERT_EQUAL(osThreadBlocked, stats[i].state); - } - } - - t1.terminate(); - t2.terminate(); - - count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); - TEST_ASSERT_EQUAL(count, old_count); - - delete[] stats; -} - -Case cases[] = { - Case("Single Thread Stats", test_case_single_thread_stats), - Case("Less count value", test_case_less_count), - Case("Multiple Threads blocked", test_case_multi_threads_blocked), - Case("Multiple Threads terminate", test_case_multi_threads_terminate), -}; - -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(20, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); - -int main() -{ - Harness::run(specification); -} - -#endif // !defined(MBED_THREAD_STATS_ENABLED) diff --git a/TESTS/mbed_platform/system_reset/main.cpp b/TESTS/mbed_platform/system_reset/main.cpp deleted file mode 100644 index f1f00e7..0000000 --- a/TESTS/mbed_platform/system_reset/main.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* mbed Microcontroller Library - * 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 "mbed.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" - -#define MSG_VALUE_DUMMY "0" -#define MSG_VALUE_LEN 16 -#define MSG_KEY_LEN 16 - -#define MSG_KEY_DEVICE_READY "ready" -#define MSG_KEY_DEVICE_RESET "reset" - -void test_system_reset() -{ - // Report readiness - greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_DUMMY); - - static char _key[MSG_KEY_LEN + 1] = { }; - static char _value[MSG_VALUE_LEN + 1] = { }; - - greentea_parse_kv(_key, _value, MSG_KEY_LEN, MSG_VALUE_LEN); - if (strcmp(_key, MSG_KEY_DEVICE_RESET) == 0) { - system_reset(); - TEST_ASSERT_MESSAGE(0, "system_reset() did not reset the device as expected."); - } - - TEST_ASSERT_MESSAGE(0, "Unexpected message key."); -} - -int main(void) -{ - GREENTEA_SETUP(30, "system_reset"); - test_system_reset(); - GREENTEA_TESTSUITE_RESULT(0); // Fail on any error. - - return 0; -} diff --git a/TESTS/mbed_platform/wait_ns/main.cpp b/TESTS/mbed_platform/wait_ns/main.cpp deleted file mode 100644 index 9d8743b..0000000 --- a/TESTS/mbed_platform/wait_ns/main.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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 "mbed.h" -#include "greentea-client/test_env.h" -#include "unity.h" -#include "utest.h" -#include "platform/mbed_wait_api.h" -#include "hal/us_ticker_api.h" -#include "hal/lp_ticker_api.h" - -//FastModels not support timing test -#if defined(TARGET_ARM_FM) -#error [NOT_SUPPORTED] test not supported -#else - -using namespace utest::v1; - -/* This test is created based on the test for Timer class. - * Since low power timer is less accurate than regular - * timer we need to adjust delta. - */ - -/* - * Define tolerance as follows: - * Timer might be +/-5% out; wait_ns is permitted 40% slow, but not fast. - * Therefore minimum measured time should be 95% of requested, maximum should - * be 145%. Unity doesn't let us specify an asymmetric error though. - * - * Would be nice to have tighter upper tolerance, but in practice we've seen - * a few devices unable to sustain theoretical throughput - flash wait states? - */ -#define TOLERANCE_MIN 0.95f -#define TOLERANCE_MAX 1.45f -#define MIDPOINT ((TOLERANCE_MIN+TOLERANCE_MAX)/2) -#define DELTA (MIDPOINT-TOLERANCE_MIN) - -/* This test verifies if wait_ns's wait time - * is accurate, according to a timer. - * - * Given timer is created. - * When timer is used to measure delay. - * Then the results are valid (within acceptable range). - */ -template -void test_wait_ns_time_measurement() -{ - CompareTimer timer; - - float wait_val_s = (float)wait_val_ms / 1000; - - /* Start the timer. */ - timer.start(); - - /* Wait ms - arithmetic inside wait_ns will overflow if - * asked for too large a delay, so break it up. - */ - for (int i = 0; i < wait_val_ms; i++) { - wait_ns(1000000); - } - - /* Stop the timer. */ - timer.stop(); - - /* Check results - wait_val_us us have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA * wait_val_s, MIDPOINT * wait_val_s, timer.read()); -} - -utest::v1::status_t test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(15, "default_auto"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { -#if DEVICE_LPTICKER - Case("Test: wait_ns - compare with lp_timer 1s", test_wait_ns_time_measurement<1000, LowPowerTimer>), -#endif - Case("Test: wait_ns - compare with us_timer 1s", test_wait_ns_time_measurement<1000, Timer>) -}; - -Specification specification(test_setup, cases); - -int main() -{ - return !Harness::run(specification); -} - -#endif // defined(TARGET_ARM_FM) diff --git a/UNITTESTS/CMakeLists.txt b/UNITTESTS/CMakeLists.txt index 62b7b18..87863de 100644 --- a/UNITTESTS/CMakeLists.txt +++ b/UNITTESTS/CMakeLists.txt @@ -112,7 +112,8 @@ "${PROJECT_SOURCE_DIR}/stubs" "${PROJECT_SOURCE_DIR}/.." "${PROJECT_SOURCE_DIR}/../features" - "${PROJECT_SOURCE_DIR}/../platform" + "${PROJECT_SOURCE_DIR}/../platform/include" + "${PROJECT_SOURCE_DIR}/../platform/include/platform" "${PROJECT_SOURCE_DIR}/../storage/filesystem/littlefs/include" "${PROJECT_SOURCE_DIR}/../storage/filesystem/fat/include" "${PROJECT_SOURCE_DIR}/../storage/blockdevice/include" diff --git a/UNITTESTS/platform/ATCmdParser/test_ATCmdParser.cpp b/UNITTESTS/platform/ATCmdParser/test_ATCmdParser.cpp deleted file mode 100644 index dbe81c5..0000000 --- a/UNITTESTS/platform/ATCmdParser/test_ATCmdParser.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited and affiliates. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "gtest/gtest.h" -#include "ATCmdParser.h" -#include -#include -#include -#include -#include "FileHandle_stub.h" -#include "mbed_poll_stub.h" - -using namespace mbed; - -static bool expected_oob_callback = false; - -void urc_callback() -{ - EXPECT_TRUE(expected_oob_callback); -} - - -// AStyle ignored as the definition is not clear due to preprocessor usage -// *INDENT-OFF* -class test_ATCmdParser : public testing::Test { -protected: - - void SetUp() - { - filehandle_stub_short_value_counter = 0; - } - - void TearDown() - { - } -}; -// *INDENT-ON* - - -TEST_F(test_ATCmdParser, test_ATCmdParser_create) -{ - FileHandle_stub fh1; - - ATCmdParser *at = new ATCmdParser(&fh1, ","); - at->set_delimiter("\r"); - at->set_timeout(5000); - at->debug_on(1); - - delete at; - - at = new ATCmdParser(&fh1, "\r"); - - EXPECT_TRUE(at != NULL); - delete at; -} - -TEST_F(test_ATCmdParser, test_ATCmdParser_set_timeout) -{ - FileHandle_stub fh1; - - ATCmdParser at(&fh1, ","); - at.set_timeout(8); - at.set_timeout(80); -} - - - -TEST_F(test_ATCmdParser, test_ATCmdParser_process_oob) -{ - FileHandle_stub fh1; - - ATCmdParser at(&fh1); - at.set_timeout(10); - - at.process_oob(); - - filehandle_stub_short_value_counter = 1; - fh1.short_value = POLLIN; - at.oob("s", &urc_callback); - at.process_oob(); - - filehandle_stub_short_value_counter = 2; - at.process_oob(); - - char buf[5] = {0}; - char table[] = "ssssssssssssssssssssssssssssssss\0"; - filehandle_stub_table = table; - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - at.read(buf, 5); - - filehandle_stub_short_value_counter = 2; - expected_oob_callback = true; - at.process_oob(); - expected_oob_callback = false; - - filehandle_stub_table_pos = 0; - at.read(buf, 5); - - filehandle_stub_short_value_counter = 1; - expected_oob_callback = true; - at.process_oob(); - expected_oob_callback = false; - - char table2[5]; - table2[0] = '\r'; - table2[1] = '\r'; - table2[2] = '\n'; - table2[3] = '\n'; - table2[4] = 0; - filehandle_stub_table = table2; - - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - at.read(buf, 1); - - filehandle_stub_short_value_counter = 1; - at.process_oob(); - - filehandle_stub_table = table; - - filehandle_stub_short_value_counter = 0; - filehandle_stub_table_pos = 0; - filehandle_stub_table = NULL; -} - - - -TEST_F(test_ATCmdParser, test_ATCmdParser_flush) -{ - FileHandle_stub fh1; - - ATCmdParser at(&fh1, ","); - filehandle_stub_short_value_counter = 1; - fh1.short_value = POLLIN; - at.flush(); -} - -TEST_F(test_ATCmdParser, test_ATCmdParser_write) -{ - FileHandle_stub fh1; - - ATCmdParser at(&fh1, ","); - fh1.size_value = -1; - EXPECT_TRUE(-1 == at.write("help", 4)); - - mbed_poll_stub::revents_value = POLLOUT; - mbed_poll_stub::int_value = 1; - fh1.size_value = -1; - EXPECT_TRUE(-1 == at.write("help", 4)); - - mbed_poll_stub::revents_value = POLLOUT; - mbed_poll_stub::int_value = 1; - fh1.size_value = 7; - EXPECT_EQ(4, at.write("help", 4)); -} - -TEST_F(test_ATCmdParser, test_ATCmdParser_set_delimiter) -{ - FileHandle_stub fh1; - - ATCmdParser at(&fh1, ","); - at.set_delimiter("+"); -} - -TEST_F(test_ATCmdParser, test_ATCmdParser_read) -{ - FileHandle_stub fh1; - filehandle_stub_table = NULL; - filehandle_stub_table_pos = 0; - - ATCmdParser at(&fh1, ","); - char buf[8] = {0}; - - - // TEST EMPTY BUFFER - // Shouldn't read any byte since buffer is empty - EXPECT_TRUE(-1 == at.read(buf, 1)); - // Return error due to error set to at handler by the above call on empty buffer - EXPECT_TRUE(-1 == at.read(buf, 1)); - - // TEST DATA IN BUFFER - char table1[] = "1234512345678OK\r\n\0"; - filehandle_stub_table = table1; - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - - // Read 5 bytes - EXPECT_EQ(5, at.read(buf, 5)); - EXPECT_TRUE(!memcmp(buf, table1, 5)); - // get_char triggered above should have filled in the whole reading buffer - EXPECT_EQ(filehandle_stub_table_pos, (strlen(buf))); - // Read another 8 bytes - EXPECT_TRUE(8 == at.read(buf, 8) && !memcmp(buf, table1 + 5, 8)); - // Reading more than the 4 bytes left -> ERROR - EXPECT_EQ(-1, at.read(buf, 5)); -} - -TEST_F(test_ATCmdParser, test_ATCmdParser_debug_on) -{ - FileHandle_stub fh1; - - ATCmdParser at(&fh1, ","); - at.debug_on(true); - at.debug_on(false); -} - -TEST_F(test_ATCmdParser, test_ATCmdParser_abort) -{ - FileHandle_stub fh1; - - ATCmdParser at(&fh1, ","); - at.abort(); -} - -TEST_F(test_ATCmdParser, test_ATCmdParser_printf) -{ - FileHandle_stub fh1; - - ATCmdParser at(&fh1); - at.flush(); - at.debug_on(true); - - const char * format = "TEST %d %s %x %c TEST \r\r\n\n"; - mbed_poll_stub::revents_value = POLLOUT; - mbed_poll_stub::int_value = 1; - fh1.size_value = 64; - - EXPECT_EQ(22, at.printf(format, 5, "t", 0x5, 't')); - - fh1.size_value = -1; - EXPECT_EQ(-1, at.printf(format, 5, "t", 0x5, 't')); -} - -TEST_F(test_ATCmdParser, test_ATCmdParser_send) -{ - FileHandle_stub fh1; - - ATCmdParser at(&fh1); - at.flush(); - at.debug_on(true); - - const char * format = "TEST %d %s %x %c TEST \r\r\n\n"; - mbed_poll_stub::revents_value = POLLOUT; - mbed_poll_stub::int_value = 1; - fh1.size_value = 64; - - //VALID printf - EXPECT_TRUE(at.send(format, 5, "t", 0x5, 't')); - EXPECT_TRUE(at.send("")); - - fh1.size_value = -1; - EXPECT_FALSE(at.send(format, 5, "t", 0x5, 't')); - EXPECT_FALSE(at.send("")); -} - -TEST_F(test_ATCmdParser, test_ATCmdParser_recv) -{ - FileHandle_stub fh1; - ATCmdParser at(&fh1, "\r", 8); - - //parse valid char - char table1[] = "s"; - at.flush(); - filehandle_stub_table = table1; - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - char c; - EXPECT_TRUE(at.recv("%c", &c)); - EXPECT_EQ(c, 's'); - - //too large response - char table2[] = "1234567890\n"; - at.flush(); - filehandle_stub_table = table2; - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - EXPECT_FALSE(at.recv("123456789%c\n", &c)); - - //back to normal buffer - ATCmdParser at1(&fh1); - at1.flush(); - filehandle_stub_table = table2; - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - EXPECT_TRUE(at1.recv("123456789%c\n", &c)); - - char table3[] = "s\r\n\0"; - at1.flush(); - filehandle_stub_table = table3; - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - EXPECT_TRUE(at.recv("%c", &c)); - EXPECT_EQ(c, 's'); - - char table4[] = "s 1 E test\r\n"; - char text[5]; - int hexval; - int intval; - at1.flush(); - filehandle_stub_table = table4; - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - EXPECT_TRUE(at1.recv("%c %d %x %s", &c, &intval, &hexval, &text)); - EXPECT_EQ(c, 's'); - EXPECT_EQ(intval, 1); - EXPECT_EQ(hexval, 0xE); - EXPECT_EQ(!memcmp(text, "test", 4), 0); - - char table5[] = "s 1 E test\r\nt 2 F tes2\r\n"; - char c1; - char text1[5]; - int hexval1; - int intval1; - at1.flush(); - filehandle_stub_table = table5; - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - - expected_oob_callback = true; - at1.oob("s", &urc_callback); - EXPECT_TRUE(at1.recv("%c %d %x %s\r\n%c %d %x %s\r\n", &c, &intval, &hexval, &text, &c, &intval, &hexval, &text)); - expected_oob_callback = false; - EXPECT_EQ(c, 't'); - EXPECT_EQ(intval, 2); - EXPECT_EQ(hexval, 0xF); - EXPECT_EQ(memcmp(text, "tes2", 4), 0); - -} - -TEST_F(test_ATCmdParser, test_ATCmdParser_scanf) -{ - FileHandle_stub fh1; - ATCmdParser at(&fh1, "\r"); - - //parse valid char - char table1[] = "s"; - at.flush(); - filehandle_stub_table = table1; - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - char c; - EXPECT_TRUE(at.scanf("%c", &c)); - EXPECT_EQ(c, 's'); - - //back to normal buffer - char table2[] = "1234567890\n"; - at.flush(); - filehandle_stub_table = table2; - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - EXPECT_TRUE(at.scanf("123456789%c\n", &c)); - - char table3[] = "s\r\n\0"; - at.flush(); - filehandle_stub_table = table3; - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - EXPECT_TRUE(at.scanf("%c", &c)); - EXPECT_EQ(c, 's'); - - char table4[] = "s 1 E test\r\n"; - char text[5]; - memset(text, 0, 5); - int hexval; - int intval; - at.flush(); - filehandle_stub_table = table4; - filehandle_stub_table_pos = 0; - mbed_poll_stub::revents_value = POLLIN; - mbed_poll_stub::int_value = 1; - EXPECT_TRUE(at.scanf("%c %d %x %s", &c, &intval, &hexval, &text)); - EXPECT_EQ(c, 's'); - EXPECT_EQ(intval, 1); - EXPECT_EQ(hexval, 0xE); - EXPECT_EQ(!memcmp(text, "test", 4), 0); - -} - - diff --git a/UNITTESTS/platform/ATCmdParser/unittest.cmake b/UNITTESTS/platform/ATCmdParser/unittest.cmake deleted file mode 100644 index de19302..0000000 --- a/UNITTESTS/platform/ATCmdParser/unittest.cmake +++ /dev/null @@ -1,16 +0,0 @@ -#################### -# UNIT TESTS -#################### - -# Source files -set(unittest-sources - ../platform/source/ATCmdParser.cpp -) - -# Test files -set(unittest-test-sources - platform/ATCmdParser/test_ATCmdParser.cpp - stubs/FileHandle_stub.cpp - stubs/mbed_assert_stub.cpp - stubs/mbed_poll_stub.cpp -) diff --git a/UNITTESTS/platform/CircularBuffer/test_CircularBuffer.cpp b/UNITTESTS/platform/CircularBuffer/test_CircularBuffer.cpp deleted file mode 100644 index 5286701..0000000 --- a/UNITTESTS/platform/CircularBuffer/test_CircularBuffer.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 "platform/CircularBuffer.h" - -class TestCircularBuffer : public testing::Test { -protected: - mbed::CircularBuffer *buf; - - virtual void SetUp() - { - buf = new mbed::CircularBuffer; - } - - virtual void TearDown() - { - delete buf; - } -}; - -TEST_F(TestCircularBuffer, constructor) -{ - EXPECT_TRUE(buf); -} diff --git a/UNITTESTS/platform/CircularBuffer/unittest.cmake b/UNITTESTS/platform/CircularBuffer/unittest.cmake deleted file mode 100644 index 34187f4..0000000 --- a/UNITTESTS/platform/CircularBuffer/unittest.cmake +++ /dev/null @@ -1,11 +0,0 @@ - -#################### -# UNIT TESTS -#################### - -set(unittest-sources -) - -set(unittest-test-sources - platform/CircularBuffer/test_CircularBuffer.cpp -) diff --git a/platform/ATCmdParser.h b/platform/ATCmdParser.h deleted file mode 100644 index 0e7f92c..0000000 --- a/platform/ATCmdParser.h +++ /dev/null @@ -1,304 +0,0 @@ -/* Copyright (c) 2017-2019 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. - * - * @section DESCRIPTION - * - * Parser for the AT command syntax - * - */ -#ifndef MBED_ATCMDPARSER_H -#define MBED_ATCMDPARSER_H - -#include -#include "platform/Callback.h" -#include "platform/NonCopyable.h" -#include "platform/FileHandle.h" - -namespace mbed { -/** \addtogroup platform-public-api Platform */ -/** @{*/ -/** - * \defgroup platform_ATCmdParser ATCmdParser class - * @{ - */ - -/** - * Parser class for parsing AT commands - * - * Here are some examples: - * @code - * BufferedSerial serial = BufferedSerial(D1, D0); - * ATCmdParser at = ATCmdParser(&serial, "\r\n"); - * int value; - * char buffer[100]; - * - * at.send("AT") && at.recv("OK"); - * at.send("AT+CWMODE=%d", 3) && at.recv("OK"); - * at.send("AT+CWMODE?") && at.recv("+CWMODE:%d\r\nOK", &value); - * at.recv("+IPD,%d:", &value); - * at.read(buffer, value); - * at.recv("OK"); - * @endcode - */ - -class ATCmdParser : private NonCopyable { -private: - // File handle - // Not owned by ATCmdParser - FileHandle *_fh; - - int _buffer_size; - char *_buffer; - int _timeout; - - // Parsing information - const char *_output_delimiter; - int _output_delim_size; - int _oob_cb_count; - char _in_prev; - bool _dbg_on; - bool _aborted; - - struct oob { - unsigned len; - const char *prefix; - mbed::Callback cb; - oob *next; - }; - oob *_oobs; - - /** - * Receive an AT response - * - * Receives a formatted response using scanf style formatting - * @see scanf - * - * Responses are parsed line at a time. - * If multiline is set to false parse only one line otherwise parse multiline response - * Any received data that does not match the response is ignored until - * a timeout occurs. - * - * @param response scanf-like format string of response to expect - * @param ... all scanf-like arguments to extract from response - * @param multiline determinate if parse one or multiple lines. - * @return number of bytes read or -1 on failure - */ - int vrecvscanf(const char *response, std::va_list args, bool multiline); - -public: - - /** - * Constructor - * - * @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), _oob_cb_count(0), _in_prev(0), _aborted(false), _oobs(NULL) - { - _buffer = new char[buffer_size]; - set_timeout(timeout); - set_delimiter(output_delimiter); - debug_on(debug); - } - - /** - * Destructor - */ - ~ATCmdParser() - { - while (_oobs) { - struct oob *oob = _oobs; - _oobs = oob->next; - delete oob; - } - delete[] _buffer; - } - - /** - * Allows timeout to be changed between commands - * - * @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) - { - _timeout = timeout; - } - - /** - * Sets 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) - { - _output_delimiter = output_delimiter; - _output_delim_size = strlen(output_delimiter); - } - - /** - * Allows traces from modem to be turned on or off - * - * @param on Set as 1 to turn on traces and 0 to disable traces. - */ - void debug_on(uint8_t on) - { - _dbg_on = (on) ? 1 : 0; - } - - /** - * Sends an AT command - * - * Sends a formatted command using printf style formatting - * @see printf - * - * @param command printf-like format string of command to send which - * is appended with a newline - * @param ... all printf-like arguments to insert into command - * @return true only if command is successfully sent - */ - bool send(const char *command, ...) MBED_PRINTF_METHOD(1, 2); - - bool vsend(const char *command, std::va_list args); - - /** - * Receive an AT response - * - * Receives a formatted response using scanf style formatting - * @see scanf - * - * Responses are parsed line at a time. - * Any received data that does not match the response is ignored until - * a timeout occurs. - * - * @param response scanf-like format string of response to expect - * @param ... all scanf-like arguments to extract from response - * @return true only if response is successfully matched - */ - bool recv(const char *response, ...) MBED_SCANF_METHOD(1, 2); - - bool vrecv(const char *response, std::va_list args); - - /** - * Write a single byte to the underlying stream - * - * @param c The byte to write - * @return The byte that was written or -1 during a timeout - */ - int putc(char c); - - /** - * Get a single byte from the underlying stream - * - * @return The byte that was read or -1 during a timeout - */ - int getc(); - - /** - * Write an array of bytes to the underlying stream - * - * @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); - - /** - * Read an array of bytes from the underlying stream - * - * @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); - - /** - * Direct printf to underlying stream - * @see 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, std::va_list args); - - /** - * Direct scanf on underlying stream - * This function does not itself match whitespace in its format string, so \n is not significant to it. - * It should be used only when certain string is needed or format ends with certain character, otherwise - * it will fill the output with one character. - * @see 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, 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 - * @note out-of-band data is only processed during a scanf call - */ - void oob(const char *prefix, mbed::Callback func); - - /** - * @brief remove_oob Removes oob callback handler - * @param prefix Prefix to identify oob to be removed. - */ - void remove_oob(const char *prefix); - - /** - * Flushes the underlying stream - */ - void flush(); - - /** - * Abort current recv - * - * Can be called from out-of-band handler to interrupt the current - * recv operation. - */ - void abort(); - - /** - * Process out-of-band data - * - * Process out-of-band data in the receive buffer. This function - * returns immediately if there is no data to process. - * - * @return true if out-of-band data processed, false otherwise - */ - bool process_oob(void); -}; - -/**@}*/ - -/**@}*/ - -} //namespace mbed - -#endif //MBED_ATCMDPARSER_H diff --git a/platform/CThunk.h b/platform/CThunk.h deleted file mode 100644 index 2c9c751..0000000 --- a/platform/CThunk.h +++ /dev/null @@ -1,171 +0,0 @@ -/* Copyright (c) 2014-2019 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. - */ - - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_CThunk CThunk class - * @{ - */ - -/* General C++ Object Thunking class - * - * - allows direct callbacks to non-static C++ class functions - * - keeps track for the corresponding class instance - * - supports an optional context parameter for the called function - * - ideally suited for class object receiving interrupts (NVIC_SetVector) - */ - -#ifndef __CTHUNK_H__ -#define __CTHUNK_H__ - -#include "platform/internal/CThunkBase.h" - -/** - * Class for created a pointer with data bound to it - * - * @note Synchronization level: Not protected - */ -template -class CThunk: private CThunkBase { -public: - typedef void (T::*CCallbackSimple)(void); - typedef void (T::*CCallback)(void *context); - - inline CThunk(T *instance) - { - init(instance, NULL, NULL); - } - - inline CThunk(T *instance, CCallback callback) - { - init(instance, callback, NULL); - } - - ~CThunk() - { - if (_entry != NULL) { - cthunk_free(_entry); - _entry = NULL; - } - } - - inline CThunk(T *instance, CCallbackSimple callback) - { - init(instance, (CCallback)callback, NULL); - } - - inline CThunk(T &instance, CCallback callback) - { - init(instance, callback, NULL); - } - - inline CThunk(T &instance, CCallbackSimple callback) - { - init(instance, (CCallback)callback, NULL); - } - - inline CThunk(T &instance, CCallback callback, void *context) - { - init(instance, callback, context); - } - - inline void callback(CCallback callback) - { - _callback = callback; - } - - inline void callback(CCallbackSimple callback) - { - _callback_simple = callback; - } - - inline void context(void *context) - { - _context = context; - } - - inline void context(uint32_t context) - { - _context = (void *)context; - } - - inline uint32_t entry(void) - { - if (_entry == NULL) { - _entry = cthunk_alloc(this); - } - return (uint32_t)_entry; - } - - /* get thunk entry point for connecting rhunk to an IRQ table */ - inline operator CThunkEntry(void) - { - return (CThunkEntry)entry(); - } - - /* get thunk entry point for connecting rhunk to an IRQ table */ - inline operator uint32_t(void) - { - return entry(); - } - - /* simple test function */ - inline void call(void) - { - (((CThunkEntry)(entry()))()); - } - -private: - T *_instance; - void *_context; - union { - CCallbackSimple _callback_simple; - CCallback _callback; - }; - - CThunkEntry _entry; - - static void trampoline(CThunkBase *base) - { - CThunk *self = static_cast*>(base); - T *instance = self->_instance; - void *context = self->_context; - CCallback callback = self->_callback; - - if (instance && callback) { - (instance->*callback)(context); - } - } - - inline void init(T *instance, CCallback callback, void *context) - { - _instance = instance; - _context = context; - _callback = callback; - _trampoline = &trampoline; - _entry = 0; - } -}; - -/**@}*/ - -/**@}*/ - -#endif/*__CTHUNK_H__*/ - diff --git a/platform/Callback.h b/platform/Callback.h deleted file mode 100644 index e76a4f1..0000000 --- a/platform/Callback.h +++ /dev/null @@ -1,838 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_CALLBACK_H -#define MBED_CALLBACK_H - -#include -#include -#include -#include -#include "platform/mbed_assert.h" -#include "platform/mbed_toolchain.h" -#include -#include - -// Controlling switches from config: -// MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - support storing non-trivial function objects -// MBED_CONF_PLATFORM_CALLBACK_COMPARABLE - support memcmp comparing stored objects (requires zero padding) - -#ifdef __ICCARM__ -/* Force platform.callback-nontrivial for IAR */ -#undef MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL -#define MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 1 -#endif - - -namespace mbed { -/** \addtogroup platform-public-api */ -/** @{*/ -/** - * \defgroup platform_Callback Callback class - * @{ - */ - -/** Callback class based on template specialization - * - * @note Synchronization level: Not protected - */ -template -class Callback; - -namespace detail { - -/* Convert pointer-to-member type to member type */ -template -struct member_type { }; - -template -struct member_type : mstd::type_identity { }; - -template -using member_type_t = typename member_type::type; - -/* Remove cv-qualifiers and lvalue ref-qualifiers */ -/* Not rvalue - we store the function object, so are always going to call it on an lvalue */ -template -struct unqualify_fn { }; - -// *INDENT-OFF* -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -#if __cplusplus >=201703 || __cpp_noexcept_function_type >= 201510 -/* We have to spell out all c/v/ref/noexcept versions here, as specialization needs exact type match */ -/* Compare to callback() and deduction guides, where dropping the noexcept is a permitted conversion */ -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -template -struct unqualify_fn : mstd::type_identity { }; -#endif - -template -using unqualify_fn_t = typename unqualify_fn::type; - -template ::value, int> = 0> -R invoke_r(F&& f, Args&&... args) -{ - return mstd::invoke(std::forward(f), std::forward(args)...); -} - -template ::value, int> = 0> -R invoke_r(F&& f, Args&&... args) -{ - mstd::invoke(std::forward(f), std::forward(args)...); -} - -template -struct can_null_check : - mstd::disjunction< - std::is_function>, - std::is_member_pointer - > { -}; -// *INDENT-ON* - -struct [[gnu::may_alias]] CallbackBase { - // Storage is sufficient to hold at least a pointer to member - // function, and an object pointer. - struct _model_function_object { - struct _class; - void (_class::*_methodfunc)(int); - void *obj; - }; - - /* Notes on the [[gnu::may_alias]] attribute here. - * - * The CallbackBase::Store is subject to aliasing problems if ever copied via a trivial copy. - * This issue is described here: - * - * https://answers.launchpad.net/gcc-arm-embedded/+question/686870/+index - * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0593r5.html - * - * The paper p0593 proposes to solve the problem via a language Defect Report, which would make this - * code valid - it would become legal to copy a trivial object into char array storage. (But not - * aligned_storage_t, as of version 5 - I've suggested a revision). - * - * Real-life problems have only been seen in GCC when the code used aligned_storage_t. - * - * The libstdc++ implementation of std::function uses the [[gnu::may_alias]] attribute itself to avoid - * problems when it swaps locally-stored functors; we need it for copy-assignment too. - * - * It appears [[gnu::may_alias]] doesn't work through composition - it's not sufficent to mark just the - * `Store` type, we have to mark the whole `Callback` if we're going to let the compiler - * implicitly define the trivial copy for it. This potentially could lead to an issue if a `Callback` - * was used in a trivially-copyable type itself, but this seems an unlikely use case. The p0593r5 - * change would, if correctly implemented, work in composition. - * - * Although, to further increase the confusion, it appears that using a character array does work - * fine without may_alias, while aligned_storage_t does not. I've seen a suggestion that GCC 8 - * may have implicit "may_alias" on character arrays, rendering the attribute in std::function - * and here redundant on current GCC: - * - * https://gcc.gnu.org/ml/gcc-help/2017-06/msg00102.html - * - * For maximum safety, this version now avoids aligned_storage_t, and also has the possibly-redundant - * attribute at each level. - * - * C++17 says that implementations ignore unrecognized attributes, and IAR+clang comply with this - * even in C++14 mode, so we add [[gnu::may_alias]] unconditionally. - */ - struct alignas(_model_function_object) [[gnu::may_alias]] Store { - char data[sizeof(_model_function_object)]; - }; - Store _storage; - -#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - // Dynamically dispatched operations - const struct ops { - void (*call)(); // type-erased function pointer - void (*copy)(Store &, const Store &); - void (*dtor)(Store &); - } *_ops; - - // Control - using Control = const ops *; - - // Construct as empty - CallbackBase(std::nullptr_t) noexcept : _ops(nullptr) { } -#else - void (*_call)(); // type-erased function pointer - - using Control = void(*)(); - - // Construct as empty - CallbackBase(std::nullptr_t) noexcept : _call(nullptr) { } -#endif - - // Default constructor - no initialization - CallbackBase() = default; - - Control &control() - { -#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - return _ops; -#else - return _call; -#endif - } - - const Control &control() const - { -#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - return _ops; -#else - return _call; -#endif - } - - auto call_fn() const - { -#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - return _ops->call; -#else - return _call; -#endif - } - - // Clear to empty - does not destroy - void clear() noexcept - { - // For copy efficiency we only zero out the operation pointer - // Therefore storage is undefined when we are empty. - // Callback-to-Callback comparison operator has to deal with this, - // but such comparisons are rare. Comparisons to empty are efficient. - control() = nullptr; - } - -#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - // Copy from another CallbackBase - assumes we are uninitialised - void copy(const CallbackBase &other) - { - _ops = other._ops; - if (_ops) { - _ops->copy(_storage, other._storage); - } - } -#else - void swap(CallbackBase &other) noexcept - { - std::swap(_storage, other._storage); - std::swap(_call, other._call); - } -#endif - - // Destroy anything we hold - does not reset, so we are in undefined state afterwards. - // Must be followed by copy, move, reset, or destruction of the CallbackBase - void destroy() - { -#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - if (_ops) { - _ops->dtor(_storage); - } -#endif - } - -#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - // Copy construct F into storage - template - static void target_copy(Store &d, const Store &p) - { - const F &f = reinterpret_cast(p); - new (&d) F(f); - } - - // Destroy F in storage - template - static void target_dtor(Store &p) - { - F &f = reinterpret_cast(p); - f.~F(); - } - - // Trivial copy construction into storage - static void trivial_target_copy(Store &d, const Store &p) noexcept - { - std::memcpy(&d, &p, sizeof d); - } - - // Trivial destruction in storage - static void trivial_target_dtor(Store &p) noexcept - { - } -#endif -}; - -} - -/** Callback class based on template specialization - * - * @note Synchronization level: Not protected - */ -template -class Callback : private detail::CallbackBase { -public: - using result_type = R; - - /** Create an empty Callback - */ - Callback() noexcept : CallbackBase(nullptr) { } - - /** Create an empty Callback - */ - Callback(std::nullptr_t) noexcept : Callback() { } - -#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - /** Copy a Callback - * @param other The Callback to copy - */ - Callback(const Callback &other) : CallbackBase() - { - copy(other); - } - - /** Move a Callback - * @param other The Callback to move - */ - Callback(Callback &&other) : CallbackBase() - { - // Move constructor exists to ensure that it gets selected - // in preference to the universal constructor form. - copy(other); - } -#else // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - Callback(const Callback &other) = default; - Callback(Callback &&other) = default; -#endif // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - - /** Create a Callback with a member function - * @param obj Pointer to object to invoke member function on - * @param method Member function to attach - */ - template::value, int> = 0> - Callback(Obj obj, Method method) : CallbackBase() - { - generate([obj, method](ArgTs... args) { - return detail::invoke_r(method, obj, std::forward(args)...); - }); - } - - /** Create a Callback with a static function and bound pointer - * @param func Static function to attach - * @param arg Pointer argument to function - */ - template::value, int> = 0> - Callback(Fn func, BoundArg arg) : CallbackBase() - { - generate([func, arg](ArgTs... args) { - return detail::invoke_r(func, arg, std::forward(args)...); - }); - } - - // *INDENT-OFF* - /** Create a Callback with a function object - * @param f Function object to attach - * @note The function object is limited to a a few words of storage - */ - template ::value && - mstd::is_invocable_r::value, int> = 0> - Callback(F f) : CallbackBase() - { - static_assert(std::is_copy_constructible::value, "Callback F must be CopyConstructible"); - generate(std::move(f)); - } - - /** Create a Callback with a function pointer - * @param f Function pointer to attach - */ - template ::value && - mstd::is_invocable_r::value, int> = 0> - Callback(F f) : CallbackBase() - { - static_assert(std::is_copy_constructible::value, "Callback F must be CopyConstructible"); - if (!f) { - clear(); - } else { - generate(std::move(f)); - } - } - // *INDENT-ON* - - /** Destroy a callback - */ -#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - ~Callback() - { - destroy(); - } -#else - ~Callback() = default; -#endif - - /** Swap a callback - */ - void swap(Callback &that) noexcept - { -#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - if (this != &that) { - Callback temp(std::move(*this)); - *this = std::move(that); - that = std::move(temp); - } -#else - CallbackBase::swap(that); -#endif - } - -#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - /** Assign a callback - */ - Callback &operator=(const Callback &that) - { - // C++ standard says to use swap, but that's overkill with no exceptions - // Callback(f).swap(*this); - if (this != &that) { - destroy(); - copy(that); - } - - return *this; - } - - /** Assign a callback - */ - Callback &operator=(Callback &&that) - { - if (this != &that) { - destroy(); - copy(that); - } - - return *this; - } -#else // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - Callback &operator=(const Callback &that) = default; - Callback &operator=(Callback &&that) = default; -#endif // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - - /** Assign a callback - */ - // C++ std::function lacks the is_same restriction here, which would mean non-const lvalue references hit this, - // rather than the normal copy assignment (`F &&` is a better match for `Callback &` than `const Callback &`). - // Wouldn't matter if both used the swap form, but having cut it down, for code size want to ensure we don't use this - // instead of copy assignment. (If nontrivial disabled, definitely want to use the default copy assignment, and - // if nontrivial enabled, we know this doesn't handle self-assignment). - // *INDENT-OFF* - template ::value && - !mstd::is_same, Callback>::value>> - Callback &operator=(F &&f) - { - // C++ standard says to use swap, but that's overkill with no exceptions - // Callback(std::forward(that)).swap(*this); - this->~Callback(); - new (this) Callback(std::forward(f)); - return *this; - } - // *INDENT-ON* - - template - Callback &operator=(std::reference_wrapper f) noexcept - { - // C++ standard says to use swap, but that's overkill with no exceptions - // Callback(f).swap(*this); - this->~Callback(); - new (this) Callback(f); - return *this; - } - - /** Empty a callback - */ - Callback &operator=(std::nullptr_t) noexcept - { - destroy(); - clear(); - - return *this; - } - - /** Call the attached function - */ - R call(ArgTs... args) const - { - MBED_ASSERT(bool(*this)); - auto op_call = reinterpret_cast(call_fn()); - return op_call(this, args...); - } - - /** Call the attached function - */ - R operator()(ArgTs... args) const - { - return call(args...); - } - - /** Test if function has been assigned - */ - explicit operator bool() const noexcept - { - return control(); - } - -#if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE - /** Test for equality - * - * @note This only compares stored objects byte-wise using memcmp - * after checking that they're the same type. It does *not* use - * any equality operator defined for the class. - * - * @note This is an extension compared to std::function, and supporting - * it requires extra code even if the comparison is never used. - * Avoid using this operator if possible, so that the option - * `platform.callback-comparable` can be turned off to save ROM. - */ - friend bool operator==(const Callback &l, const Callback &r) noexcept - { - if (l.control() != r.control()) { - /* Type of stored object differs */ - return false; - } - if (!l) { - /* Both must be empty, as we checked the types match. Do not - * check storage in this case - this simplifies clear(), and - * clears are far more common than callback comparison. - */ - return true; - } - return memcmp(&l._storage, &r._storage, sizeof(Store)) == 0; - } -#endif - - /** Test for emptiness - */ - friend bool operator==(const Callback &f, std::nullptr_t) noexcept - { - return !f; - } - - /** Test for emptiness - */ - friend bool operator==(std::nullptr_t, const Callback &f) noexcept - { - return !f; - } - -#if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE - /** Test for inequality - * - * @see operator==(const Callback &l, const Callback &r) - */ - friend bool operator!=(const Callback &l, const Callback &r) noexcept - { - return !(l == r); - } -#endif - - /** Test for non-emptiness - */ - friend bool operator!=(const Callback &f, std::nullptr_t) noexcept - { - return bool(f); - } - - /** Test for non-emptiness - */ - friend bool operator!=(std::nullptr_t, const Callback &f) noexcept - { - return bool(f); - } - - /** Static thunk for passing as C-style function - * @param func Callback to call passed as void pointer - * @param args Arguments to be called with function func - * @return the value as determined by func which is of - * type and determined by the signature of func - */ - static R thunk(void *func, ArgTs... args) - { - return static_cast(func)->call(args...); - } - -private: - using call_type = R(const CallbackBase *, ArgTs...); - - // *INDENT-OFF* - // Generate operations for function object - // Storage assumed to be uninitialised - destructor should have already been called if it was previously used - // When generating, function object should always be moved - template ::value>> - void generate(F &&f) - { -#ifndef __ICCARM__ /* This assert fails on IAR for unknown reason */ - static_assert(std::is_same), call_type>::value, "Call type mismatch"); -#endif - static_assert(sizeof(Callback) == sizeof(CallbackBase), "Callback should be same size as CallbackBase"); - static_assert(std::is_trivially_copyable::value, "CallbackBase expected to be TriviallyCopyable"); - - // Set the control pointer -#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - // Generates one static ops for each tuple - // But the functions used for copy/move/dtor depend only on F, and even then only if non-trivial. - // `call` is type-erased - we cast from our call_type to the void (*)(void) in CallbackBase - // This should be a ROMmed constant table, but formally it can't be constexpr because of the reinterpret_cast :( - static const ops ops = { - reinterpret_cast(target_call), - std::is_trivially_copy_constructible::value ? trivial_target_copy : target_copy, - std::is_trivially_destructible::value ? trivial_target_dtor : target_dtor, - }; - _ops = &ops; -#else // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - // Avoid the need for the const ops table - just one function pointer in the Callback itself - _call = reinterpret_cast(target_call); - static_assert(std::is_trivially_copyable::value, "F must be TriviallyCopyable. Turn on Mbed configuration option 'platform.callback-nontrivial' to use more complex function objects"); - static_assert(std::is_trivially_copyable::value, "Callback expected to be TriviallyCopyable"); -#endif // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - - // Move the functor into storage - static_assert(sizeof(F) <= sizeof(Store) && alignof(F) <= alignof(Store), - "Type F must not exceed the size of the Callback class"); - new (&_storage) F(std::move(f)); - -#if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE - // Zero out any padding - required for Callback-to-Callback comparisons. - if (sizeof(F) < sizeof(Store)) { - std::memset(reinterpret_cast(&_storage) + sizeof(F), 0, sizeof(Store) - sizeof(F)); - } -#endif - } - // *INDENT-ON* - - // Target call routine - custom needed for each tuple - template - static R target_call(const CallbackBase *p, ArgTs... args) - { - // Need for const_cast here correlates to a std::function bug - see P0045 and N4159 - F &f = const_cast(reinterpret_cast(p->_storage)); - return detail::invoke_r(f, std::forward(args)...); - } -}; - -// Internally used event type -using event_callback_t = Callback; - -template -void swap(Callback &lhs, Callback &rhs) noexcept -{ - lhs.swap(rhs); -} - -/** Create a callback class with type inferred from the arguments - * - * @param func Static function to attach - * @return Callback with inferred type - */ -template -Callback callback(R(*func)(ArgTs...) = nullptr) noexcept -{ - return Callback(func); -} - -/** Create a callback class with type inferred from the arguments - * - * @param func Static function to attach - * @return Callback with inferred type - */ -template -Callback callback(const Callback &func) -{ - return Callback(func); -} - -/** Create a callback class with type inferred from the arguments - * - * @param func Static function to attach - * @return Callback with inferred type - */ -template -Callback callback(Callback &&func) noexcept -{ - return Callback(std::move(func)); -} - -/** 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 inferred type - */ -template -Callback callback(U *obj, R(T::*method)(ArgTs...)) noexcept -{ - return Callback(obj, method); -} - -template -Callback callback(U *obj, R(T::*method)(ArgTs...) &) noexcept -{ - return Callback(obj, method); -} - -template -Callback callback(const U *obj, R(T::*method)(ArgTs...) const) noexcept -{ - return Callback(obj, method); -} - -template -Callback callback(const U *obj, R(T::*method)(ArgTs...) const &) noexcept -{ - return Callback(obj, method); -} - -template -Callback callback(volatile U *obj, R(T::*method)(ArgTs...) volatile) noexcept -{ - return Callback(obj, method); -} - -template -Callback callback(volatile U *obj, R(T::*method)(ArgTs...) volatile &) noexcept -{ - return Callback(obj, method); -} - -template -Callback callback(const volatile U *obj, R(T::*method)(ArgTs...) const volatile) noexcept -{ - return Callback(obj, method); -} - -template -Callback callback(const volatile U *obj, R(T::*method)(ArgTs...) const volatile &) noexcept -{ - return Callback(obj, method); -} - -/** 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 inferred type - */ -template -Callback callback(R(*func)(T *, ArgTs...), U *arg) noexcept -{ - return Callback(func, arg); -} - -template -Callback callback(R(*func)(const T *, ArgTs...), const U *arg) noexcept -{ - return Callback(func, arg); -} - -template -Callback callback(R(*func)(volatile T *, ArgTs...), volatile U *arg) noexcept -{ - return Callback(func, arg); -} - -template -Callback callback(R(*func)(const volatile T *, ArgTs...), const volatile U *arg) noexcept -{ - return Callback(func, arg); -} - -/** Create a Create a callback class with type inferred from the arguments - * @param f Function object to attach - * @note The function object is limited to a single word of storage - */ -template -Callback::operator())>>> -callback(F &&f) -{ - return Callback::operator())>>>(std::forward(f)); -} - -#if __cplusplus >= 201703 || __cpp_deduction_guides >= 201703 -/* Deduction guides that can replace callback() helper */ -template -Callback(R(*)(Args...)) -> Callback; -template -Callback(F) -> Callback>>; -template -Callback(U *obj, R(T::*method)(ArgTs...)) -> Callback; -template -Callback(U *obj, R(T::*method)(ArgTs...) &) -> Callback; -template -Callback(const U *obj, R(T::*method)(ArgTs...) const) -> Callback; -template -Callback(const U *obj, R(T::*method)(ArgTs...) const &) -> Callback; -template -Callback(volatile U *obj, R(T::*method)(ArgTs...) volatile) -> Callback; -template -Callback(volatile U *obj, R(T::*method)(ArgTs...) volatile &) -> Callback; -template -Callback(const volatile U *obj, R(T::*method)(ArgTs...) const volatile) -> Callback; -template -Callback(const volatile U *obj, R(T::*method)(ArgTs...) const volatile &) -> Callback; -template -Callback(R(*func)(T *, ArgTs...), U *arg) -> Callback; -template -Callback(R(*func)(const T *, ArgTs...), const U *arg) -> Callback; -template -Callback(R(*func)(volatile T *, ArgTs...), volatile U *arg) -> Callback; -template -Callback(R(*func)(const volatile T *, ArgTs...), const volatile U *arg) -> Callback; -#endif - -/**@}*/ - -/**@}*/ - -} // namespace mbed - -#endif diff --git a/platform/CircularBuffer.h b/platform/CircularBuffer.h deleted file mode 100644 index c167444..0000000 --- a/platform/CircularBuffer.h +++ /dev/null @@ -1,216 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2015-2019 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_CIRCULARBUFFER_H -#define MBED_CIRCULARBUFFER_H - -#include -#include "platform/mbed_critical.h" -#include "platform/mbed_assert.h" - -namespace mbed { - -namespace internal { -/* Detect if CounterType of the Circular buffer is of unsigned type. */ -template -struct is_unsigned { - static const bool value = false; -}; -template<> -struct is_unsigned { - static const bool value = true; -}; -template<> -struct is_unsigned { - static const bool value = true; -}; -template<> -struct is_unsigned { - static const bool value = true; -}; -template<> -struct is_unsigned { - static const bool value = true; -}; -template<> -struct is_unsigned { - static const bool value = true; -}; -} - -/** \addtogroup platform-public-api */ -/** @{*/ -/** - * \defgroup platform_CircularBuffer CircularBuffer functions - * @{ - */ - -/** Templated Circular buffer class - * - * @note Synchronization level: Interrupt safe - * @note CounterType must be unsigned and consistent with BufferSize - */ -template -class CircularBuffer { -public: - CircularBuffer() : _head(0), _tail(0), _full(false) - { - MBED_STATIC_ASSERT( - internal::is_unsigned::value, - "CounterType must be unsigned" - ); - - MBED_STATIC_ASSERT( - (sizeof(CounterType) >= sizeof(uint32_t)) || - (BufferSize < (((uint64_t) 1) << (sizeof(CounterType) * 8))), - "Invalid BufferSize for the CounterType" - ); - } - - ~CircularBuffer() - { - } - - /** Push the transaction to the buffer. This overwrites the buffer if it's - * full - * - * @param data Data to be pushed to the buffer - */ - void push(const T &data) - { - core_util_critical_section_enter(); - if (full()) { - _tail++; - if (_tail == BufferSize) { - _tail = 0; - } - } - _pool[_head++] = data; - if (_head == BufferSize) { - _head = 0; - } - if (_head == _tail) { - _full = true; - } - core_util_critical_section_exit(); - } - - /** Pop the transaction from the buffer - * - * @param data Data to be popped from the buffer - * @return True if the buffer is not empty and data contains a transaction, false otherwise - */ - bool pop(T &data) - { - bool data_popped = false; - core_util_critical_section_enter(); - if (!empty()) { - data = _pool[_tail++]; - if (_tail == BufferSize) { - _tail = 0; - } - _full = false; - data_popped = true; - } - core_util_critical_section_exit(); - return data_popped; - } - - /** Check if the buffer is empty - * - * @return True if the buffer is empty, false if not - */ - bool empty() const - { - core_util_critical_section_enter(); - bool is_empty = (_head == _tail) && !_full; - core_util_critical_section_exit(); - return is_empty; - } - - /** Check if the buffer is full - * - * @return True if the buffer is full, false if not - */ - bool full() const - { - core_util_critical_section_enter(); - bool full = _full; - core_util_critical_section_exit(); - return full; - } - - /** Reset the buffer - * - */ - void reset() - { - core_util_critical_section_enter(); - _head = 0; - _tail = 0; - _full = false; - core_util_critical_section_exit(); - } - - /** Get the number of elements currently stored in the circular_buffer */ - CounterType size() const - { - core_util_critical_section_enter(); - CounterType elements; - if (!_full) { - if (_head < _tail) { - elements = BufferSize + _head - _tail; - } else { - elements = _head - _tail; - } - } else { - elements = BufferSize; - } - core_util_critical_section_exit(); - return elements; - } - - /** Peek into circular buffer without popping - * - * @param data Data to be peeked from the buffer - * @return True if the buffer is not empty and data contains a transaction, false otherwise - */ - bool peek(T &data) const - { - bool data_updated = false; - core_util_critical_section_enter(); - if (!empty()) { - data = _pool[_tail]; - data_updated = true; - } - core_util_critical_section_exit(); - return data_updated; - } - -private: - T _pool[BufferSize]; - CounterType _head; - CounterType _tail; - bool _full; -}; - -/**@}*/ - -/**@}*/ - -} - -#endif diff --git a/platform/CriticalSectionLock.h b/platform/CriticalSectionLock.h deleted file mode 100644 index 3f9aa62..0000000 --- a/platform/CriticalSectionLock.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2017-2019 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_CRITICALSECTIONLOCK_H -#define MBED_CRITICALSECTIONLOCK_H - -#include "platform/mbed_toolchain.h" - -namespace mbed { -/** \addtogroup platform-public-api */ -/** @{*/ -/** - * \defgroup platform_CriticalSectionLock CriticalSectionLock functions - * @{ - */ - -/** RAII object for disabling, then restoring, interrupt state - * Usage: - * @code - * - * // RAII style usage - * unsigned int atomic_counter_increment(unsigned int &counter) { - * CriticalSectionLock lock; - * // Code in this block will run with interrupts disabled - * // Interrupts will be restored to their previous state automatically - * // at the end of function scope - * return ++counter; - * } - * - * // free locking usage - * unsigned int atomic_counter_decrement(unsigned int &counter) { - * CriticalSectionLock::enable(); - * // Code in this block will run with interrupts disabled - * counter--; - * CriticalSectionLock::disable(); // need explicitly to disable critical section lock - * // interrupts will be restored to their previous state here - * return counter; - * } - * - * @endcode - */ -class CriticalSectionLock { -public: - CriticalSectionLock(); - - ~CriticalSectionLock(); - - /** Mark the start of a critical section - */ - static void enable(); - - /** Mark the end of a critical section - */ - static void disable(); -}; - -/**@}*/ - -/**@}*/ - -} // namespace mbed - -#endif diff --git a/platform/DeepSleepLock.h b/platform/DeepSleepLock.h deleted file mode 100644 index c4841aa..0000000 --- a/platform/DeepSleepLock.h +++ /dev/null @@ -1,70 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017-2019 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_DEEPSLEEPLOCK_H -#define MBED_DEEPSLEEPLOCK_H - -#include -#include - -namespace mbed { -/** \addtogroup platform-public-api */ -/** @{*/ -/** - * \defgroup platform_DeepSleepLock DeepSleepLock functions - * @{ - */ - -/** RAII object for disabling, then restoring the deep sleep mode - * Usage: - * @code - * - * void f() { - * // some code here - * { - * DeepSleepLock lock; - * // Code in this block will run with the deep sleep mode locked - * } - * // deep sleep mode will be restored to their previous state - * } - * @endcode - */ -class DeepSleepLock { -private: - uint16_t _lock_count; - -public: - DeepSleepLock(); - - ~DeepSleepLock(); - - /** Mark the start of a locked deep sleep section - */ - void lock(); - - /** Mark the end of a locked deep sleep section - */ - void unlock(); -}; - -/**@}*/ - -/**@}*/ - - -} - -#endif diff --git a/platform/DirHandle.h b/platform/DirHandle.h deleted file mode 100644 index 4c49676..0000000 --- a/platform/DirHandle.h +++ /dev/null @@ -1,115 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_DIRHANDLE_H -#define MBED_DIRHANDLE_H - -#include -#include "platform/mbed_toolchain.h" -#include "platform/NonCopyable.h" - -namespace mbed { -/** \addtogroup platform-public-api */ -/** @{*/ -/** - * \defgroup platform_DirHandle DirHandle functions - * @{ - */ - - -/** 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 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 pointer returned by opendir("/") - * reflects this. - * - * @note to create a directory, @see Dir - * @note Synchronization level: Set by subclass - */ -class DirHandle : private NonCopyable { -public: - virtual ~DirHandle() {} - - /** Read the next directory entry - * - * @param ent The directory entry to fill out - * @return 1 on reading a filename, 0 at end of directory, negative error on failure - */ - virtual ssize_t read(struct dirent *ent) = 0; - - /** Close a directory - * - * @return 0 on success, negative error code on failure - */ - virtual int close() = 0; - - /** Set the current position of the directory - * - * @param offset Offset of the location to seek to, - * must be a value returned from tell - */ - virtual void seek(off_t offset) = 0; - - /** Get the current position of the directory - * - * @return Position of the directory that can be passed to rewind - */ - virtual off_t tell() = 0; - - /** Rewind the current position to the beginning of the directory - */ - virtual void rewind() = 0; - - /** Get the sizeof the directory - * - * @return Number of files in the directory - */ - virtual size_t size() - { - off_t off = tell(); - size_t size = 0; - struct dirent *ent = new struct dirent; - - rewind(); - while (read(ent) > 0) { - size += 1; - } - seek(off); - - delete ent; - return size; - } -}; - -/**@}*/ - -/**@}*/ -} // namespace mbed - -#endif /* MBED_DIRHANDLE_H */ diff --git a/platform/FileBase.h b/platform/FileBase.h deleted file mode 100644 index f4aac58..0000000 --- a/platform/FileBase.h +++ /dev/null @@ -1,76 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_FILEBASE_H -#define MBED_FILEBASE_H - -typedef int FILEHANDLE; - -#include "platform/platform.h" -#include "platform/SingletonPtr.h" -#include "platform/PlatformMutex.h" -#include "platform/NonCopyable.h" - -namespace mbed { - -typedef enum { - FilePathType, - FileSystemPathType -} PathType; - -/** \defgroup platform-public-api-file File - * \ingroup platform-public-api - */ - -/** - * \defgroup platform_FileBase FileBase class - * \ingroup platform-public-api-file - * @{ - */ - -/** Class FileBase - * - */ - -class FileBase : private NonCopyable { -public: - FileBase(const char *name, PathType t); - virtual ~FileBase(); - - const char *getName(void); - PathType getPathType(void); - - static FileBase *lookup(const char *name, unsigned int len); - - static FileBase *get(int n); - - void set_as_default(); - -private: - static FileBase *_head; - static FileBase *_default; - static SingletonPtr _mutex; - - FileBase *_next; - const char *const _name; - const PathType _path_type; -}; - -/**@}*/ - -} // namespace mbed - -#endif diff --git a/platform/FileHandle.h b/platform/FileHandle.h deleted file mode 100644 index b666301..0000000 --- a/platform/FileHandle.h +++ /dev/null @@ -1,280 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017-2019 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_FILEHANDLE_H -#define MBED_FILEHANDLE_H - -typedef int FILEHANDLE; - -#include -#include "platform/Callback.h" -#include "platform/mbed_poll.h" -#include "platform/platform.h" -#include "platform/NonCopyable.h" - -namespace mbed { - -/** - * \defgroup platform_FileHandle FileHandle functions - * \ingroup platform-public-api-file - * @{ - */ - - -/** Class FileHandle - * - * An abstract interface that represents operations on a file-like - * 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 - * @note Synchronization level: Set by subclass - */ -class FileHandle : private NonCopyable { -public: - virtual ~FileHandle() = default; - - /** Read the contents of a file into a buffer - * - * Devices acting as FileHandles should follow POSIX semantics: - * - * * 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 - * - * @param buffer The buffer to read in to - * @param size The number of bytes to read - * @return The number of bytes read, 0 at end of file, negative error on failure - */ - virtual ssize_t read(void *buffer, size_t size) = 0; - - /** Write the contents of a buffer to a file - * - * Devices acting as FileHandles should follow POSIX semantics: - * - * * if blocking, block until all data is written - * * 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 - * @return The number of bytes written, negative error on failure - */ - virtual ssize_t write(const void *buffer, size_t size) = 0; - - /** Move the file position to a given offset from from a given location - * - * @param offset The offset from whence to move to - * @param whence The start of where to seek - * SEEK_SET to start from beginning of file, - * SEEK_CUR to start from current position in file, - * SEEK_END to start from end of file - * @return The new offset of the file, negative error code on failure - */ - virtual off_t seek(off_t offset, int whence = SEEK_SET) = 0; - - /** Close a file - * - * @return 0 on success, negative error code on failure - */ - virtual int close() = 0; - - /** Flush any buffers associated with the file - * - * @return 0 on success, negative error code on failure - */ - virtual int sync() - { - return 0; - } - - /** Check if the file in an interactive terminal device - * - * @return True if the file is a terminal - * @return False if the file is not a terminal - * @return Negative error code on failure - */ - virtual int isatty() - { - return false; - } - - /** Get the file position of the file - * - * @note This is equivalent to seek(0, SEEK_CUR) - * - * @return The current offset in the file, negative error code on failure - */ - virtual off_t tell() - { - return seek(0, SEEK_CUR); - } - - /** Rewind the file position to the beginning of the file - * - * @note This is equivalent to seek(0, SEEK_SET) - */ - virtual void rewind() - { - seek(0, SEEK_SET); - } - - /** Get the size of the file - * - * @return Size of the file in bytes - */ - virtual off_t size(); - - /** Truncate or extend a file. - * - * The file's length is set to the specified value. The seek pointer is - * not changed. If the file is extended, the extended area appears as if - * it were zero-filled. - * - * @param length The requested new length for the file - * - * @return Zero on success, negative error code on failure - */ - virtual int truncate(off_t length) - { - return -EINVAL; - } - - /** 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 nonblocking mode. - * - * @return 0 on success - * @return Negative error code on failure - */ - virtual int set_blocking(bool blocking) - { - return blocking ? 0 : -ENOTTY; - } - - /** Check current blocking or nonblocking mode for file operations. - * - * @return true for blocking mode, false for nonblocking mode. - */ - virtual bool is_blocking() const - { - return true; - } - - /** Enable or disable input - * - * Control enabling of device for input. This is primarily intended - * for temporary power-saving; the overall ability of the device to operate for - * input and/or output may be fixed at creation time, but this call can - * allow input to be temporarily disabled to permit power saving without - * losing device state. - * - * @param enabled true to enable input, false to disable. - * - * @return 0 on success - * @return Negative error code on failure - */ - virtual int enable_input(bool enabled) - { - return -EINVAL; - } - - /** Enable or disable output - * - * Control enabling of device for output. This is primarily intended - * for temporary power-saving; the overall ability of the device to operate for - * input and/or output may be fixed at creation time, but this call can - * allow output to be temporarily disabled to permit power saving without - * losing device state. - * - * @param enabled true to enable output, false to disable. - * - * @return 0 on success - * @return Negative error code on failure - */ - virtual int enable_output(bool enabled) - { - return -EINVAL; - } - - /** Check for poll event flags - * 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. - * - * @returns bitmask of poll events that have occurred. - */ - virtual short poll(short events) const - { - // Possible default for real files - return POLLIN | POLLOUT; - } - - /** 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. - * - * @returns true if the FileHandle is writable. - */ - bool writable() const - { - return poll(POLLOUT) & POLLOUT; - } - - /** 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. - * - * @returns true when there is something available to read. - */ - bool readable() const - { - return poll(POLLIN) & POLLIN; - } - - /** Register a callback on state change of the file. - * - * The specified callback will be called on state changes such as when - * the file can be written to or read from. - * - * 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. - * - * The exact timing of when the registered function - * 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 - */ - virtual void sigio(Callback func) - { - //Default for real files. Do nothing for real files. - } -}; - -/**@}*/ - -} // namespace mbed - -#endif diff --git a/platform/FileLike.h b/platform/FileLike.h deleted file mode 100644 index 5f4409a..0000000 --- a/platform/FileLike.h +++ /dev/null @@ -1,52 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_FILELIKE_H -#define MBED_FILELIKE_H - -#include "platform/FileBase.h" -#include "platform/FileHandle.h" -#include "platform/NonCopyable.h" - -namespace mbed { -/** - * \defgroup platform_FileLike FileLike class - * \ingroup platform-public-api-file - * @{ - */ - -/** Class FileLike - * - * A file-like object is one that can be opened with fopen by - * fopen("/name", mode). - * - * @note Synchronization level: Set by subclass - */ -class FileLike : public FileHandle, public FileBase, private NonCopyable { -public: - /** Constructor FileLike - * - * @param name The name to use to open the file. - */ - FileLike(const char *name = NULL) : FileBase(name, FilePathType) {} - virtual ~FileLike() {} -}; - -/**@}*/ - -} // namespace mbed - -#endif diff --git a/platform/FilePath.h b/platform/FilePath.h deleted file mode 100644 index 1740a98..0000000 --- a/platform/FilePath.h +++ /dev/null @@ -1,64 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_FILEPATH_H -#define MBED_FILEPATH_H - -#include "platform/platform.h" - -#include "platform/FileSystemLike.h" -#include "platform/FileLike.h" - -namespace mbed { - -class FileSystem; - -/** - * \defgroup platform_FilePath FilePath class - * \ingroup platform-public-api-file - * @{ - */ - -/** Class FilePath - * - */ -class FilePath { -public: - /** Constructor FilePath - * - * @param file_path The path of file. - */ - FilePath(const char *file_path); - - const char *fileName(void); - - bool isFileSystem(void); - FileSystemLike *fileSystem(void); - - bool isFile(void); - FileLike *file(void); - bool exists(void); - -private: - const char *file_name; - FileBase *fb; -}; - -/**@}*/ - -} // namespace mbed - -#endif diff --git a/platform/FileSystemHandle.h b/platform/FileSystemHandle.h deleted file mode 100644 index ceedcd9..0000000 --- a/platform/FileSystemHandle.h +++ /dev/null @@ -1,109 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_FILESYSTEMHANDLE_H -#define MBED_FILESYSTEMHANDLE_H - -#include "platform/platform.h" - -#include "platform/FileHandle.h" -#include "platform/DirHandle.h" -#include "platform/NonCopyable.h" - -namespace mbed { -/** - * \defgroup platform_FileSystemHandle FileSystemHandle functions - * \ingroup platform-public-api-file - * @{ - */ - - -/** A filesystem-like object is one that can be used to open file-like - * objects though it by fopen("/name/filename", mode) - * - * Implementations must define at least open (the default definitions - * of the rest of the functions just return error values). - * - * @note Synchronization level: Set by subclass - */ -class FileSystemHandle : private NonCopyable { -public: - /** FileSystemHandle lifetime - */ - virtual ~FileSystemHandle() {} - - /** Open a file on the filesystem - * - * @param file Destination for the handle to a newly created file - * @param filename The name of the file to open - * @param flags The flags to open the file in, one of O_RDONLY, O_WRONLY, O_RDWR, - * bitwise or'd with one of O_CREAT, O_TRUNC, O_APPEND - * @return 0 on success, negative error code on failure - */ - virtual int open(FileHandle **file, const char *filename, int flags) = 0; - - /** Open a directory on the filesystem - * - * @param dir Destination for the handle to the directory - * @param path Name of the directory to open - * @return 0 on success, negative error code on failure - */ - virtual int open(DirHandle **dir, const char *path); - - /** Remove a file from the filesystem. - * - * @param path The name of the file to remove. - * @return 0 on success, negative error code on failure - */ - virtual int remove(const char *path); - - /** Rename a file in the filesystem. - * - * @param path The name of the file to rename. - * @param newpath The name to rename it to - * @return 0 on success, negative error code on failure - */ - virtual int rename(const char *path, const char *newpath); - - /** Store information about the file in a stat structure - * - * @param path The name of the file to find information about - * @param st The stat buffer to write to - * @return 0 on success, negative error code on failure - */ - virtual int stat(const char *path, struct stat *st); - - /** Create a directory in the filesystem. - * - * @param path The name of the directory to create. - * @param mode The permissions with which to create the directory - * @return 0 on success, negative error code on failure - */ - virtual int mkdir(const char *path, mode_t mode); - - /** Store information about the mounted filesystem in a statvfs structure - * - * @param path The name of the file to find information about - * @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); -}; -/**@}*/ - -} // namespace mbed - -#endif diff --git a/platform/FileSystemLike.h b/platform/FileSystemLike.h deleted file mode 100644 index 176e2c7..0000000 --- a/platform/FileSystemLike.h +++ /dev/null @@ -1,57 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_FILESYSTEMLIKE_H -#define MBED_FILESYSTEMLIKE_H - -#include "platform/platform.h" - -#include "platform/FileBase.h" -#include "platform/FileSystemHandle.h" -#include "platform/FileHandle.h" -#include "platform/DirHandle.h" -#include "platform/NonCopyable.h" - -namespace mbed { -/** - * \defgroup platform_FileSystemLike FileSystemLike functions - * \ingroup platform-public-api-file - * @{ - */ - - -/** A filesystem-like object is one that can be used to open file-like - * objects though it by fopen("/name/filename", mode) - * - * Implementations must define at least open (the default definitions - * of the rest of the functions just return error values). - * - * @note Synchronization level: Set by subclass - */ -class FileSystemLike : public FileSystemHandle, public FileBase, private NonCopyable { -public: - /** FileSystemLike lifetime - */ - FileSystemLike(const char *name = NULL) : FileBase(name, FileSystemPathType) {} - virtual ~FileSystemLike() {} - -}; - -/**@}*/ - -} // namespace mbed - -#endif diff --git a/platform/LocalFileSystem.h b/platform/LocalFileSystem.h deleted file mode 100644 index 4ee6b6a..0000000 --- a/platform/LocalFileSystem.h +++ /dev/null @@ -1,129 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_LOCALFILESYSTEM_H -#define MBED_LOCALFILESYSTEM_H - -#include "platform/platform.h" - -#if DEVICE_LOCALFILESYSTEM - -#include "platform/FileSystemLike.h" -#include "platform/PlatformMutex.h" -#include "platform/NonCopyable.h" - -namespace mbed { -/** \addtogroup platform-public-api */ -/** @{*/ -/** - * \defgroup platform_LocalFileSystem LocalFileSystem functions - * @{ - */ - -FILEHANDLE local_file_open(const char *name, int flags); - -/** - * @class LocalFileHandle - * @ingroup platform - */ -class LocalFileHandle : public FileHandle, private NonCopyable { - -public: - LocalFileHandle(FILEHANDLE fh); - - virtual int close(); - - virtual ssize_t write(const void *buffer, size_t length); - - virtual ssize_t read(void *buffer, size_t length); - - virtual int isatty(); - - virtual off_t seek(off_t position, int whence); - - virtual int sync(); - - virtual off_t size(); - -protected: - virtual void lock(); - virtual void unlock(); - FILEHANDLE _fh; - int pos; - PlatformMutex _mutex; -}; - -/** A filesystem for accessing the local mbed Microcontroller USB disk drive - * - * This allows programs to read and write files on the same disk drive that is used to program the - * mbed Microcontroller. Once created, the standard C file access functions are used to open, - * read and write files. - * - * @note Synchronization level: Thread safe - * - * Example: - * @code - * #include "mbed.h" - * - * LocalFileSystem local("local"); // Create the local filesystem under the name "local" - * - * int main() { - * FILE *fp = fopen("/local/out.txt", "w"); // Open "out.txt" on the local file system for writing - * fprintf(fp, "Hello World!"); - * fclose(fp); - * remove("/local/out.txt"); // Removes the file "out.txt" from the local file system - * - * DIR *d = opendir("/local"); // Opens the root directory of the local file system - * struct dirent *p; - * while((p = readdir(d)) != NULL) { // Print the names of the files in the local file system - * printf("%s\n", p->d_name); // to stdout. - * } - * closedir(d); - * } - * @endcode - * - * @note - * If the microcontroller program makes an access to the local drive, it will be marked as "removed" - * on the Host computer. This means it is no longer accessible from the Host Computer. - * - * The drive will only re-appear when the microcontroller program exists. Note that if the program does - * not exit, you will need to hold down reset on the mbed Microcontroller to be able to see the drive again! - * @ingroup platform - */ -class LocalFileSystem : public FileSystemLike, private NonCopyable { - // No modifiable state - -public: - LocalFileSystem(const char *n) : FileSystemLike(n) - { - - } - - virtual int open(FileHandle **file, const char *path, int flags); - virtual int open(DirHandle **dir, const char *name); - virtual int remove(const char *filename); -}; - -/**@}*/ - -/**@}*/ - -} // namespace mbed - -#endif - -#endif - diff --git a/platform/NonCopyable.h b/platform/NonCopyable.h deleted file mode 100644 index e29b8fb..0000000 --- a/platform/NonCopyable.h +++ /dev/null @@ -1,195 +0,0 @@ -/* Copyright (c) 2017-2019 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_NONCOPYABLE_H_ -#define MBED_NONCOPYABLE_H_ - -namespace mbed { - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \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 - * // base class representing a connection - * struct Connection { - * Connection(); - * virtual ~Connection(); - * virtual void open() = 0; - * } - * - * class SerialConnection : public Connection { - * public: - * SerialConnection(Serial*); - * - * private: - * Serial* _serial; - * }; - * - * Connection& get_connection() { - * static SerialConnection serial_connection; - * return serial_connection; - * } - * - * Connection connection = get_connection(); - * @endcode - * - * 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 defined as deleted: - * - * @code - * struct Connection { - * Connection(const Connection &) = delete; - * Connection &operator=(const Connection &) = delete; - * } - * @endcode - * - * Although manually defining deleted 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 - * } - * @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 classes is also a base type of the first nonstatic data member: - * - * @code - * struct A { }; - * struct B : A { - * int foo; - * }; - * // thanks to empty base optimization, sizeof(B) == sizeof(int) - * - * struct C : A { - * B b; - * }; - * - * // empty base optimization cannot be applied here because A from C and A from - * // 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 make it - * unique to the type it is applied to: - * - * @code - * template - * struct A { }; - * struct B : A { - * int foo; - * }; - * struct C : A { - * B b; - * }; - * - * // empty base optimization can be applied B and C does not refer to the same - * // kind of A. sizeof(C) == sizeof(B) == sizeof(int). - * @endcode - * - * @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. - */ - NonCopyable() = default; - /** - * Disallow destruction of NonCopyable objects from outside of its hierarchy. - */ - ~NonCopyable() = default; - -public: - /** - * Define copy constructor as deleted. Any attempt to copy construct - * a NonCopyable will fail at compile time. - */ - NonCopyable(const NonCopyable &) = delete; - - /** - * Define copy assignment operator as deleted. Any attempt to copy assign - * a NonCopyable will fail at compile time. - */ - NonCopyable &operator=(const NonCopyable &) = delete; -#endif -}; - -/**@}*/ - -/**@}*/ - -} // namespace mbed - -#endif /* MBED_NONCOPYABLE_H_ */ diff --git a/platform/PlatformMutex.h b/platform/PlatformMutex.h deleted file mode 100644 index d2e94e5..0000000 --- a/platform/PlatformMutex.h +++ /dev/null @@ -1,92 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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 PLATFORM_MUTEX_H -#define PLATFORM_MUTEX_H - -#include "platform/NonCopyable.h" - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** \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_API_PRESENT - -// rtos::Mutex is itself a dummy class if the RTOS API is present, but not the RTOS -#include "rtos/Mutex.h" -typedef rtos::Mutex PlatformMutex; - -#else - -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() - { - } - - /** PlatformMutex destructor. - * - * @note When the RTOS is present, this is an alias for rtos::Mutex::~Mutex(). - */ - ~PlatformMutex() - { - } - - /** 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() - { - } - - /** 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() - { - } -}; - -#endif - -#endif - -/**@}*/ - -/**@}*/ diff --git a/platform/ScopedLock.h b/platform/ScopedLock.h deleted file mode 100644 index b2e664d..0000000 --- a/platform/ScopedLock.h +++ /dev/null @@ -1,89 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018-2019 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_SCOPEDLOCK_H -#define MBED_SCOPEDLOCK_H - -#include "platform/NonCopyable.h" - -namespace mbed { - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_ScopedLock ScopedLock functions - * @{ - */ - -/** RAII-style mechanism for owning a lock of Lockable object for the duration of a scoped block - * - * @tparam Lockable The type implementing BasicLockable concept - * - * @note For type Lockable to be BasicLockable, the following conditions have to be satisfied: - * - has public member function @a lock which blocks until a lock can be obtained for the current execution context - * - has public member function @a unlock which releases the lock - * - * Usage: - * - * Example with rtos::Mutex - * - * @code - * void foo(Mutex &m) { - * ScopedLock lock(m); - * // Mutex lock protects code in this block - * } - * @endcode - * - * - * More generic example - * - * @code - * template - * void foo(Lockable& lockable) { - * ScopedLock lock(lockable); - * // Code in this block runs under lock - * } - * @endcode - */ -template -class ScopedLock : private NonCopyable > { -public: - /** Locks given lockable object - * - * @param lockable reference to the instance of Lockable object - * @note lockable object should outlive the ScopedLock object - */ - ScopedLock(Lockable &lockable): _lockable(lockable) - { - _lockable.lock(); - } - - ~ScopedLock() - { - _lockable.unlock(); - } -private: - Lockable &_lockable; -}; - -/**@}*/ - -/**@}*/ - -} // embed - -#endif // MBED_SCOPEDLOCK_H diff --git a/platform/ScopedRamExecutionLock.h b/platform/ScopedRamExecutionLock.h deleted file mode 100644 index 0f7cadd..0000000 --- a/platform/ScopedRamExecutionLock.h +++ /dev/null @@ -1,73 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018-2019 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_SCOPEDRAMEXECUTIONLOCK_H -#define MBED_SCOPEDRAMEXECUTIONLOCK_H - -#include "platform/mbed_mpu_mgmt.h" -#include "platform/NonCopyable.h" - -namespace mbed { - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** RAII object for disabling, then restoring RAM execute never mode - * Usage: - * @code - * - * void f() { - * // some code here - * { - * ScopedRamExecutionLock make_ram_executable; - * // Code in this block is allowed to call functions in RAM - * } - * // Execution from RAM is no longer allowed - * } - * @endcode - */ -class ScopedRamExecutionLock : private mbed::NonCopyable { -public: - - /** - * Allow execution from RAM - * - * Increment the execute never lock to ensure code can - * be executed from RAM. This class uses RAII to allow - * execution from ram while it is in scope. - */ - ScopedRamExecutionLock() - { - mbed_mpu_manager_lock_ram_execution(); - } - - /** - * Restore previous execution from RAM settings - * - * Decrement the execute never lock to return execute from RAM - * to its prior state. - */ - ~ScopedRamExecutionLock() - { - mbed_mpu_manager_unlock_ram_execution(); - } -}; - -/**@}*/ - -} - -#endif diff --git a/platform/ScopedRomWriteLock.h b/platform/ScopedRomWriteLock.h deleted file mode 100644 index 5ebdd12..0000000 --- a/platform/ScopedRomWriteLock.h +++ /dev/null @@ -1,73 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018-2019 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_SCOPEDROMWRITELOCK_H -#define MBED_SCOPEDROMWRITELOCK_H - -#include "platform/mbed_mpu_mgmt.h" -#include "platform/NonCopyable.h" - -namespace mbed { - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** RAII object for disabling, then restoring ROM write never mode - * Usage: - * @code - * - * void f() { - * // some code here - * { - * ScopedRomWriteLock make_ram_executable; - * // Code in this block is allowed to write to ROM - * } - * // Writing to ROM is no longer allowed - * } - * @endcode - */ -class ScopedRomWriteLock : private mbed::NonCopyable { -public: - - /** - * Allow writing to ROM - * - * Increment the ROM write lock to ensure code can - * write to ROM. This class uses RAII to allow - * writing to ROM while it is in scope. - */ - ScopedRomWriteLock() - { - mbed_mpu_manager_lock_rom_write(); - } - - /** - * Restore previous write to ROM settings - * - * Decrement the ROM write lock to return ROM write - * to its prior state. - */ - ~ScopedRomWriteLock() - { - mbed_mpu_manager_unlock_rom_write(); - } -}; - -/**@}*/ - -} - -#endif diff --git a/platform/SharedPtr.h b/platform/SharedPtr.h deleted file mode 100644 index 73a3b3c..0000000 --- a/platform/SharedPtr.h +++ /dev/null @@ -1,340 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-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 __SHAREDPTR_H__ -#define __SHAREDPTR_H__ - -#include - -#include -#include - -#include "platform/mbed_atomic.h" - -namespace mbed { - -/** Shared pointer class. - * - * A shared pointer is a "smart" pointer that retains ownership of an object using - * reference counting across all smart pointers referencing that object. - * - * @code - * #include "platform/SharedPtr.h" - * - * void test() { - * struct MyStruct { int a; }; - * - * // Create shared pointer - * SharedPtr ptr( new MyStruct ); - * - * // Increase reference count - * SharedPtr ptr2( ptr ); - * - * ptr = nullptr; // Reference to the struct instance is still held by ptr2 - * - * ptr2 = nullptr; // The raw pointer is freed - * } - * @endcode - * - * - * It is similar to the std::shared_ptr class introduced in C++11; - * however, this is not a compatible implementation (no weak pointer, no make_shared, no custom deleters and so on.) - * - * Usage: SharedPtr ptr(new Class()) - * - * When ptr is passed around by value, the copy constructor and - * destructor manages the reference count of the raw pointer. - * If the counter reaches zero, delete is called on the raw pointer. - * - * To avoid loops, use "weak" references by calling the original - * pointer directly through ptr.get(). - */ - -template -class SharedPtr { -public: - /** - * @brief Create empty SharedPtr not pointing to anything. - * @details Used for variable declaration. - */ - constexpr SharedPtr(): _ptr(), _counter() - { - } - - /** - * @brief Create empty SharedPtr not pointing to anything. - */ - constexpr SharedPtr(std::nullptr_t) : SharedPtr() - { - } - - /** - * @brief Create new SharedPtr - * @param ptr Pointer to take control over - */ - SharedPtr(T *ptr): _ptr(ptr), _counter() - { - // Allocate counter on the heap, so it can be shared - if (_ptr != nullptr) { - _counter = new uint32_t(1); - } - } - - /** - * @brief Destructor. - * @details Decrement reference counter, and delete object if no longer pointed to. - */ - ~SharedPtr() - { - decrement_counter(); - } - - /** - * @brief Copy constructor. - * @details Create new SharedPtr from other SharedPtr by - * copying pointer to original object and pointer to counter. - * @param source Object being copied from. - */ - SharedPtr(const SharedPtr &source): _ptr(source._ptr), _counter(source._counter) - { - // Increment reference counter - if (_ptr != nullptr) { - core_util_atomic_incr_u32(_counter, 1); - } - } - - /** - * @brief Move constructor. - * @details Create new SharedPtr from other SharedPtr by - * moving pointer to original object and pointer to counter. - * @param source Object being copied from. - */ - SharedPtr(SharedPtr &&source): _ptr(source._ptr), _counter(source._counter) - { - source._ptr = nullptr; - source._counter = nullptr; - } - - /** - * @brief Copy assignment operator. - * @details Cleanup previous reference and assign new pointer and counter. - * @param source Object being assigned from. - * @return Object being assigned. - */ - SharedPtr operator=(const SharedPtr &source) - { - if (this != &source) { - // Clean up by decrementing counter - decrement_counter(); - - // Assign new values - _ptr = source.get(); - _counter = source.get_counter(); - - // Increment new counter - if (_ptr != nullptr) { - core_util_atomic_incr_u32(_counter, 1); - } - } - - return *this; - } - - /** - * @brief Move assignment operator. - * @details Cleanup previous reference and assign new pointer and counter. - * @param source Object being assigned from. - * @return Object being assigned. - */ - SharedPtr operator=(SharedPtr &&source) - { - if (this != &source) { - // Clean up by decrementing counter - decrement_counter(); - - // Assign new values - _ptr = source._ptr; - _counter = source._counter; - - source._ptr = nullptr; - source._counter = nullptr; - } - - return *this; - } - - /** - * @brief Replaces the managed pointer with a new unmanaged pointer. - * @param[in] ptr the new raw pointer to manage. - */ - void reset(T *ptr) - { - // Clean up by decrementing counter - decrement_counter(); - - _ptr = ptr; - if (ptr != nullptr) { - // Allocate counter on the heap, so it can be shared - _counter = new uint32_t(1); - } else { - _counter = nullptr; - } - } - - /** - * @brief Replace the managed pointer with a null pointer. - */ - void reset() - { - // Clean up by decrementing counter - decrement_counter(); - - _ptr = nullptr; - _counter = nullptr; - } - - /** - * @brief Raw pointer accessor. - * @details Get raw pointer to object pointed to. - * @return Pointer. - */ - T *get() const - { - return _ptr; - } - - /** - * @brief Reference count accessor. - * @return Reference count. - */ - uint32_t use_count() const - { - if (_ptr != nullptr) { - return core_util_atomic_load_u32(_counter); - } else { - return 0; - } - } - - /** - * @brief Dereference object operator. - * @details Override to return the object pointed to. - */ - T &operator*() const - { - return *_ptr; - } - - /** - * @brief Dereference object member operator. - * @details Override to return return member in object pointed to. - */ - T *operator->() const - { - return _ptr; - } - - /** - * @brief Boolean conversion operator. - * @return Whether or not the pointer is null. - */ - operator bool() const - { - return _ptr != nullptr; - } - -private: - /** - * @brief Get pointer to reference counter. - * @return Pointer to reference counter. - */ - uint32_t *get_counter() const - { - return _counter; - } - - /** - * @brief Decrement reference counter. - * @details If count reaches zero, free counter and delete object pointed to. - * Does not modify our own pointers - assumption is they will be overwritten - * or destroyed immediately afterwards. - */ - void decrement_counter() - { - if (_ptr != nullptr) { - if (core_util_atomic_decr_u32(_counter, 1) == 0) { - delete _counter; - delete _ptr; - } - } - } - -private: - // Pointer to shared object - T *_ptr; - - // Pointer to shared reference counter - uint32_t *_counter; -}; - -/** Non-member relational operators. - */ -template -bool operator== (const SharedPtr &lhs, const SharedPtr &rhs) -{ - return (lhs.get() == rhs.get()); -} - -template -bool operator== (const SharedPtr &lhs, U rhs) -{ - return (lhs.get() == (T *) rhs); -} - -template -bool operator== (U lhs, const SharedPtr &rhs) -{ - return ((T *) lhs == rhs.get()); -} - -/** Non-member relational operators. - */ -template -bool operator!= (const SharedPtr &lhs, const SharedPtr &rhs) -{ - return (lhs.get() != rhs.get()); -} - -template -bool operator!= (const SharedPtr &lhs, U rhs) -{ - return (lhs.get() != (T *) rhs); -} - -template -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 deleted file mode 100644 index 2b873a2..0000000 --- a/platform/SingletonPtr.h +++ /dev/null @@ -1,211 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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 SINGLETONPTR_H -#define SINGLETONPTR_H - -#include -#include -#include -#include "platform/mbed_assert.h" -#include "platform/mbed_atomic.h" -#ifdef MBED_CONF_RTOS_PRESENT -#include "cmsis_os2.h" -#endif - -#ifdef MBED_CONF_RTOS_PRESENT -extern osMutexId_t singleton_mutex_id; -#endif - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_SingletonPtr SingletonPtr class - * @{ - */ - -/** Lock the singleton mutex - * - * This function is typically used to provide - * exclusive access when initializing a - * global object. - */ -inline static void singleton_lock(void) -{ -#ifdef MBED_CONF_RTOS_PRESENT - if (!singleton_mutex_id) { - // RTOS has not booted yet so no mutex is needed - return; - } - osMutexAcquire(singleton_mutex_id, osWaitForever); -#endif -} - -/** Unlock the singleton mutex - * - * This function is typically used to provide - * exclusive access when initializing a - * global object. - */ -inline static void singleton_unlock(void) -{ -#ifdef MBED_CONF_RTOS_PRESENT - if (!singleton_mutex_id) { - // RTOS has not booted yet so no mutex is needed - return; - } - osMutexRelease(singleton_mutex_id); -#endif -} - -/** Utility class for creating and using a singleton - * - * @note Synchronization level: Thread safe - * - * @note: This class is lazily initialized on first use. - * This class has a constexpr default constructor so if it is - * not used as a non-local variable it will be garbage collected. - * - * @note: This class would normally be used in a static standalone - * context. It does not call the destructor of the wrapped object - * when it is destroyed, effectively ensuring linker exclusion of the - * destructor for static objects. If used in another context, such as - * a member of a normal class wanting "initialize on first-use" - * semantics on a member, care should be taken to call the destroy - * method manually if necessary. - * - * @note: If used as a sub-object of a class, that class's own - * constructor must be constexpr to achieve its exclusion by - * the linker when unused. That will require explicit - * initialization of its other members. - * - * @note: More detail on initialization: Formerly, SingletonPtr - * had no constructor, so was "zero-initialized" when non-local. - * So if enclosed in another class with no constructor, the whole - * thing would be zero-initialized, and linker-excludable. - * Having no constructor meant SingletonPtr was not constexpr, - * which limited applicability in other contexts. With its new - * constexpr constructor, it is now "constant-initialized" when - * non-local. This achieves the same effect as a standalone - * non-local object, but as a sub-object linker exclusion is - * now only achieved if the outer object is itself using a - * constexpr constructor to get constant-initialization. - * Otherwise, the outer object will be neither zero-initialized - * nor constant-initialized, so will be "dynamic-initialized", - * and likely to be left in by the linker. - */ -template -struct SingletonPtr { - - // Initializers are required to make default constructor constexpr - // This adds no overhead as a static object - the compiler and linker can - // figure out that we are effectively zero-init, and either place us in - // ".bss", or exclude us if unused. - constexpr SingletonPtr() noexcept : _ptr(), _data() { } - - /** Get a pointer to the underlying singleton - * - * @returns - * A pointer to the singleton - */ - T *get() const - { - T *p = core_util_atomic_load(&_ptr); - if (p == NULL) { - singleton_lock(); - p = _ptr; - if (p == NULL) { - p = new (_data) T(); - core_util_atomic_store(&_ptr, p); - } - singleton_unlock(); - } - // _ptr was not zero initialized or was - // corrupted if this assert is hit - MBED_ASSERT(p == reinterpret_cast(&_data)); - return p; - } - - /** Get a pointer to the underlying singleton - * - * @returns - * A pointer to the singleton - */ - T *operator->() const - { - return get(); - } - - /** Get a reference to the underlying singleton - * - * @returns - * A reference to the singleton - */ - T &operator*() const - { - return *get(); - } - - /** Get a pointer to the underlying singleton - * - * Gets a pointer without initialization - can be - * used as an optimization when it is known that - * initialization must have already occurred. - * - * @returns - * A pointer to the singleton, or NULL if not - * initialized. - */ - T *get_no_init() const - { - return _ptr; - } - - /** Destroy the underlying singleton - * - * The underlying singleton is never automatically destroyed; - * this is a potential optimization to avoid destructors - * being pulled into an embedded image on the exit path, - * which should never occur. The destructor can be - * manually invoked via this call. - * - * Unlike construction, this is not thread-safe. After this call, - * no further operations on the object are permitted. - * - * Is a no-op if the object has not been constructed. - */ - void destroy() - { - if (_ptr) { - _ptr->~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 deleted file mode 100644 index 450b7f5..0000000 --- a/platform/Span.h +++ /dev/null @@ -1,1127 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018-2019 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_PLATFORM_SPAN_H_ -#define MBED_PLATFORM_SPAN_H_ - -#include -#include -#include -#include - -#include "platform/mbed_assert.h" - -namespace mbed { - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \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 { - -// If From type is convertible to To type, then the compilation constant value is -// true; otherwise, it is false. -template -class is_convertible { - struct true_type { - char x[512]; - }; - struct false_type { }; - - static const From &generator(); - static true_type sink(const To &); - static false_type sink(...); - -public: - static const bool value = sizeof(true_type) == sizeof(sink(generator())); -}; - -} - -#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. - * - * Spans encapsulate a pointer to a sequence of contiguous elements and its size - * into a single object. Span can replace the traditional pair of pointer and - * size arguments passed as array definitions in function calls. - * - * @par Operations - * - * Span objects can be copied and assigned like regular value types with the help - * of the copy constructor or the copy assignment (=) operator. - * - * You can retrieve elements of the object with the subscript ([]) operator. You can access the - * pointer to the first element of the sequence viewed with data(). - * The function size() returns the number of elements in the sequence, and - * empty() informs whether there is any element in the sequence. - * - * You can slice Span from the beginning of the sequence (first()), from the end - * of the sequence (last()) or from an arbitrary point of the sequence (subspan()). - * - * @par Size encoding - * - * The size of the sequence can be encoded in the type itself or in the value of - * the instance with the help of the template parameter Extent: - * - * - Span: Span over a sequence of 6 elements. - * - Span: Span over an arbitrary long sequence. - * - * When the size is encoded in the type itself, it is guaranteed that the Span - * view is a valid sequence (not empty() and not NULL) - unless Extent equals 0. - * The type system also prevents automatic conversion from Span of different - * sizes. Finally, the Span object is internally represented as a single pointer. - * - * When the size of the sequence viewed is encoded in the Span value, Span - * instances can view an empty sequence. The function empty() helps client code - * decide whether Span is viewing valid content or not. - * - * @par Example - * - * - Encoding fixed size array: Array values in parameter decays automatically - * to pointer, which leaves room for subtitle bugs: - * - * @code - typedef uint8_t mac_address_t[6]; - void process_mac(mac_address_t); - - // compile just fine - uint8_t *invalid_value = NULL; - process_mac(invalid_value); - - - // correct way - typedef Span mac_address_t; - void process_mac(mac_address_t); - - // compilation error - uint8_t *invalid_value = NULL; - process_mac(invalid_value); - - // compilation ok - uint8_t valid_value[6]; - process_mac(valid_value); - * @endcode - * - * - Arbitrary buffer: When dealing with multiple buffers, it becomes painful to - * keep track of every buffer size and pointer. - * - * @code - const uint8_t options_tag[OPTIONS_TAG_SIZE]; - - struct parsed_value_t { - uint8_t *header; - uint8_t *options; - uint8_t *payload; - size_t payload_size; - } - - parsed_value_t parse(uint8_t *buffer, size_t buffer_size) - { - parsed_value_t parsed_value { 0 }; - - if (buffer != NULL && buffer_size <= MINIMAL_BUFFER_SIZE) { - return parsed_value; - } - - parsed_value.header = buffer; - parsed_value.header_size = BUFFER_HEADER_SIZE; - - if (memcmp(buffer + HEADER_OPTIONS_INDEX, options_tag, sizeof(options_tag)) == 0) { - options = buffer + BUFFER_HEADER_SIZE; - payload = buffer + BUFFER_HEADER_SIZE + OPTIONS_SIZE; - payload_size = buffer_size - BUFFER_HEADER_SIZE + OPTIONS_SIZE; - } else { - payload = buffer + BUFFER_HEADER_SIZE; - payload_size = buffer_size - BUFFER_HEADER_SIZE; - } - - return parsed_value; - } - - - //with Span - struct parsed_value_t { - Span header; - Span options; - Span payload; - } - - parsed_value_t parse(const Span &buffer) - { - parsed_value_t parsed_value; - - if (buffer.size() <= MINIMAL_BUFFER_SIZE) { - return parsed_value; - } - - parsed_value.header = buffer.first(BUFFER_HEADER_SIZE); - - if (buffer.subspan() == option_tag) { - options = buffer.supspan(parsed_value.header.size(), OPTIONS_SIZE); - } - - payload = buffer.subspan(parsed_value.header.size() + parsed_value.options.size()); - - return parsed_value; - } - * @endcode - * - * @note You can create Span instances with the help of the function template - * make_Span() and make_const_Span(). - * - * @note Span objects can be implicitly converted to Span objects - * where required. - * - * @tparam ElementType type of objects the Span views. - * - * @tparam Extent The size of the contiguous sequence viewed. The default value - * SPAN_DYNAMIC_SIZE is special because it allows construction of Span objects of - * any size (set at runtime). - */ -template -struct Span { - - /** - * Type of the element contained - */ - typedef ElementType element_type; - - /** - * Type of the index. - */ - typedef ptrdiff_t index_type; - - /** - * Pointer to an ElementType - */ - typedef element_type *pointer; - - /** - * Reference to an ElementType - */ - typedef element_type &reference; - - /** - * Iterator to an ElementType - */ - typedef pointer iterator; - - /** - * Reverse iterator to an ElementType - */ - typedef std::reverse_iterator reverse_iterator; - - /** - * Size of the Extent; -1 if dynamic. - */ - static const index_type extent = Extent; - - MBED_STATIC_ASSERT(Extent >= 0, "Invalid extent for a Span"); - - /** - * Construct an empty Span. - * - * @post a call to size() returns 0, and data() returns NULL. - * - * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or - * Extent != 0 . - */ - Span() : - _data(NULL) - { - MBED_STATIC_ASSERT( - Extent == 0, - "Cannot default construct a static-extent Span (unless Extent is 0)" - ); - } - - /** - * Construct a Span from a pointer to a buffer and its size. - * - * @param ptr Pointer to the beginning of the data viewed. - * - * @param count Number of elements viewed. - * - * @pre [ptr, ptr + count) must be be a valid range. - * @pre count must be equal to Extent. - * - * @post a call to size() returns Extent, and data() returns @p ptr. - */ - Span(pointer ptr, index_type count) : - _data(ptr) - { - MBED_ASSERT(count == Extent); - MBED_ASSERT(Extent == 0 || ptr != NULL); - } - - /** - * Construct a Span from the range [first, last). - * - * @param first Pointer to the beginning of the data viewed. - * @param last End of the range (element after the last element). - * - * @pre [first, last) must be be a valid range. - * @pre first <= last. - * @pre last - first must be equal to Extent. - * - * @post a call to size() returns Extent, and data() returns @p first. - */ - Span(pointer first, pointer last) : - _data(first) - { - MBED_ASSERT(first <= last); - MBED_ASSERT((last - first) == Extent); - MBED_ASSERT(Extent == 0 || first != NULL); - } - - // AStyle ignore, not handling correctly below - // *INDENT-OFF* - /** - * Construct a Span from the reference to an array. - * - * @param elements Reference to the array viewed. - * - * @post a call to size() returns Extent, and data() returns a - * pointer to elements. - */ - Span(element_type (&elements)[Extent]): - _data(elements) { } - - /** - * Construct a Span object from another Span of the same size. - * - * @param other The Span object used to construct this. - * - * @note For Span with a positive extent, this function is not accessible. - * - * @note OtherElementType(*)[] must be convertible to ElementType(*)[]. - */ - template - Span(const Span &other): - _data(other.data()) - { - MBED_STATIC_ASSERT( - (span_detail::is_convertible::value), - "OtherElementType(*)[] should be convertible to ElementType (*)[]" - ); - } - // *INDENT-ON* - - /** - * Return the size of the sequence viewed. - * - * @return The size of the sequence viewed. - */ - index_type size() const - { - return Extent; - } - - /** - * Return if the sequence is empty or not. - * - * @return true if the sequence is empty and false otherwise. - */ - bool empty() const - { - return size() == 0; - } - - /** - * Return an iterator to the first element of the sequence. - * - * @return An iterator to the first element of the sequence. - */ - iterator begin() const - { - return _data; - } - - /** - * Return an iterator to the element following the last element of the sequence. - * - * @return An iterator to the element following the last element of the sequence. - */ - iterator end() const - { - return _data + Extent; - } - - /** - * Return a reverse_iterator to the first element of the reversed sequence. - * - * @return A reverse_iterator to the first element of the reversed sequence. - */ - reverse_iterator rbegin() const - { - return reverse_iterator(end()); - } - - /** - * Return a reverse_iterator to the element following the last element of the reversed sequence. - * - * @return A reverse_iterator to the element following the last element of the reversed sequence. - */ - reverse_iterator rend() const - { - return reverse_iterator(begin()); - } - - /** - * Returns a reference to the element at position @p index. - * - * @param index Index of the element to access. - * - * @return A reference to the element at the index specified in input. - * - * @pre 0 <= index < Extent. - */ - reference operator[](index_type index) const - { -#ifdef MBED_DEBUG - MBED_ASSERT(0 <= index && index < Extent); -#endif - return _data[index]; - } - - /** - * Return a pointer to the first element of the sequence or NULL if the Span - * is empty(). - * - * @return The pointer to the first element of the Span. - */ - pointer data() const - { - return _data; - } - - /** - * Create a new Span over the first @p Count elements of the existing view. - * - * @tparam Count The number of element viewed by the new Span - * - * @return A new Span over the first @p Count elements. - * - * @pre Count >= 0 && Count <= size(). - */ - template - Span first() const - { - MBED_STATIC_ASSERT( - (0 <= Count) && (Count <= Extent), - "Invalid subspan extent" - ); - return Span(_data, Count); - } - - /** - * Create a new Span over the last @p Count elements of the existing view. - * - * @tparam Count The number of element viewed by the new Span. - * - * @return A new Span over the last @p Count elements. - * - * @pre Count >= 0 && Count <= size(). - */ - template - Span last() const - { - MBED_STATIC_ASSERT( - (0 <= Count) && (Count <= Extent), - "Invalid subspan extent" - ); - return Span(_data + (Extent - Count), Count); - } - - // AStyle ignore, not handling correctly below - // *INDENT-OFF* - /** - * Create a subspan that is a view of other Count elements; the view starts at - * element Offset. - * - * @tparam Offset The offset of the first element viewed by the subspan. - * - * @tparam Count The number of elements present in the subspan. If Count - * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and - * containing the rest of the elements is returned. - * - * @return A subspan of this starting at Offset and Count long. - */ - template - Span - subspan() const - { - MBED_STATIC_ASSERT( - 0 <= Offset && Offset <= Extent, - "Invalid subspan offset" - ); - MBED_STATIC_ASSERT( - (Count == SPAN_DYNAMIC_EXTENT) || - (0 <= Count && (Count + Offset) <= Extent), - "Invalid subspan count" - ); - return Span( - _data + Offset, - Count == SPAN_DYNAMIC_EXTENT ? Extent - Offset : Count - ); - } - // *INDENT-ON* - - /** - * Create a new Span over the first @p count elements of the existing view. - * - * @param count The number of element viewed by the new Span. - * - * @return A new Span over the first @p count elements. - */ - Span first(index_type count) const - { - MBED_ASSERT(0 <= count && count <= Extent); - return Span(_data, count); - } - - /** - * Create a new Span over the last @p count elements of the existing view. - * - * @param count The number of elements viewed by the new Span. - * - * @return A new Span over the last @p count elements. - */ - Span last(index_type count) const - { - MBED_ASSERT(0 <= count && count <= Extent); - return Span( - _data + (Extent - count), - count - ); - } - - /** - * Create a subspan that is a view of other count elements; the view starts at - * element offset. - * - * @param offset The offset of the first element viewed by the subspan. - * - * @param count The number of elements present in the subspan. If Count - * is equal to SPAN_DYNAMIC_EXTENT, then a span starting at offset and - * containing the rest of the elements is returned. - * - * @return - */ - Span subspan( - index_type offset, index_type count = SPAN_DYNAMIC_EXTENT - ) const - { - MBED_ASSERT(0 <= offset && offset <= Extent); - MBED_ASSERT( - (count == SPAN_DYNAMIC_EXTENT) || - (0 <= count && (count + offset) <= Extent) - ); - return Span( - _data + offset, - count == SPAN_DYNAMIC_EXTENT ? Extent - offset : count - ); - } - -private: - pointer _data; -}; - -/** - * Span specialization that handle dynamic size. - */ -template -struct Span { - /** - * Type of the element contained. - */ - typedef ElementType element_type; - - /** - * Type of the index. - */ - typedef ptrdiff_t index_type; - - /** - * Pointer to an ElementType. - */ - typedef element_type *pointer; - - /** - * Reference to an ElementType. - */ - typedef element_type &reference; - - /** - * Iterator to an ElementType - */ - typedef pointer iterator; - - /** - * Reverse iterator to an ElementType - */ - typedef std::reverse_iterator reverse_iterator; - - /** - * Size of the Extent; -1 if dynamic. - */ - static const index_type extent = SPAN_DYNAMIC_EXTENT; - - /** - * Construct an empty Span. - * - * @post a call to size() returns 0, and data() returns NULL. - * - * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or - * Extent != 0 . - */ - Span() : - _data(NULL), _size(0) { } - - /** - * Construct a Span from a pointer to a buffer and its size. - * - * @param ptr Pointer to the beginning of the data viewed. - * - * @param count Number of elements viewed. - * - * @pre [ptr, ptr + count) must be be a valid range. - * @pre count must be equal to extent. - * - * @post a call to size() returns count, and data() returns @p ptr. - */ - Span(pointer ptr, index_type count) : - _data(ptr), _size(count) - { - MBED_ASSERT(count >= 0); - MBED_ASSERT(ptr != NULL || count == 0); - } - - /** - * Construct a Span from the range [first, last). - * - * @param first Pointer to the beginning of the data viewed. - * @param last End of the range (element after the last element). - * - * @pre [first, last) must be be a valid range. - * @pre first <= last. - * - * @post a call to size() returns the result of (last - first), and - * data() returns @p first. - */ - Span(pointer first, pointer last) : - _data(first), _size(last - first) - { - MBED_ASSERT(first <= last); - MBED_ASSERT(first != NULL || (last - first) == 0); - } - - // AStyle ignore, not handling correctly below - // *INDENT-OFF* - /** - * Construct a Span from the reference to an array. - * - * @param elements Reference to the array viewed. - * - * @tparam Count Number of elements of T presents in the array. - * - * @post a call to size() returns Count, and data() returns a - * pointer to elements. - */ - template - Span(element_type (&elements)[Count]): - _data(elements), _size(Count) { } - - /** - * Construct a Span object from another Span. - * - * @param other The Span object used to construct this. - * - * @note For Span with a positive extent, this function is not accessible. - * - * @note OtherElementType(*)[] must be convertible to ElementType(*)[]. - */ - template - Span(const Span &other): - _data(other.data()), _size(other.size()) - { - MBED_STATIC_ASSERT( - (span_detail::is_convertible::value), - "OtherElementType(*)[] should be convertible to ElementType (*)[]" - ); - } - // *INDENT-ON* - - /** - * Return the size of the array viewed. - * - * @return The number of elements present in the array viewed. - */ - index_type size() const - { - return _size; - } - - /** - * Return if the sequence viewed is empty or not. - * - * @return true if the sequence is empty and false otherwise. - */ - bool empty() const - { - return size() == 0; - } - - /** - * Return an iterator to the first element of the sequence. - * - * @return An iterator to the first element of the sequence. - */ - iterator begin() const - { - return _data; - } - - /** - * Return an iterator to the element following the last element of the sequence. - * - * @return An iterator to the element following the last element of the sequence. - */ - iterator end() const - { - return _data + _size; - } - - /** - * Return a reverse_iterator to the first element of the reversed sequence. - * - * @return A reverse_iterator to the first element of the reversed sequence. - */ - reverse_iterator rbegin() const - { - return reverse_iterator(end()); - } - - /** - * Return a reverse_iterator to the element following the last element of the reversed sequence. - * - * @return A reverse_iterator to the element following the last element of the reversed sequence. - */ - reverse_iterator rend() const - { - return reverse_iterator(begin()); - } - - /** - * Access to an element of the sequence. - * - * @param index Element index to access. - * - * @return A reference to the element at the index specified in input. - * - * @pre index is less than size(). - */ - reference operator[](index_type index) const - { -#ifdef MBED_DEBUG - MBED_ASSERT(0 <= index && index < _size); -#endif - return _data[index]; - } - - /** - * Get the raw pointer to the sequence viewed. - * - * @return The raw pointer to the first element viewed. - */ - pointer data() const - { - return _data; - } - - /** - * Create a new Span over the first @p Count elements of the existing view. - * - * @tparam Count The number of elements viewed by the new Span. - * - * @return A new Span over the first @p Count elements. - * - * @pre Count >= 0 && Count <= size(). - */ - template - Span first() const - { - MBED_ASSERT((Count >= 0) && (Count <= _size)); - return Span(_data, Count); - } - - /** - * Create a new Span over the last @p Count elements of the existing view. - * - * @tparam Count The number of elements viewed by the new Span. - * - * @return A new Span over the last @p Count elements. - * - * @pre Count >= 0 && Count <= size(). - */ - template - Span last() const - { - MBED_ASSERT((0 <= Count) && (Count <= _size)); - return Span(_data + (_size - Count), Count); - } - - /** - * Create a subspan that is a view other Count elements; the view starts at - * element Offset. - * - * @tparam Offset The offset of the first element viewed by the subspan. - * - * @tparam Count The number of elements present in the subspan. If Count - * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and - * containing the rest of the elements is returned. - * - * @return A subspan of this starting at Offset and Count long. - */ - template - Span - subspan() const - { - MBED_ASSERT(0 <= Offset && Offset <= _size); - MBED_ASSERT( - (Count == SPAN_DYNAMIC_EXTENT) || - (0 <= Count && (Count + Offset) <= _size) - ); - return Span( - _data + Offset, - Count == SPAN_DYNAMIC_EXTENT ? _size - Offset : Count - ); - } - - /** - * Create a new Span over the first @p count elements of the existing view. - * - * @param count The number of elements viewed by the new Span. - * - * @return A new Span over the first @p count elements. - */ - Span first(index_type count) const - { - MBED_ASSERT(0 <= count && count <= _size); - return Span(_data, count); - } - - /** - * Create a new Span over the last @p count elements of the existing view. - * - * @param count The number of elements viewed by the new Span. - * - * @return A new Span over the last @p count elements. - */ - Span last(index_type count) const - { - MBED_ASSERT(0 <= count && count <= _size); - return Span( - _data + (_size - count), - count - ); - } - - /** - * Create a subspan that is a view of other count elements; the view starts at - * element offset. - * - * @param offset The offset of the first element viewed by the subspan. - * - * @param count The number of elements present in the subspan. If Count - * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and - * containing the rest of the elements is returned. - * - * @return A subspan of this starting at offset and count long. - */ - Span subspan( - index_type offset, index_type count = SPAN_DYNAMIC_EXTENT - ) const - { - MBED_ASSERT(0 <= offset && offset <= _size); - MBED_ASSERT( - (count == SPAN_DYNAMIC_EXTENT) || - (0 <= count && (count + offset) <= _size) - ); - return Span( - _data + offset, - count == SPAN_DYNAMIC_EXTENT ? _size - offset : count - ); - } - -private: - pointer _data; - index_type _size; -}; - -/** - * Equality operator between two Span objects. - * - * @param lhs Left side of the binary operation. - * @param rhs Right side of the binary operation. - * - * @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) -{ - if (lhs.size() != rhs.size()) { - return false; - } - - if (lhs.data() == rhs.data()) { - return true; - } - - return std::equal(lhs.data(), lhs.data() + lhs.size(), rhs.data()); -} - -// AStyle ignore, not handling correctly below -// *INDENT-OFF* -/** - * Equality operation between a Span and a reference to a C++ array. - * - * @param lhs Left side of the binary operation. - * @param rhs Right side of the binary operation. - * - * @return True if elements in input have the same size and the same content and - * false otherwise. - */ -template -bool operator==(const Span &lhs, T (&rhs)[RhsExtent]) -{ - return lhs == Span(rhs); -} - -/** - * Equality operation between a Span and a reference to a C++ array. - * - * @param lhs Left side of the binary operation. - * @param rhs Right side of the binary operation. - * - * @return True if elements in input have the same size and the same content - * and false otherwise. - */ -template -bool operator==(T (&lhs)[LhsExtent], const Span &rhs) -{ - return Span(lhs) == rhs; -} - -/** - * Not equal operator - * - * @param lhs Left side of the binary operation. - * @param rhs Right side of the binary operation. - * - * @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) -{ - return !(lhs == rhs); -} - -/** - * Not Equal operation between a Span and a reference to a C++ array. - * - * @param lhs Left side of the binary operation. - * @param rhs Right side of the binary operation. - * - * @return True if elements in input have the same size and the same content - * and false otherwise. - */ -template -bool operator!=(const Span &lhs, T (&rhs)[RhsExtent]) -{ - return !(lhs == Span(rhs)); -} - -/** - * Not Equal operation between a Span and a reference to a C++ array. - * - * @param lhs Left side of the binary operation. - * @param rhs Right side of the binary operation. - * - * @return True if elements in input have the same size and the same content - * and false otherwise. - */ -template -bool operator!=(T (&lhs)[LhsExtent], const Span &rhs) -{ - return !(Span(lhs) == rhs); -} - -/** - * Generate a Span from a reference to a C/C++ array. - * - * @tparam T Type of elements held in elements. - * @tparam Extent Number of items held in elements. - * - * @param elements The reference to the array viewed. - * - * @return The Span to elements. - * - * @note This helper avoids the typing of template parameter when Span is - * created 'inline'. - * - * @relates Span - */ -template -Span make_Span(T (&elements)[Size]) -{ - return Span(elements); -} - -/** - * Generate a Span from a pointer to a C/C++ array. - * - * @tparam Extent Number of items held in elements. - * @tparam T Type of elements held in elements. - * - * @param elements The reference to the array viewed. - * - * @return The Span to elements. - * - * @note This helper avoids the typing of template parameter when Span is - * created 'inline'. - */ -template -Span make_Span(T *elements) -{ - return Span(elements, Extent); -} - -/** - * Generate a Span from a C/C++ pointer and the size of the array. - * - * @tparam T Type of elements held in array_ptr. - * - * @param array_ptr The pointer to the array viewed. - * @param array_size The number of T elements in the array. - * - * @return The Span to array_ptr with a size of array_size. - * - * @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) -{ - return Span(array_ptr, array_size); -} - -/** - * Generate a Span to a const content from a reference to a C/C++ array. - * - * @tparam T Type of elements held in elements. - * @tparam Extent Number of items held in elements. - * - * @param elements The array viewed. - * @return The Span to elements. - * - * @note This helper avoids the typing of template parameter when Span is - * created 'inline'. - */ -template -Span make_const_Span(const T (&elements)[Extent]) -{ - return Span(elements); -} -// *INDENT-ON* -/** - * Generate a Span to a const content from a pointer to a C/C++ array. - * - * @tparam Extent Number of items held in elements. - * @tparam T Type of elements held in elements. - * - * @param elements The reference to the array viewed. - * - * @return The Span to elements. - * - * @note This helper avoids the typing of template parameter when Span is - * created 'inline'. - * - * @relates Span - */ -template -Span make_const_Span(const T *elements) -{ - return Span(elements, Extent); -} - -/** - * Generate a Span to a const content from a C/C++ pointer and the size of the - * array. - * - * @tparam T Type of elements held in array_ptr. - * - * @param array_ptr The pointer to the array to viewed. - * @param array_size The number of T elements in the array. - * - * @return The Span to array_ptr with a size of array_size. - * - * @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) -{ - return Span(array_ptr, array_size); -} - -/**@}*/ - -/**@}*/ - -} // namespace mbed - -#endif /* MBED_PLATFORM_SPAN_H_ */ diff --git a/platform/Stream.h b/platform/Stream.h deleted file mode 100644 index 03bc7dc..0000000 --- a/platform/Stream.h +++ /dev/null @@ -1,102 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_STREAM_H -#define MBED_STREAM_H - -#include "platform/platform.h" -#include "platform/FileLike.h" -#include "platform/NonCopyable.h" -#include "platform/mbed_toolchain.h" -#include -#include - -namespace mbed { -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_Stream Stream class - * @{ - */ - -extern void mbed_set_unbuffered_stream(std::FILE *_file); - -/** File stream - * - * @note Synchronization level: Set by subclass - */ -class Stream : public FileLike, private NonCopyable { - -public: - Stream(const char *name = NULL); - virtual ~Stream(); - -#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY - int putc(int c); - int puts(const char *s); - int getc(); - char *gets(char *s, int size); - 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 *() - { - return _file; - } - -#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY - virtual int close(); - virtual ssize_t write(const void *buffer, size_t length); - virtual ssize_t read(void *buffer, size_t length); - virtual off_t seek(off_t offset, int whence); - virtual off_t tell(); - virtual void rewind(); - virtual int isatty(); - virtual int sync(); - virtual off_t size(); - -protected: - virtual int _putc(int c) = 0; - virtual int _getc() = 0; - -#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY - std::FILE *_file; -#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY - - /** Acquire exclusive access to this object. - */ - virtual void lock() - { - // Stub - } - - /** Release exclusive access to this object. - */ - virtual void unlock() - { - // Stub - } -}; -/**@}*/ - -/**@}*/ -} // namespace mbed - -#endif - diff --git a/platform/Transaction.h b/platform/Transaction.h deleted file mode 100644 index 1d8d4cd..0000000 --- a/platform/Transaction.h +++ /dev/null @@ -1,89 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2015-2019 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_TRANSACTION_H -#define MBED_TRANSACTION_H - -#include "platform/platform.h" - -namespace mbed { -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_Transaction Transaction class - * @{ - */ - -/** Transaction structure - */ -typedef struct { - void *tx_buffer; /**< Tx buffer */ - size_t tx_length; /**< Length of Tx buffer*/ - void *rx_buffer; /**< Rx buffer */ - size_t rx_length; /**< Length of Rx buffer */ - uint32_t event; /**< Event for a transaction */ - event_callback_t callback; /**< User's callback */ - uint8_t width; /**< Buffer's word width (8, 16, 32, 64) */ -} transaction_t; - -/** Transaction class defines a transaction. - * - * @note Synchronization level: Not protected - */ -template -class Transaction { -public: - Transaction(Class *tpointer, const transaction_t &transaction) : _obj(tpointer), _data(transaction) - { - } - - Transaction() : _obj(), _data() - { - } - - ~Transaction() - { - } - - /** Get object's instance for the transaction - * - * @return The object which was stored - */ - Class *get_object() - { - return _obj; - } - - /** Get the transaction - * - * @return The transaction which was stored - */ - transaction_t *get_transaction() - { - return &_data; - } - -private: - Class *_obj; - transaction_t _data; -}; -/**@}*/ - -/**@}*/ -} - -#endif diff --git a/platform/include/platform/ATCmdParser.h b/platform/include/platform/ATCmdParser.h new file mode 100644 index 0000000..0e7f92c --- /dev/null +++ b/platform/include/platform/ATCmdParser.h @@ -0,0 +1,304 @@ +/* Copyright (c) 2017-2019 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. + * + * @section DESCRIPTION + * + * Parser for the AT command syntax + * + */ +#ifndef MBED_ATCMDPARSER_H +#define MBED_ATCMDPARSER_H + +#include +#include "platform/Callback.h" +#include "platform/NonCopyable.h" +#include "platform/FileHandle.h" + +namespace mbed { +/** \addtogroup platform-public-api Platform */ +/** @{*/ +/** + * \defgroup platform_ATCmdParser ATCmdParser class + * @{ + */ + +/** + * Parser class for parsing AT commands + * + * Here are some examples: + * @code + * BufferedSerial serial = BufferedSerial(D1, D0); + * ATCmdParser at = ATCmdParser(&serial, "\r\n"); + * int value; + * char buffer[100]; + * + * at.send("AT") && at.recv("OK"); + * at.send("AT+CWMODE=%d", 3) && at.recv("OK"); + * at.send("AT+CWMODE?") && at.recv("+CWMODE:%d\r\nOK", &value); + * at.recv("+IPD,%d:", &value); + * at.read(buffer, value); + * at.recv("OK"); + * @endcode + */ + +class ATCmdParser : private NonCopyable { +private: + // File handle + // Not owned by ATCmdParser + FileHandle *_fh; + + int _buffer_size; + char *_buffer; + int _timeout; + + // Parsing information + const char *_output_delimiter; + int _output_delim_size; + int _oob_cb_count; + char _in_prev; + bool _dbg_on; + bool _aborted; + + struct oob { + unsigned len; + const char *prefix; + mbed::Callback cb; + oob *next; + }; + oob *_oobs; + + /** + * Receive an AT response + * + * Receives a formatted response using scanf style formatting + * @see scanf + * + * Responses are parsed line at a time. + * If multiline is set to false parse only one line otherwise parse multiline response + * Any received data that does not match the response is ignored until + * a timeout occurs. + * + * @param response scanf-like format string of response to expect + * @param ... all scanf-like arguments to extract from response + * @param multiline determinate if parse one or multiple lines. + * @return number of bytes read or -1 on failure + */ + int vrecvscanf(const char *response, std::va_list args, bool multiline); + +public: + + /** + * Constructor + * + * @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), _oob_cb_count(0), _in_prev(0), _aborted(false), _oobs(NULL) + { + _buffer = new char[buffer_size]; + set_timeout(timeout); + set_delimiter(output_delimiter); + debug_on(debug); + } + + /** + * Destructor + */ + ~ATCmdParser() + { + while (_oobs) { + struct oob *oob = _oobs; + _oobs = oob->next; + delete oob; + } + delete[] _buffer; + } + + /** + * Allows timeout to be changed between commands + * + * @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) + { + _timeout = timeout; + } + + /** + * Sets 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) + { + _output_delimiter = output_delimiter; + _output_delim_size = strlen(output_delimiter); + } + + /** + * Allows traces from modem to be turned on or off + * + * @param on Set as 1 to turn on traces and 0 to disable traces. + */ + void debug_on(uint8_t on) + { + _dbg_on = (on) ? 1 : 0; + } + + /** + * Sends an AT command + * + * Sends a formatted command using printf style formatting + * @see printf + * + * @param command printf-like format string of command to send which + * is appended with a newline + * @param ... all printf-like arguments to insert into command + * @return true only if command is successfully sent + */ + bool send(const char *command, ...) MBED_PRINTF_METHOD(1, 2); + + bool vsend(const char *command, std::va_list args); + + /** + * Receive an AT response + * + * Receives a formatted response using scanf style formatting + * @see scanf + * + * Responses are parsed line at a time. + * Any received data that does not match the response is ignored until + * a timeout occurs. + * + * @param response scanf-like format string of response to expect + * @param ... all scanf-like arguments to extract from response + * @return true only if response is successfully matched + */ + bool recv(const char *response, ...) MBED_SCANF_METHOD(1, 2); + + bool vrecv(const char *response, std::va_list args); + + /** + * Write a single byte to the underlying stream + * + * @param c The byte to write + * @return The byte that was written or -1 during a timeout + */ + int putc(char c); + + /** + * Get a single byte from the underlying stream + * + * @return The byte that was read or -1 during a timeout + */ + int getc(); + + /** + * Write an array of bytes to the underlying stream + * + * @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); + + /** + * Read an array of bytes from the underlying stream + * + * @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); + + /** + * Direct printf to underlying stream + * @see 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, std::va_list args); + + /** + * Direct scanf on underlying stream + * This function does not itself match whitespace in its format string, so \n is not significant to it. + * It should be used only when certain string is needed or format ends with certain character, otherwise + * it will fill the output with one character. + * @see 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, 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 + * @note out-of-band data is only processed during a scanf call + */ + void oob(const char *prefix, mbed::Callback func); + + /** + * @brief remove_oob Removes oob callback handler + * @param prefix Prefix to identify oob to be removed. + */ + void remove_oob(const char *prefix); + + /** + * Flushes the underlying stream + */ + void flush(); + + /** + * Abort current recv + * + * Can be called from out-of-band handler to interrupt the current + * recv operation. + */ + void abort(); + + /** + * Process out-of-band data + * + * Process out-of-band data in the receive buffer. This function + * returns immediately if there is no data to process. + * + * @return true if out-of-band data processed, false otherwise + */ + bool process_oob(void); +}; + +/**@}*/ + +/**@}*/ + +} //namespace mbed + +#endif //MBED_ATCMDPARSER_H diff --git a/platform/include/platform/CThunk.h b/platform/include/platform/CThunk.h new file mode 100644 index 0000000..2c9c751 --- /dev/null +++ b/platform/include/platform/CThunk.h @@ -0,0 +1,171 @@ +/* Copyright (c) 2014-2019 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. + */ + + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_CThunk CThunk class + * @{ + */ + +/* General C++ Object Thunking class + * + * - allows direct callbacks to non-static C++ class functions + * - keeps track for the corresponding class instance + * - supports an optional context parameter for the called function + * - ideally suited for class object receiving interrupts (NVIC_SetVector) + */ + +#ifndef __CTHUNK_H__ +#define __CTHUNK_H__ + +#include "platform/internal/CThunkBase.h" + +/** + * Class for created a pointer with data bound to it + * + * @note Synchronization level: Not protected + */ +template +class CThunk: private CThunkBase { +public: + typedef void (T::*CCallbackSimple)(void); + typedef void (T::*CCallback)(void *context); + + inline CThunk(T *instance) + { + init(instance, NULL, NULL); + } + + inline CThunk(T *instance, CCallback callback) + { + init(instance, callback, NULL); + } + + ~CThunk() + { + if (_entry != NULL) { + cthunk_free(_entry); + _entry = NULL; + } + } + + inline CThunk(T *instance, CCallbackSimple callback) + { + init(instance, (CCallback)callback, NULL); + } + + inline CThunk(T &instance, CCallback callback) + { + init(instance, callback, NULL); + } + + inline CThunk(T &instance, CCallbackSimple callback) + { + init(instance, (CCallback)callback, NULL); + } + + inline CThunk(T &instance, CCallback callback, void *context) + { + init(instance, callback, context); + } + + inline void callback(CCallback callback) + { + _callback = callback; + } + + inline void callback(CCallbackSimple callback) + { + _callback_simple = callback; + } + + inline void context(void *context) + { + _context = context; + } + + inline void context(uint32_t context) + { + _context = (void *)context; + } + + inline uint32_t entry(void) + { + if (_entry == NULL) { + _entry = cthunk_alloc(this); + } + return (uint32_t)_entry; + } + + /* get thunk entry point for connecting rhunk to an IRQ table */ + inline operator CThunkEntry(void) + { + return (CThunkEntry)entry(); + } + + /* get thunk entry point for connecting rhunk to an IRQ table */ + inline operator uint32_t(void) + { + return entry(); + } + + /* simple test function */ + inline void call(void) + { + (((CThunkEntry)(entry()))()); + } + +private: + T *_instance; + void *_context; + union { + CCallbackSimple _callback_simple; + CCallback _callback; + }; + + CThunkEntry _entry; + + static void trampoline(CThunkBase *base) + { + CThunk *self = static_cast*>(base); + T *instance = self->_instance; + void *context = self->_context; + CCallback callback = self->_callback; + + if (instance && callback) { + (instance->*callback)(context); + } + } + + inline void init(T *instance, CCallback callback, void *context) + { + _instance = instance; + _context = context; + _callback = callback; + _trampoline = &trampoline; + _entry = 0; + } +}; + +/**@}*/ + +/**@}*/ + +#endif/*__CTHUNK_H__*/ + diff --git a/platform/include/platform/Callback.h b/platform/include/platform/Callback.h new file mode 100644 index 0000000..e76a4f1 --- /dev/null +++ b/platform/include/platform/Callback.h @@ -0,0 +1,838 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_CALLBACK_H +#define MBED_CALLBACK_H + +#include +#include +#include +#include +#include "platform/mbed_assert.h" +#include "platform/mbed_toolchain.h" +#include +#include + +// Controlling switches from config: +// MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL - support storing non-trivial function objects +// MBED_CONF_PLATFORM_CALLBACK_COMPARABLE - support memcmp comparing stored objects (requires zero padding) + +#ifdef __ICCARM__ +/* Force platform.callback-nontrivial for IAR */ +#undef MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL +#define MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 1 +#endif + + +namespace mbed { +/** \addtogroup platform-public-api */ +/** @{*/ +/** + * \defgroup platform_Callback Callback class + * @{ + */ + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + */ +template +class Callback; + +namespace detail { + +/* Convert pointer-to-member type to member type */ +template +struct member_type { }; + +template +struct member_type : mstd::type_identity { }; + +template +using member_type_t = typename member_type::type; + +/* Remove cv-qualifiers and lvalue ref-qualifiers */ +/* Not rvalue - we store the function object, so are always going to call it on an lvalue */ +template +struct unqualify_fn { }; + +// *INDENT-OFF* +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +#if __cplusplus >=201703 || __cpp_noexcept_function_type >= 201510 +/* We have to spell out all c/v/ref/noexcept versions here, as specialization needs exact type match */ +/* Compare to callback() and deduction guides, where dropping the noexcept is a permitted conversion */ +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +template +struct unqualify_fn : mstd::type_identity { }; +#endif + +template +using unqualify_fn_t = typename unqualify_fn::type; + +template ::value, int> = 0> +R invoke_r(F&& f, Args&&... args) +{ + return mstd::invoke(std::forward(f), std::forward(args)...); +} + +template ::value, int> = 0> +R invoke_r(F&& f, Args&&... args) +{ + mstd::invoke(std::forward(f), std::forward(args)...); +} + +template +struct can_null_check : + mstd::disjunction< + std::is_function>, + std::is_member_pointer + > { +}; +// *INDENT-ON* + +struct [[gnu::may_alias]] CallbackBase { + // Storage is sufficient to hold at least a pointer to member + // function, and an object pointer. + struct _model_function_object { + struct _class; + void (_class::*_methodfunc)(int); + void *obj; + }; + + /* Notes on the [[gnu::may_alias]] attribute here. + * + * The CallbackBase::Store is subject to aliasing problems if ever copied via a trivial copy. + * This issue is described here: + * + * https://answers.launchpad.net/gcc-arm-embedded/+question/686870/+index + * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0593r5.html + * + * The paper p0593 proposes to solve the problem via a language Defect Report, which would make this + * code valid - it would become legal to copy a trivial object into char array storage. (But not + * aligned_storage_t, as of version 5 - I've suggested a revision). + * + * Real-life problems have only been seen in GCC when the code used aligned_storage_t. + * + * The libstdc++ implementation of std::function uses the [[gnu::may_alias]] attribute itself to avoid + * problems when it swaps locally-stored functors; we need it for copy-assignment too. + * + * It appears [[gnu::may_alias]] doesn't work through composition - it's not sufficent to mark just the + * `Store` type, we have to mark the whole `Callback` if we're going to let the compiler + * implicitly define the trivial copy for it. This potentially could lead to an issue if a `Callback` + * was used in a trivially-copyable type itself, but this seems an unlikely use case. The p0593r5 + * change would, if correctly implemented, work in composition. + * + * Although, to further increase the confusion, it appears that using a character array does work + * fine without may_alias, while aligned_storage_t does not. I've seen a suggestion that GCC 8 + * may have implicit "may_alias" on character arrays, rendering the attribute in std::function + * and here redundant on current GCC: + * + * https://gcc.gnu.org/ml/gcc-help/2017-06/msg00102.html + * + * For maximum safety, this version now avoids aligned_storage_t, and also has the possibly-redundant + * attribute at each level. + * + * C++17 says that implementations ignore unrecognized attributes, and IAR+clang comply with this + * even in C++14 mode, so we add [[gnu::may_alias]] unconditionally. + */ + struct alignas(_model_function_object) [[gnu::may_alias]] Store { + char data[sizeof(_model_function_object)]; + }; + Store _storage; + +#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + // Dynamically dispatched operations + const struct ops { + void (*call)(); // type-erased function pointer + void (*copy)(Store &, const Store &); + void (*dtor)(Store &); + } *_ops; + + // Control + using Control = const ops *; + + // Construct as empty + CallbackBase(std::nullptr_t) noexcept : _ops(nullptr) { } +#else + void (*_call)(); // type-erased function pointer + + using Control = void(*)(); + + // Construct as empty + CallbackBase(std::nullptr_t) noexcept : _call(nullptr) { } +#endif + + // Default constructor - no initialization + CallbackBase() = default; + + Control &control() + { +#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + return _ops; +#else + return _call; +#endif + } + + const Control &control() const + { +#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + return _ops; +#else + return _call; +#endif + } + + auto call_fn() const + { +#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + return _ops->call; +#else + return _call; +#endif + } + + // Clear to empty - does not destroy + void clear() noexcept + { + // For copy efficiency we only zero out the operation pointer + // Therefore storage is undefined when we are empty. + // Callback-to-Callback comparison operator has to deal with this, + // but such comparisons are rare. Comparisons to empty are efficient. + control() = nullptr; + } + +#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + // Copy from another CallbackBase - assumes we are uninitialised + void copy(const CallbackBase &other) + { + _ops = other._ops; + if (_ops) { + _ops->copy(_storage, other._storage); + } + } +#else + void swap(CallbackBase &other) noexcept + { + std::swap(_storage, other._storage); + std::swap(_call, other._call); + } +#endif + + // Destroy anything we hold - does not reset, so we are in undefined state afterwards. + // Must be followed by copy, move, reset, or destruction of the CallbackBase + void destroy() + { +#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + if (_ops) { + _ops->dtor(_storage); + } +#endif + } + +#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + // Copy construct F into storage + template + static void target_copy(Store &d, const Store &p) + { + const F &f = reinterpret_cast(p); + new (&d) F(f); + } + + // Destroy F in storage + template + static void target_dtor(Store &p) + { + F &f = reinterpret_cast(p); + f.~F(); + } + + // Trivial copy construction into storage + static void trivial_target_copy(Store &d, const Store &p) noexcept + { + std::memcpy(&d, &p, sizeof d); + } + + // Trivial destruction in storage + static void trivial_target_dtor(Store &p) noexcept + { + } +#endif +}; + +} + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + */ +template +class Callback : private detail::CallbackBase { +public: + using result_type = R; + + /** Create an empty Callback + */ + Callback() noexcept : CallbackBase(nullptr) { } + + /** Create an empty Callback + */ + Callback(std::nullptr_t) noexcept : Callback() { } + +#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + /** Copy a Callback + * @param other The Callback to copy + */ + Callback(const Callback &other) : CallbackBase() + { + copy(other); + } + + /** Move a Callback + * @param other The Callback to move + */ + Callback(Callback &&other) : CallbackBase() + { + // Move constructor exists to ensure that it gets selected + // in preference to the universal constructor form. + copy(other); + } +#else // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + Callback(const Callback &other) = default; + Callback(Callback &&other) = default; +#endif // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template::value, int> = 0> + Callback(Obj obj, Method method) : CallbackBase() + { + generate([obj, method](ArgTs... args) { + return detail::invoke_r(method, obj, std::forward(args)...); + }); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template::value, int> = 0> + Callback(Fn func, BoundArg arg) : CallbackBase() + { + generate([func, arg](ArgTs... args) { + return detail::invoke_r(func, arg, std::forward(args)...); + }); + } + + // *INDENT-OFF* + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a a few words of storage + */ + template ::value && + mstd::is_invocable_r::value, int> = 0> + Callback(F f) : CallbackBase() + { + static_assert(std::is_copy_constructible::value, "Callback F must be CopyConstructible"); + generate(std::move(f)); + } + + /** Create a Callback with a function pointer + * @param f Function pointer to attach + */ + template ::value && + mstd::is_invocable_r::value, int> = 0> + Callback(F f) : CallbackBase() + { + static_assert(std::is_copy_constructible::value, "Callback F must be CopyConstructible"); + if (!f) { + clear(); + } else { + generate(std::move(f)); + } + } + // *INDENT-ON* + + /** Destroy a callback + */ +#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + ~Callback() + { + destroy(); + } +#else + ~Callback() = default; +#endif + + /** Swap a callback + */ + void swap(Callback &that) noexcept + { +#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + if (this != &that) { + Callback temp(std::move(*this)); + *this = std::move(that); + that = std::move(temp); + } +#else + CallbackBase::swap(that); +#endif + } + +#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + /** Assign a callback + */ + Callback &operator=(const Callback &that) + { + // C++ standard says to use swap, but that's overkill with no exceptions + // Callback(f).swap(*this); + if (this != &that) { + destroy(); + copy(that); + } + + return *this; + } + + /** Assign a callback + */ + Callback &operator=(Callback &&that) + { + if (this != &that) { + destroy(); + copy(that); + } + + return *this; + } +#else // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + Callback &operator=(const Callback &that) = default; + Callback &operator=(Callback &&that) = default; +#endif // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + + /** Assign a callback + */ + // C++ std::function lacks the is_same restriction here, which would mean non-const lvalue references hit this, + // rather than the normal copy assignment (`F &&` is a better match for `Callback &` than `const Callback &`). + // Wouldn't matter if both used the swap form, but having cut it down, for code size want to ensure we don't use this + // instead of copy assignment. (If nontrivial disabled, definitely want to use the default copy assignment, and + // if nontrivial enabled, we know this doesn't handle self-assignment). + // *INDENT-OFF* + template ::value && + !mstd::is_same, Callback>::value>> + Callback &operator=(F &&f) + { + // C++ standard says to use swap, but that's overkill with no exceptions + // Callback(std::forward(that)).swap(*this); + this->~Callback(); + new (this) Callback(std::forward(f)); + return *this; + } + // *INDENT-ON* + + template + Callback &operator=(std::reference_wrapper f) noexcept + { + // C++ standard says to use swap, but that's overkill with no exceptions + // Callback(f).swap(*this); + this->~Callback(); + new (this) Callback(f); + return *this; + } + + /** Empty a callback + */ + Callback &operator=(std::nullptr_t) noexcept + { + destroy(); + clear(); + + return *this; + } + + /** Call the attached function + */ + R call(ArgTs... args) const + { + MBED_ASSERT(bool(*this)); + auto op_call = reinterpret_cast(call_fn()); + return op_call(this, args...); + } + + /** Call the attached function + */ + R operator()(ArgTs... args) const + { + return call(args...); + } + + /** Test if function has been assigned + */ + explicit operator bool() const noexcept + { + return control(); + } + +#if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE + /** Test for equality + * + * @note This only compares stored objects byte-wise using memcmp + * after checking that they're the same type. It does *not* use + * any equality operator defined for the class. + * + * @note This is an extension compared to std::function, and supporting + * it requires extra code even if the comparison is never used. + * Avoid using this operator if possible, so that the option + * `platform.callback-comparable` can be turned off to save ROM. + */ + friend bool operator==(const Callback &l, const Callback &r) noexcept + { + if (l.control() != r.control()) { + /* Type of stored object differs */ + return false; + } + if (!l) { + /* Both must be empty, as we checked the types match. Do not + * check storage in this case - this simplifies clear(), and + * clears are far more common than callback comparison. + */ + return true; + } + return memcmp(&l._storage, &r._storage, sizeof(Store)) == 0; + } +#endif + + /** Test for emptiness + */ + friend bool operator==(const Callback &f, std::nullptr_t) noexcept + { + return !f; + } + + /** Test for emptiness + */ + friend bool operator==(std::nullptr_t, const Callback &f) noexcept + { + return !f; + } + +#if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE + /** Test for inequality + * + * @see operator==(const Callback &l, const Callback &r) + */ + friend bool operator!=(const Callback &l, const Callback &r) noexcept + { + return !(l == r); + } +#endif + + /** Test for non-emptiness + */ + friend bool operator!=(const Callback &f, std::nullptr_t) noexcept + { + return bool(f); + } + + /** Test for non-emptiness + */ + friend bool operator!=(std::nullptr_t, const Callback &f) noexcept + { + return bool(f); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @param args Arguments to be called with function func + * @return the value as determined by func which is of + * type and determined by the signature of func + */ + static R thunk(void *func, ArgTs... args) + { + return static_cast(func)->call(args...); + } + +private: + using call_type = R(const CallbackBase *, ArgTs...); + + // *INDENT-OFF* + // Generate operations for function object + // Storage assumed to be uninitialised - destructor should have already been called if it was previously used + // When generating, function object should always be moved + template ::value>> + void generate(F &&f) + { +#ifndef __ICCARM__ /* This assert fails on IAR for unknown reason */ + static_assert(std::is_same), call_type>::value, "Call type mismatch"); +#endif + static_assert(sizeof(Callback) == sizeof(CallbackBase), "Callback should be same size as CallbackBase"); + static_assert(std::is_trivially_copyable::value, "CallbackBase expected to be TriviallyCopyable"); + + // Set the control pointer +#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + // Generates one static ops for each tuple + // But the functions used for copy/move/dtor depend only on F, and even then only if non-trivial. + // `call` is type-erased - we cast from our call_type to the void (*)(void) in CallbackBase + // This should be a ROMmed constant table, but formally it can't be constexpr because of the reinterpret_cast :( + static const ops ops = { + reinterpret_cast(target_call), + std::is_trivially_copy_constructible::value ? trivial_target_copy : target_copy, + std::is_trivially_destructible::value ? trivial_target_dtor : target_dtor, + }; + _ops = &ops; +#else // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + // Avoid the need for the const ops table - just one function pointer in the Callback itself + _call = reinterpret_cast(target_call); + static_assert(std::is_trivially_copyable::value, "F must be TriviallyCopyable. Turn on Mbed configuration option 'platform.callback-nontrivial' to use more complex function objects"); + static_assert(std::is_trivially_copyable::value, "Callback expected to be TriviallyCopyable"); +#endif // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL + + // Move the functor into storage + static_assert(sizeof(F) <= sizeof(Store) && alignof(F) <= alignof(Store), + "Type F must not exceed the size of the Callback class"); + new (&_storage) F(std::move(f)); + +#if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE + // Zero out any padding - required for Callback-to-Callback comparisons. + if (sizeof(F) < sizeof(Store)) { + std::memset(reinterpret_cast(&_storage) + sizeof(F), 0, sizeof(Store) - sizeof(F)); + } +#endif + } + // *INDENT-ON* + + // Target call routine - custom needed for each tuple + template + static R target_call(const CallbackBase *p, ArgTs... args) + { + // Need for const_cast here correlates to a std::function bug - see P0045 and N4159 + F &f = const_cast(reinterpret_cast(p->_storage)); + return detail::invoke_r(f, std::forward(args)...); + } +}; + +// Internally used event type +using event_callback_t = Callback; + +template +void swap(Callback &lhs, Callback &rhs) noexcept +{ + lhs.swap(rhs); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template +Callback callback(R(*func)(ArgTs...) = nullptr) noexcept +{ + return Callback(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template +Callback callback(const Callback &func) +{ + return Callback(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template +Callback callback(Callback &&func) noexcept +{ + return Callback(std::move(func)); +} + +/** 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 inferred type + */ +template +Callback callback(U *obj, R(T::*method)(ArgTs...)) noexcept +{ + return Callback(obj, method); +} + +template +Callback callback(U *obj, R(T::*method)(ArgTs...) &) noexcept +{ + return Callback(obj, method); +} + +template +Callback callback(const U *obj, R(T::*method)(ArgTs...) const) noexcept +{ + return Callback(obj, method); +} + +template +Callback callback(const U *obj, R(T::*method)(ArgTs...) const &) noexcept +{ + return Callback(obj, method); +} + +template +Callback callback(volatile U *obj, R(T::*method)(ArgTs...) volatile) noexcept +{ + return Callback(obj, method); +} + +template +Callback callback(volatile U *obj, R(T::*method)(ArgTs...) volatile &) noexcept +{ + return Callback(obj, method); +} + +template +Callback callback(const volatile U *obj, R(T::*method)(ArgTs...) const volatile) noexcept +{ + return Callback(obj, method); +} + +template +Callback callback(const volatile U *obj, R(T::*method)(ArgTs...) const volatile &) noexcept +{ + return Callback(obj, method); +} + +/** 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 inferred type + */ +template +Callback callback(R(*func)(T *, ArgTs...), U *arg) noexcept +{ + return Callback(func, arg); +} + +template +Callback callback(R(*func)(const T *, ArgTs...), const U *arg) noexcept +{ + return Callback(func, arg); +} + +template +Callback callback(R(*func)(volatile T *, ArgTs...), volatile U *arg) noexcept +{ + return Callback(func, arg); +} + +template +Callback callback(R(*func)(const volatile T *, ArgTs...), const volatile U *arg) noexcept +{ + return Callback(func, arg); +} + +/** Create a Create a callback class with type inferred from the arguments + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback::operator())>>> +callback(F &&f) +{ + return Callback::operator())>>>(std::forward(f)); +} + +#if __cplusplus >= 201703 || __cpp_deduction_guides >= 201703 +/* Deduction guides that can replace callback() helper */ +template +Callback(R(*)(Args...)) -> Callback; +template +Callback(F) -> Callback>>; +template +Callback(U *obj, R(T::*method)(ArgTs...)) -> Callback; +template +Callback(U *obj, R(T::*method)(ArgTs...) &) -> Callback; +template +Callback(const U *obj, R(T::*method)(ArgTs...) const) -> Callback; +template +Callback(const U *obj, R(T::*method)(ArgTs...) const &) -> Callback; +template +Callback(volatile U *obj, R(T::*method)(ArgTs...) volatile) -> Callback; +template +Callback(volatile U *obj, R(T::*method)(ArgTs...) volatile &) -> Callback; +template +Callback(const volatile U *obj, R(T::*method)(ArgTs...) const volatile) -> Callback; +template +Callback(const volatile U *obj, R(T::*method)(ArgTs...) const volatile &) -> Callback; +template +Callback(R(*func)(T *, ArgTs...), U *arg) -> Callback; +template +Callback(R(*func)(const T *, ArgTs...), const U *arg) -> Callback; +template +Callback(R(*func)(volatile T *, ArgTs...), volatile U *arg) -> Callback; +template +Callback(R(*func)(const volatile T *, ArgTs...), const volatile U *arg) -> Callback; +#endif + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif diff --git a/platform/include/platform/CircularBuffer.h b/platform/include/platform/CircularBuffer.h new file mode 100644 index 0000000..c167444 --- /dev/null +++ b/platform/include/platform/CircularBuffer.h @@ -0,0 +1,216 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015-2019 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_CIRCULARBUFFER_H +#define MBED_CIRCULARBUFFER_H + +#include +#include "platform/mbed_critical.h" +#include "platform/mbed_assert.h" + +namespace mbed { + +namespace internal { +/* Detect if CounterType of the Circular buffer is of unsigned type. */ +template +struct is_unsigned { + static const bool value = false; +}; +template<> +struct is_unsigned { + static const bool value = true; +}; +template<> +struct is_unsigned { + static const bool value = true; +}; +template<> +struct is_unsigned { + static const bool value = true; +}; +template<> +struct is_unsigned { + static const bool value = true; +}; +template<> +struct is_unsigned { + static const bool value = true; +}; +} + +/** \addtogroup platform-public-api */ +/** @{*/ +/** + * \defgroup platform_CircularBuffer CircularBuffer functions + * @{ + */ + +/** Templated Circular buffer class + * + * @note Synchronization level: Interrupt safe + * @note CounterType must be unsigned and consistent with BufferSize + */ +template +class CircularBuffer { +public: + CircularBuffer() : _head(0), _tail(0), _full(false) + { + MBED_STATIC_ASSERT( + internal::is_unsigned::value, + "CounterType must be unsigned" + ); + + MBED_STATIC_ASSERT( + (sizeof(CounterType) >= sizeof(uint32_t)) || + (BufferSize < (((uint64_t) 1) << (sizeof(CounterType) * 8))), + "Invalid BufferSize for the CounterType" + ); + } + + ~CircularBuffer() + { + } + + /** Push the transaction to the buffer. This overwrites the buffer if it's + * full + * + * @param data Data to be pushed to the buffer + */ + void push(const T &data) + { + core_util_critical_section_enter(); + if (full()) { + _tail++; + if (_tail == BufferSize) { + _tail = 0; + } + } + _pool[_head++] = data; + if (_head == BufferSize) { + _head = 0; + } + if (_head == _tail) { + _full = true; + } + core_util_critical_section_exit(); + } + + /** Pop the transaction from the buffer + * + * @param data Data to be popped from the buffer + * @return True if the buffer is not empty and data contains a transaction, false otherwise + */ + bool pop(T &data) + { + bool data_popped = false; + core_util_critical_section_enter(); + if (!empty()) { + data = _pool[_tail++]; + if (_tail == BufferSize) { + _tail = 0; + } + _full = false; + data_popped = true; + } + core_util_critical_section_exit(); + return data_popped; + } + + /** Check if the buffer is empty + * + * @return True if the buffer is empty, false if not + */ + bool empty() const + { + core_util_critical_section_enter(); + bool is_empty = (_head == _tail) && !_full; + core_util_critical_section_exit(); + return is_empty; + } + + /** Check if the buffer is full + * + * @return True if the buffer is full, false if not + */ + bool full() const + { + core_util_critical_section_enter(); + bool full = _full; + core_util_critical_section_exit(); + return full; + } + + /** Reset the buffer + * + */ + void reset() + { + core_util_critical_section_enter(); + _head = 0; + _tail = 0; + _full = false; + core_util_critical_section_exit(); + } + + /** Get the number of elements currently stored in the circular_buffer */ + CounterType size() const + { + core_util_critical_section_enter(); + CounterType elements; + if (!_full) { + if (_head < _tail) { + elements = BufferSize + _head - _tail; + } else { + elements = _head - _tail; + } + } else { + elements = BufferSize; + } + core_util_critical_section_exit(); + return elements; + } + + /** Peek into circular buffer without popping + * + * @param data Data to be peeked from the buffer + * @return True if the buffer is not empty and data contains a transaction, false otherwise + */ + bool peek(T &data) const + { + bool data_updated = false; + core_util_critical_section_enter(); + if (!empty()) { + data = _pool[_tail]; + data_updated = true; + } + core_util_critical_section_exit(); + return data_updated; + } + +private: + T _pool[BufferSize]; + CounterType _head; + CounterType _tail; + bool _full; +}; + +/**@}*/ + +/**@}*/ + +} + +#endif diff --git a/platform/include/platform/CriticalSectionLock.h b/platform/include/platform/CriticalSectionLock.h new file mode 100644 index 0000000..3f9aa62 --- /dev/null +++ b/platform/include/platform/CriticalSectionLock.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2019 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_CRITICALSECTIONLOCK_H +#define MBED_CRITICALSECTIONLOCK_H + +#include "platform/mbed_toolchain.h" + +namespace mbed { +/** \addtogroup platform-public-api */ +/** @{*/ +/** + * \defgroup platform_CriticalSectionLock CriticalSectionLock functions + * @{ + */ + +/** RAII object for disabling, then restoring, interrupt state + * Usage: + * @code + * + * // RAII style usage + * unsigned int atomic_counter_increment(unsigned int &counter) { + * CriticalSectionLock lock; + * // Code in this block will run with interrupts disabled + * // Interrupts will be restored to their previous state automatically + * // at the end of function scope + * return ++counter; + * } + * + * // free locking usage + * unsigned int atomic_counter_decrement(unsigned int &counter) { + * CriticalSectionLock::enable(); + * // Code in this block will run with interrupts disabled + * counter--; + * CriticalSectionLock::disable(); // need explicitly to disable critical section lock + * // interrupts will be restored to their previous state here + * return counter; + * } + * + * @endcode + */ +class CriticalSectionLock { +public: + CriticalSectionLock(); + + ~CriticalSectionLock(); + + /** Mark the start of a critical section + */ + static void enable(); + + /** Mark the end of a critical section + */ + static void disable(); +}; + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif diff --git a/platform/include/platform/DeepSleepLock.h b/platform/include/platform/DeepSleepLock.h new file mode 100644 index 0000000..c4841aa --- /dev/null +++ b/platform/include/platform/DeepSleepLock.h @@ -0,0 +1,70 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2019 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_DEEPSLEEPLOCK_H +#define MBED_DEEPSLEEPLOCK_H + +#include +#include + +namespace mbed { +/** \addtogroup platform-public-api */ +/** @{*/ +/** + * \defgroup platform_DeepSleepLock DeepSleepLock functions + * @{ + */ + +/** RAII object for disabling, then restoring the deep sleep mode + * Usage: + * @code + * + * void f() { + * // some code here + * { + * DeepSleepLock lock; + * // Code in this block will run with the deep sleep mode locked + * } + * // deep sleep mode will be restored to their previous state + * } + * @endcode + */ +class DeepSleepLock { +private: + uint16_t _lock_count; + +public: + DeepSleepLock(); + + ~DeepSleepLock(); + + /** Mark the start of a locked deep sleep section + */ + void lock(); + + /** Mark the end of a locked deep sleep section + */ + void unlock(); +}; + +/**@}*/ + +/**@}*/ + + +} + +#endif diff --git a/platform/include/platform/DirHandle.h b/platform/include/platform/DirHandle.h new file mode 100644 index 0000000..4c49676 --- /dev/null +++ b/platform/include/platform/DirHandle.h @@ -0,0 +1,115 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_DIRHANDLE_H +#define MBED_DIRHANDLE_H + +#include +#include "platform/mbed_toolchain.h" +#include "platform/NonCopyable.h" + +namespace mbed { +/** \addtogroup platform-public-api */ +/** @{*/ +/** + * \defgroup platform_DirHandle DirHandle functions + * @{ + */ + + +/** 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 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 pointer returned by opendir("/") + * reflects this. + * + * @note to create a directory, @see Dir + * @note Synchronization level: Set by subclass + */ +class DirHandle : private NonCopyable { +public: + virtual ~DirHandle() {} + + /** Read the next directory entry + * + * @param ent The directory entry to fill out + * @return 1 on reading a filename, 0 at end of directory, negative error on failure + */ + virtual ssize_t read(struct dirent *ent) = 0; + + /** Close a directory + * + * @return 0 on success, negative error code on failure + */ + virtual int close() = 0; + + /** Set the current position of the directory + * + * @param offset Offset of the location to seek to, + * must be a value returned from tell + */ + virtual void seek(off_t offset) = 0; + + /** Get the current position of the directory + * + * @return Position of the directory that can be passed to rewind + */ + virtual off_t tell() = 0; + + /** Rewind the current position to the beginning of the directory + */ + virtual void rewind() = 0; + + /** Get the sizeof the directory + * + * @return Number of files in the directory + */ + virtual size_t size() + { + off_t off = tell(); + size_t size = 0; + struct dirent *ent = new struct dirent; + + rewind(); + while (read(ent) > 0) { + size += 1; + } + seek(off); + + delete ent; + return size; + } +}; + +/**@}*/ + +/**@}*/ +} // namespace mbed + +#endif /* MBED_DIRHANDLE_H */ diff --git a/platform/include/platform/FileBase.h b/platform/include/platform/FileBase.h new file mode 100644 index 0000000..f4aac58 --- /dev/null +++ b/platform/include/platform/FileBase.h @@ -0,0 +1,76 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_FILEBASE_H +#define MBED_FILEBASE_H + +typedef int FILEHANDLE; + +#include "platform/platform.h" +#include "platform/SingletonPtr.h" +#include "platform/PlatformMutex.h" +#include "platform/NonCopyable.h" + +namespace mbed { + +typedef enum { + FilePathType, + FileSystemPathType +} PathType; + +/** \defgroup platform-public-api-file File + * \ingroup platform-public-api + */ + +/** + * \defgroup platform_FileBase FileBase class + * \ingroup platform-public-api-file + * @{ + */ + +/** Class FileBase + * + */ + +class FileBase : private NonCopyable { +public: + FileBase(const char *name, PathType t); + virtual ~FileBase(); + + const char *getName(void); + PathType getPathType(void); + + static FileBase *lookup(const char *name, unsigned int len); + + static FileBase *get(int n); + + void set_as_default(); + +private: + static FileBase *_head; + static FileBase *_default; + static SingletonPtr _mutex; + + FileBase *_next; + const char *const _name; + const PathType _path_type; +}; + +/**@}*/ + +} // namespace mbed + +#endif diff --git a/platform/include/platform/FileHandle.h b/platform/include/platform/FileHandle.h new file mode 100644 index 0000000..b666301 --- /dev/null +++ b/platform/include/platform/FileHandle.h @@ -0,0 +1,280 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2019 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_FILEHANDLE_H +#define MBED_FILEHANDLE_H + +typedef int FILEHANDLE; + +#include +#include "platform/Callback.h" +#include "platform/mbed_poll.h" +#include "platform/platform.h" +#include "platform/NonCopyable.h" + +namespace mbed { + +/** + * \defgroup platform_FileHandle FileHandle functions + * \ingroup platform-public-api-file + * @{ + */ + + +/** Class FileHandle + * + * An abstract interface that represents operations on a file-like + * 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 + * @note Synchronization level: Set by subclass + */ +class FileHandle : private NonCopyable { +public: + virtual ~FileHandle() = default; + + /** Read the contents of a file into a buffer + * + * Devices acting as FileHandles should follow POSIX semantics: + * + * * 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 + * + * @param buffer The buffer to read in to + * @param size The number of bytes to read + * @return The number of bytes read, 0 at end of file, negative error on failure + */ + virtual ssize_t read(void *buffer, size_t size) = 0; + + /** Write the contents of a buffer to a file + * + * Devices acting as FileHandles should follow POSIX semantics: + * + * * if blocking, block until all data is written + * * 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 + * @return The number of bytes written, negative error on failure + */ + virtual ssize_t write(const void *buffer, size_t size) = 0; + + /** Move the file position to a given offset from from a given location + * + * @param offset The offset from whence to move to + * @param whence The start of where to seek + * SEEK_SET to start from beginning of file, + * SEEK_CUR to start from current position in file, + * SEEK_END to start from end of file + * @return The new offset of the file, negative error code on failure + */ + virtual off_t seek(off_t offset, int whence = SEEK_SET) = 0; + + /** Close a file + * + * @return 0 on success, negative error code on failure + */ + virtual int close() = 0; + + /** Flush any buffers associated with the file + * + * @return 0 on success, negative error code on failure + */ + virtual int sync() + { + return 0; + } + + /** Check if the file in an interactive terminal device + * + * @return True if the file is a terminal + * @return False if the file is not a terminal + * @return Negative error code on failure + */ + virtual int isatty() + { + return false; + } + + /** Get the file position of the file + * + * @note This is equivalent to seek(0, SEEK_CUR) + * + * @return The current offset in the file, negative error code on failure + */ + virtual off_t tell() + { + return seek(0, SEEK_CUR); + } + + /** Rewind the file position to the beginning of the file + * + * @note This is equivalent to seek(0, SEEK_SET) + */ + virtual void rewind() + { + seek(0, SEEK_SET); + } + + /** Get the size of the file + * + * @return Size of the file in bytes + */ + virtual off_t size(); + + /** Truncate or extend a file. + * + * The file's length is set to the specified value. The seek pointer is + * not changed. If the file is extended, the extended area appears as if + * it were zero-filled. + * + * @param length The requested new length for the file + * + * @return Zero on success, negative error code on failure + */ + virtual int truncate(off_t length) + { + return -EINVAL; + } + + /** 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 nonblocking mode. + * + * @return 0 on success + * @return Negative error code on failure + */ + virtual int set_blocking(bool blocking) + { + return blocking ? 0 : -ENOTTY; + } + + /** Check current blocking or nonblocking mode for file operations. + * + * @return true for blocking mode, false for nonblocking mode. + */ + virtual bool is_blocking() const + { + return true; + } + + /** Enable or disable input + * + * Control enabling of device for input. This is primarily intended + * for temporary power-saving; the overall ability of the device to operate for + * input and/or output may be fixed at creation time, but this call can + * allow input to be temporarily disabled to permit power saving without + * losing device state. + * + * @param enabled true to enable input, false to disable. + * + * @return 0 on success + * @return Negative error code on failure + */ + virtual int enable_input(bool enabled) + { + return -EINVAL; + } + + /** Enable or disable output + * + * Control enabling of device for output. This is primarily intended + * for temporary power-saving; the overall ability of the device to operate for + * input and/or output may be fixed at creation time, but this call can + * allow output to be temporarily disabled to permit power saving without + * losing device state. + * + * @param enabled true to enable output, false to disable. + * + * @return 0 on success + * @return Negative error code on failure + */ + virtual int enable_output(bool enabled) + { + return -EINVAL; + } + + /** Check for poll event flags + * 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. + * + * @returns bitmask of poll events that have occurred. + */ + virtual short poll(short events) const + { + // Possible default for real files + return POLLIN | POLLOUT; + } + + /** 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. + * + * @returns true if the FileHandle is writable. + */ + bool writable() const + { + return poll(POLLOUT) & POLLOUT; + } + + /** 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. + * + * @returns true when there is something available to read. + */ + bool readable() const + { + return poll(POLLIN) & POLLIN; + } + + /** Register a callback on state change of the file. + * + * The specified callback will be called on state changes such as when + * the file can be written to or read from. + * + * 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. + * + * The exact timing of when the registered function + * 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 + */ + virtual void sigio(Callback func) + { + //Default for real files. Do nothing for real files. + } +}; + +/**@}*/ + +} // namespace mbed + +#endif diff --git a/platform/include/platform/FileLike.h b/platform/include/platform/FileLike.h new file mode 100644 index 0000000..5f4409a --- /dev/null +++ b/platform/include/platform/FileLike.h @@ -0,0 +1,52 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_FILELIKE_H +#define MBED_FILELIKE_H + +#include "platform/FileBase.h" +#include "platform/FileHandle.h" +#include "platform/NonCopyable.h" + +namespace mbed { +/** + * \defgroup platform_FileLike FileLike class + * \ingroup platform-public-api-file + * @{ + */ + +/** Class FileLike + * + * A file-like object is one that can be opened with fopen by + * fopen("/name", mode). + * + * @note Synchronization level: Set by subclass + */ +class FileLike : public FileHandle, public FileBase, private NonCopyable { +public: + /** Constructor FileLike + * + * @param name The name to use to open the file. + */ + FileLike(const char *name = NULL) : FileBase(name, FilePathType) {} + virtual ~FileLike() {} +}; + +/**@}*/ + +} // namespace mbed + +#endif diff --git a/platform/include/platform/FilePath.h b/platform/include/platform/FilePath.h new file mode 100644 index 0000000..1740a98 --- /dev/null +++ b/platform/include/platform/FilePath.h @@ -0,0 +1,64 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_FILEPATH_H +#define MBED_FILEPATH_H + +#include "platform/platform.h" + +#include "platform/FileSystemLike.h" +#include "platform/FileLike.h" + +namespace mbed { + +class FileSystem; + +/** + * \defgroup platform_FilePath FilePath class + * \ingroup platform-public-api-file + * @{ + */ + +/** Class FilePath + * + */ +class FilePath { +public: + /** Constructor FilePath + * + * @param file_path The path of file. + */ + FilePath(const char *file_path); + + const char *fileName(void); + + bool isFileSystem(void); + FileSystemLike *fileSystem(void); + + bool isFile(void); + FileLike *file(void); + bool exists(void); + +private: + const char *file_name; + FileBase *fb; +}; + +/**@}*/ + +} // namespace mbed + +#endif diff --git a/platform/include/platform/FileSystemHandle.h b/platform/include/platform/FileSystemHandle.h new file mode 100644 index 0000000..ceedcd9 --- /dev/null +++ b/platform/include/platform/FileSystemHandle.h @@ -0,0 +1,109 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_FILESYSTEMHANDLE_H +#define MBED_FILESYSTEMHANDLE_H + +#include "platform/platform.h" + +#include "platform/FileHandle.h" +#include "platform/DirHandle.h" +#include "platform/NonCopyable.h" + +namespace mbed { +/** + * \defgroup platform_FileSystemHandle FileSystemHandle functions + * \ingroup platform-public-api-file + * @{ + */ + + +/** A filesystem-like object is one that can be used to open file-like + * objects though it by fopen("/name/filename", mode) + * + * Implementations must define at least open (the default definitions + * of the rest of the functions just return error values). + * + * @note Synchronization level: Set by subclass + */ +class FileSystemHandle : private NonCopyable { +public: + /** FileSystemHandle lifetime + */ + virtual ~FileSystemHandle() {} + + /** Open a file on the filesystem + * + * @param file Destination for the handle to a newly created file + * @param filename The name of the file to open + * @param flags The flags to open the file in, one of O_RDONLY, O_WRONLY, O_RDWR, + * bitwise or'd with one of O_CREAT, O_TRUNC, O_APPEND + * @return 0 on success, negative error code on failure + */ + virtual int open(FileHandle **file, const char *filename, int flags) = 0; + + /** Open a directory on the filesystem + * + * @param dir Destination for the handle to the directory + * @param path Name of the directory to open + * @return 0 on success, negative error code on failure + */ + virtual int open(DirHandle **dir, const char *path); + + /** Remove a file from the filesystem. + * + * @param path The name of the file to remove. + * @return 0 on success, negative error code on failure + */ + virtual int remove(const char *path); + + /** Rename a file in the filesystem. + * + * @param path The name of the file to rename. + * @param newpath The name to rename it to + * @return 0 on success, negative error code on failure + */ + virtual int rename(const char *path, const char *newpath); + + /** Store information about the file in a stat structure + * + * @param path The name of the file to find information about + * @param st The stat buffer to write to + * @return 0 on success, negative error code on failure + */ + virtual int stat(const char *path, struct stat *st); + + /** Create a directory in the filesystem. + * + * @param path The name of the directory to create. + * @param mode The permissions with which to create the directory + * @return 0 on success, negative error code on failure + */ + virtual int mkdir(const char *path, mode_t mode); + + /** Store information about the mounted filesystem in a statvfs structure + * + * @param path The name of the file to find information about + * @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); +}; +/**@}*/ + +} // namespace mbed + +#endif diff --git a/platform/include/platform/FileSystemLike.h b/platform/include/platform/FileSystemLike.h new file mode 100644 index 0000000..176e2c7 --- /dev/null +++ b/platform/include/platform/FileSystemLike.h @@ -0,0 +1,57 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_FILESYSTEMLIKE_H +#define MBED_FILESYSTEMLIKE_H + +#include "platform/platform.h" + +#include "platform/FileBase.h" +#include "platform/FileSystemHandle.h" +#include "platform/FileHandle.h" +#include "platform/DirHandle.h" +#include "platform/NonCopyable.h" + +namespace mbed { +/** + * \defgroup platform_FileSystemLike FileSystemLike functions + * \ingroup platform-public-api-file + * @{ + */ + + +/** A filesystem-like object is one that can be used to open file-like + * objects though it by fopen("/name/filename", mode) + * + * Implementations must define at least open (the default definitions + * of the rest of the functions just return error values). + * + * @note Synchronization level: Set by subclass + */ +class FileSystemLike : public FileSystemHandle, public FileBase, private NonCopyable { +public: + /** FileSystemLike lifetime + */ + FileSystemLike(const char *name = NULL) : FileBase(name, FileSystemPathType) {} + virtual ~FileSystemLike() {} + +}; + +/**@}*/ + +} // namespace mbed + +#endif diff --git a/platform/include/platform/LocalFileSystem.h b/platform/include/platform/LocalFileSystem.h new file mode 100644 index 0000000..4ee6b6a --- /dev/null +++ b/platform/include/platform/LocalFileSystem.h @@ -0,0 +1,129 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_LOCALFILESYSTEM_H +#define MBED_LOCALFILESYSTEM_H + +#include "platform/platform.h" + +#if DEVICE_LOCALFILESYSTEM + +#include "platform/FileSystemLike.h" +#include "platform/PlatformMutex.h" +#include "platform/NonCopyable.h" + +namespace mbed { +/** \addtogroup platform-public-api */ +/** @{*/ +/** + * \defgroup platform_LocalFileSystem LocalFileSystem functions + * @{ + */ + +FILEHANDLE local_file_open(const char *name, int flags); + +/** + * @class LocalFileHandle + * @ingroup platform + */ +class LocalFileHandle : public FileHandle, private NonCopyable { + +public: + LocalFileHandle(FILEHANDLE fh); + + virtual int close(); + + virtual ssize_t write(const void *buffer, size_t length); + + virtual ssize_t read(void *buffer, size_t length); + + virtual int isatty(); + + virtual off_t seek(off_t position, int whence); + + virtual int sync(); + + virtual off_t size(); + +protected: + virtual void lock(); + virtual void unlock(); + FILEHANDLE _fh; + int pos; + PlatformMutex _mutex; +}; + +/** A filesystem for accessing the local mbed Microcontroller USB disk drive + * + * This allows programs to read and write files on the same disk drive that is used to program the + * mbed Microcontroller. Once created, the standard C file access functions are used to open, + * read and write files. + * + * @note Synchronization level: Thread safe + * + * Example: + * @code + * #include "mbed.h" + * + * LocalFileSystem local("local"); // Create the local filesystem under the name "local" + * + * int main() { + * FILE *fp = fopen("/local/out.txt", "w"); // Open "out.txt" on the local file system for writing + * fprintf(fp, "Hello World!"); + * fclose(fp); + * remove("/local/out.txt"); // Removes the file "out.txt" from the local file system + * + * DIR *d = opendir("/local"); // Opens the root directory of the local file system + * struct dirent *p; + * while((p = readdir(d)) != NULL) { // Print the names of the files in the local file system + * printf("%s\n", p->d_name); // to stdout. + * } + * closedir(d); + * } + * @endcode + * + * @note + * If the microcontroller program makes an access to the local drive, it will be marked as "removed" + * on the Host computer. This means it is no longer accessible from the Host Computer. + * + * The drive will only re-appear when the microcontroller program exists. Note that if the program does + * not exit, you will need to hold down reset on the mbed Microcontroller to be able to see the drive again! + * @ingroup platform + */ +class LocalFileSystem : public FileSystemLike, private NonCopyable { + // No modifiable state + +public: + LocalFileSystem(const char *n) : FileSystemLike(n) + { + + } + + virtual int open(FileHandle **file, const char *path, int flags); + virtual int open(DirHandle **dir, const char *name); + virtual int remove(const char *filename); +}; + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif + +#endif + diff --git a/platform/include/platform/NonCopyable.h b/platform/include/platform/NonCopyable.h new file mode 100644 index 0000000..e29b8fb --- /dev/null +++ b/platform/include/platform/NonCopyable.h @@ -0,0 +1,195 @@ +/* Copyright (c) 2017-2019 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_NONCOPYABLE_H_ +#define MBED_NONCOPYABLE_H_ + +namespace mbed { + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \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 + * // base class representing a connection + * struct Connection { + * Connection(); + * virtual ~Connection(); + * virtual void open() = 0; + * } + * + * class SerialConnection : public Connection { + * public: + * SerialConnection(Serial*); + * + * private: + * Serial* _serial; + * }; + * + * Connection& get_connection() { + * static SerialConnection serial_connection; + * return serial_connection; + * } + * + * Connection connection = get_connection(); + * @endcode + * + * 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 defined as deleted: + * + * @code + * struct Connection { + * Connection(const Connection &) = delete; + * Connection &operator=(const Connection &) = delete; + * } + * @endcode + * + * Although manually defining deleted 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 + * } + * @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 classes is also a base type of the first nonstatic data member: + * + * @code + * struct A { }; + * struct B : A { + * int foo; + * }; + * // thanks to empty base optimization, sizeof(B) == sizeof(int) + * + * struct C : A { + * B b; + * }; + * + * // empty base optimization cannot be applied here because A from C and A from + * // 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 make it + * unique to the type it is applied to: + * + * @code + * template + * struct A { }; + * struct B : A { + * int foo; + * }; + * struct C : A { + * B b; + * }; + * + * // empty base optimization can be applied B and C does not refer to the same + * // kind of A. sizeof(C) == sizeof(B) == sizeof(int). + * @endcode + * + * @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. + */ + NonCopyable() = default; + /** + * Disallow destruction of NonCopyable objects from outside of its hierarchy. + */ + ~NonCopyable() = default; + +public: + /** + * Define copy constructor as deleted. Any attempt to copy construct + * a NonCopyable will fail at compile time. + */ + NonCopyable(const NonCopyable &) = delete; + + /** + * Define copy assignment operator as deleted. Any attempt to copy assign + * a NonCopyable will fail at compile time. + */ + NonCopyable &operator=(const NonCopyable &) = delete; +#endif +}; + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif /* MBED_NONCOPYABLE_H_ */ diff --git a/platform/include/platform/PlatformMutex.h b/platform/include/platform/PlatformMutex.h new file mode 100644 index 0000000..d2e94e5 --- /dev/null +++ b/platform/include/platform/PlatformMutex.h @@ -0,0 +1,92 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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 PLATFORM_MUTEX_H +#define PLATFORM_MUTEX_H + +#include "platform/NonCopyable.h" + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** \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_API_PRESENT + +// rtos::Mutex is itself a dummy class if the RTOS API is present, but not the RTOS +#include "rtos/Mutex.h" +typedef rtos::Mutex PlatformMutex; + +#else + +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() + { + } + + /** PlatformMutex destructor. + * + * @note When the RTOS is present, this is an alias for rtos::Mutex::~Mutex(). + */ + ~PlatformMutex() + { + } + + /** 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() + { + } + + /** 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() + { + } +}; + +#endif + +#endif + +/**@}*/ + +/**@}*/ diff --git a/platform/include/platform/ScopedLock.h b/platform/include/platform/ScopedLock.h new file mode 100644 index 0000000..b2e664d --- /dev/null +++ b/platform/include/platform/ScopedLock.h @@ -0,0 +1,89 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2019 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_SCOPEDLOCK_H +#define MBED_SCOPEDLOCK_H + +#include "platform/NonCopyable.h" + +namespace mbed { + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_ScopedLock ScopedLock functions + * @{ + */ + +/** RAII-style mechanism for owning a lock of Lockable object for the duration of a scoped block + * + * @tparam Lockable The type implementing BasicLockable concept + * + * @note For type Lockable to be BasicLockable, the following conditions have to be satisfied: + * - has public member function @a lock which blocks until a lock can be obtained for the current execution context + * - has public member function @a unlock which releases the lock + * + * Usage: + * + * Example with rtos::Mutex + * + * @code + * void foo(Mutex &m) { + * ScopedLock lock(m); + * // Mutex lock protects code in this block + * } + * @endcode + * + * + * More generic example + * + * @code + * template + * void foo(Lockable& lockable) { + * ScopedLock lock(lockable); + * // Code in this block runs under lock + * } + * @endcode + */ +template +class ScopedLock : private NonCopyable > { +public: + /** Locks given lockable object + * + * @param lockable reference to the instance of Lockable object + * @note lockable object should outlive the ScopedLock object + */ + ScopedLock(Lockable &lockable): _lockable(lockable) + { + _lockable.lock(); + } + + ~ScopedLock() + { + _lockable.unlock(); + } +private: + Lockable &_lockable; +}; + +/**@}*/ + +/**@}*/ + +} // embed + +#endif // MBED_SCOPEDLOCK_H diff --git a/platform/include/platform/ScopedRamExecutionLock.h b/platform/include/platform/ScopedRamExecutionLock.h new file mode 100644 index 0000000..0f7cadd --- /dev/null +++ b/platform/include/platform/ScopedRamExecutionLock.h @@ -0,0 +1,73 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2019 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_SCOPEDRAMEXECUTIONLOCK_H +#define MBED_SCOPEDRAMEXECUTIONLOCK_H + +#include "platform/mbed_mpu_mgmt.h" +#include "platform/NonCopyable.h" + +namespace mbed { + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** RAII object for disabling, then restoring RAM execute never mode + * Usage: + * @code + * + * void f() { + * // some code here + * { + * ScopedRamExecutionLock make_ram_executable; + * // Code in this block is allowed to call functions in RAM + * } + * // Execution from RAM is no longer allowed + * } + * @endcode + */ +class ScopedRamExecutionLock : private mbed::NonCopyable { +public: + + /** + * Allow execution from RAM + * + * Increment the execute never lock to ensure code can + * be executed from RAM. This class uses RAII to allow + * execution from ram while it is in scope. + */ + ScopedRamExecutionLock() + { + mbed_mpu_manager_lock_ram_execution(); + } + + /** + * Restore previous execution from RAM settings + * + * Decrement the execute never lock to return execute from RAM + * to its prior state. + */ + ~ScopedRamExecutionLock() + { + mbed_mpu_manager_unlock_ram_execution(); + } +}; + +/**@}*/ + +} + +#endif diff --git a/platform/include/platform/ScopedRomWriteLock.h b/platform/include/platform/ScopedRomWriteLock.h new file mode 100644 index 0000000..5ebdd12 --- /dev/null +++ b/platform/include/platform/ScopedRomWriteLock.h @@ -0,0 +1,73 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2019 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_SCOPEDROMWRITELOCK_H +#define MBED_SCOPEDROMWRITELOCK_H + +#include "platform/mbed_mpu_mgmt.h" +#include "platform/NonCopyable.h" + +namespace mbed { + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** RAII object for disabling, then restoring ROM write never mode + * Usage: + * @code + * + * void f() { + * // some code here + * { + * ScopedRomWriteLock make_ram_executable; + * // Code in this block is allowed to write to ROM + * } + * // Writing to ROM is no longer allowed + * } + * @endcode + */ +class ScopedRomWriteLock : private mbed::NonCopyable { +public: + + /** + * Allow writing to ROM + * + * Increment the ROM write lock to ensure code can + * write to ROM. This class uses RAII to allow + * writing to ROM while it is in scope. + */ + ScopedRomWriteLock() + { + mbed_mpu_manager_lock_rom_write(); + } + + /** + * Restore previous write to ROM settings + * + * Decrement the ROM write lock to return ROM write + * to its prior state. + */ + ~ScopedRomWriteLock() + { + mbed_mpu_manager_unlock_rom_write(); + } +}; + +/**@}*/ + +} + +#endif diff --git a/platform/include/platform/SharedPtr.h b/platform/include/platform/SharedPtr.h new file mode 100644 index 0000000..73a3b3c --- /dev/null +++ b/platform/include/platform/SharedPtr.h @@ -0,0 +1,340 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-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 __SHAREDPTR_H__ +#define __SHAREDPTR_H__ + +#include + +#include +#include + +#include "platform/mbed_atomic.h" + +namespace mbed { + +/** Shared pointer class. + * + * A shared pointer is a "smart" pointer that retains ownership of an object using + * reference counting across all smart pointers referencing that object. + * + * @code + * #include "platform/SharedPtr.h" + * + * void test() { + * struct MyStruct { int a; }; + * + * // Create shared pointer + * SharedPtr ptr( new MyStruct ); + * + * // Increase reference count + * SharedPtr ptr2( ptr ); + * + * ptr = nullptr; // Reference to the struct instance is still held by ptr2 + * + * ptr2 = nullptr; // The raw pointer is freed + * } + * @endcode + * + * + * It is similar to the std::shared_ptr class introduced in C++11; + * however, this is not a compatible implementation (no weak pointer, no make_shared, no custom deleters and so on.) + * + * Usage: SharedPtr ptr(new Class()) + * + * When ptr is passed around by value, the copy constructor and + * destructor manages the reference count of the raw pointer. + * If the counter reaches zero, delete is called on the raw pointer. + * + * To avoid loops, use "weak" references by calling the original + * pointer directly through ptr.get(). + */ + +template +class SharedPtr { +public: + /** + * @brief Create empty SharedPtr not pointing to anything. + * @details Used for variable declaration. + */ + constexpr SharedPtr(): _ptr(), _counter() + { + } + + /** + * @brief Create empty SharedPtr not pointing to anything. + */ + constexpr SharedPtr(std::nullptr_t) : SharedPtr() + { + } + + /** + * @brief Create new SharedPtr + * @param ptr Pointer to take control over + */ + SharedPtr(T *ptr): _ptr(ptr), _counter() + { + // Allocate counter on the heap, so it can be shared + if (_ptr != nullptr) { + _counter = new uint32_t(1); + } + } + + /** + * @brief Destructor. + * @details Decrement reference counter, and delete object if no longer pointed to. + */ + ~SharedPtr() + { + decrement_counter(); + } + + /** + * @brief Copy constructor. + * @details Create new SharedPtr from other SharedPtr by + * copying pointer to original object and pointer to counter. + * @param source Object being copied from. + */ + SharedPtr(const SharedPtr &source): _ptr(source._ptr), _counter(source._counter) + { + // Increment reference counter + if (_ptr != nullptr) { + core_util_atomic_incr_u32(_counter, 1); + } + } + + /** + * @brief Move constructor. + * @details Create new SharedPtr from other SharedPtr by + * moving pointer to original object and pointer to counter. + * @param source Object being copied from. + */ + SharedPtr(SharedPtr &&source): _ptr(source._ptr), _counter(source._counter) + { + source._ptr = nullptr; + source._counter = nullptr; + } + + /** + * @brief Copy assignment operator. + * @details Cleanup previous reference and assign new pointer and counter. + * @param source Object being assigned from. + * @return Object being assigned. + */ + SharedPtr operator=(const SharedPtr &source) + { + if (this != &source) { + // Clean up by decrementing counter + decrement_counter(); + + // Assign new values + _ptr = source.get(); + _counter = source.get_counter(); + + // Increment new counter + if (_ptr != nullptr) { + core_util_atomic_incr_u32(_counter, 1); + } + } + + return *this; + } + + /** + * @brief Move assignment operator. + * @details Cleanup previous reference and assign new pointer and counter. + * @param source Object being assigned from. + * @return Object being assigned. + */ + SharedPtr operator=(SharedPtr &&source) + { + if (this != &source) { + // Clean up by decrementing counter + decrement_counter(); + + // Assign new values + _ptr = source._ptr; + _counter = source._counter; + + source._ptr = nullptr; + source._counter = nullptr; + } + + return *this; + } + + /** + * @brief Replaces the managed pointer with a new unmanaged pointer. + * @param[in] ptr the new raw pointer to manage. + */ + void reset(T *ptr) + { + // Clean up by decrementing counter + decrement_counter(); + + _ptr = ptr; + if (ptr != nullptr) { + // Allocate counter on the heap, so it can be shared + _counter = new uint32_t(1); + } else { + _counter = nullptr; + } + } + + /** + * @brief Replace the managed pointer with a null pointer. + */ + void reset() + { + // Clean up by decrementing counter + decrement_counter(); + + _ptr = nullptr; + _counter = nullptr; + } + + /** + * @brief Raw pointer accessor. + * @details Get raw pointer to object pointed to. + * @return Pointer. + */ + T *get() const + { + return _ptr; + } + + /** + * @brief Reference count accessor. + * @return Reference count. + */ + uint32_t use_count() const + { + if (_ptr != nullptr) { + return core_util_atomic_load_u32(_counter); + } else { + return 0; + } + } + + /** + * @brief Dereference object operator. + * @details Override to return the object pointed to. + */ + T &operator*() const + { + return *_ptr; + } + + /** + * @brief Dereference object member operator. + * @details Override to return return member in object pointed to. + */ + T *operator->() const + { + return _ptr; + } + + /** + * @brief Boolean conversion operator. + * @return Whether or not the pointer is null. + */ + operator bool() const + { + return _ptr != nullptr; + } + +private: + /** + * @brief Get pointer to reference counter. + * @return Pointer to reference counter. + */ + uint32_t *get_counter() const + { + return _counter; + } + + /** + * @brief Decrement reference counter. + * @details If count reaches zero, free counter and delete object pointed to. + * Does not modify our own pointers - assumption is they will be overwritten + * or destroyed immediately afterwards. + */ + void decrement_counter() + { + if (_ptr != nullptr) { + if (core_util_atomic_decr_u32(_counter, 1) == 0) { + delete _counter; + delete _ptr; + } + } + } + +private: + // Pointer to shared object + T *_ptr; + + // Pointer to shared reference counter + uint32_t *_counter; +}; + +/** Non-member relational operators. + */ +template +bool operator== (const SharedPtr &lhs, const SharedPtr &rhs) +{ + return (lhs.get() == rhs.get()); +} + +template +bool operator== (const SharedPtr &lhs, U rhs) +{ + return (lhs.get() == (T *) rhs); +} + +template +bool operator== (U lhs, const SharedPtr &rhs) +{ + return ((T *) lhs == rhs.get()); +} + +/** Non-member relational operators. + */ +template +bool operator!= (const SharedPtr &lhs, const SharedPtr &rhs) +{ + return (lhs.get() != rhs.get()); +} + +template +bool operator!= (const SharedPtr &lhs, U rhs) +{ + return (lhs.get() != (T *) rhs); +} + +template +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/include/platform/SingletonPtr.h b/platform/include/platform/SingletonPtr.h new file mode 100644 index 0000000..2b873a2 --- /dev/null +++ b/platform/include/platform/SingletonPtr.h @@ -0,0 +1,211 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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 SINGLETONPTR_H +#define SINGLETONPTR_H + +#include +#include +#include +#include "platform/mbed_assert.h" +#include "platform/mbed_atomic.h" +#ifdef MBED_CONF_RTOS_PRESENT +#include "cmsis_os2.h" +#endif + +#ifdef MBED_CONF_RTOS_PRESENT +extern osMutexId_t singleton_mutex_id; +#endif + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_SingletonPtr SingletonPtr class + * @{ + */ + +/** Lock the singleton mutex + * + * This function is typically used to provide + * exclusive access when initializing a + * global object. + */ +inline static void singleton_lock(void) +{ +#ifdef MBED_CONF_RTOS_PRESENT + if (!singleton_mutex_id) { + // RTOS has not booted yet so no mutex is needed + return; + } + osMutexAcquire(singleton_mutex_id, osWaitForever); +#endif +} + +/** Unlock the singleton mutex + * + * This function is typically used to provide + * exclusive access when initializing a + * global object. + */ +inline static void singleton_unlock(void) +{ +#ifdef MBED_CONF_RTOS_PRESENT + if (!singleton_mutex_id) { + // RTOS has not booted yet so no mutex is needed + return; + } + osMutexRelease(singleton_mutex_id); +#endif +} + +/** Utility class for creating and using a singleton + * + * @note Synchronization level: Thread safe + * + * @note: This class is lazily initialized on first use. + * This class has a constexpr default constructor so if it is + * not used as a non-local variable it will be garbage collected. + * + * @note: This class would normally be used in a static standalone + * context. It does not call the destructor of the wrapped object + * when it is destroyed, effectively ensuring linker exclusion of the + * destructor for static objects. If used in another context, such as + * a member of a normal class wanting "initialize on first-use" + * semantics on a member, care should be taken to call the destroy + * method manually if necessary. + * + * @note: If used as a sub-object of a class, that class's own + * constructor must be constexpr to achieve its exclusion by + * the linker when unused. That will require explicit + * initialization of its other members. + * + * @note: More detail on initialization: Formerly, SingletonPtr + * had no constructor, so was "zero-initialized" when non-local. + * So if enclosed in another class with no constructor, the whole + * thing would be zero-initialized, and linker-excludable. + * Having no constructor meant SingletonPtr was not constexpr, + * which limited applicability in other contexts. With its new + * constexpr constructor, it is now "constant-initialized" when + * non-local. This achieves the same effect as a standalone + * non-local object, but as a sub-object linker exclusion is + * now only achieved if the outer object is itself using a + * constexpr constructor to get constant-initialization. + * Otherwise, the outer object will be neither zero-initialized + * nor constant-initialized, so will be "dynamic-initialized", + * and likely to be left in by the linker. + */ +template +struct SingletonPtr { + + // Initializers are required to make default constructor constexpr + // This adds no overhead as a static object - the compiler and linker can + // figure out that we are effectively zero-init, and either place us in + // ".bss", or exclude us if unused. + constexpr SingletonPtr() noexcept : _ptr(), _data() { } + + /** Get a pointer to the underlying singleton + * + * @returns + * A pointer to the singleton + */ + T *get() const + { + T *p = core_util_atomic_load(&_ptr); + if (p == NULL) { + singleton_lock(); + p = _ptr; + if (p == NULL) { + p = new (_data) T(); + core_util_atomic_store(&_ptr, p); + } + singleton_unlock(); + } + // _ptr was not zero initialized or was + // corrupted if this assert is hit + MBED_ASSERT(p == reinterpret_cast(&_data)); + return p; + } + + /** Get a pointer to the underlying singleton + * + * @returns + * A pointer to the singleton + */ + T *operator->() const + { + return get(); + } + + /** Get a reference to the underlying singleton + * + * @returns + * A reference to the singleton + */ + T &operator*() const + { + return *get(); + } + + /** Get a pointer to the underlying singleton + * + * Gets a pointer without initialization - can be + * used as an optimization when it is known that + * initialization must have already occurred. + * + * @returns + * A pointer to the singleton, or NULL if not + * initialized. + */ + T *get_no_init() const + { + return _ptr; + } + + /** Destroy the underlying singleton + * + * The underlying singleton is never automatically destroyed; + * this is a potential optimization to avoid destructors + * being pulled into an embedded image on the exit path, + * which should never occur. The destructor can be + * manually invoked via this call. + * + * Unlike construction, this is not thread-safe. After this call, + * no further operations on the object are permitted. + * + * Is a no-op if the object has not been constructed. + */ + void destroy() + { + if (_ptr) { + _ptr->~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/include/platform/Span.h b/platform/include/platform/Span.h new file mode 100644 index 0000000..450b7f5 --- /dev/null +++ b/platform/include/platform/Span.h @@ -0,0 +1,1127 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2019 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_PLATFORM_SPAN_H_ +#define MBED_PLATFORM_SPAN_H_ + +#include +#include +#include +#include + +#include "platform/mbed_assert.h" + +namespace mbed { + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \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 { + +// If From type is convertible to To type, then the compilation constant value is +// true; otherwise, it is false. +template +class is_convertible { + struct true_type { + char x[512]; + }; + struct false_type { }; + + static const From &generator(); + static true_type sink(const To &); + static false_type sink(...); + +public: + static const bool value = sizeof(true_type) == sizeof(sink(generator())); +}; + +} + +#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. + * + * Spans encapsulate a pointer to a sequence of contiguous elements and its size + * into a single object. Span can replace the traditional pair of pointer and + * size arguments passed as array definitions in function calls. + * + * @par Operations + * + * Span objects can be copied and assigned like regular value types with the help + * of the copy constructor or the copy assignment (=) operator. + * + * You can retrieve elements of the object with the subscript ([]) operator. You can access the + * pointer to the first element of the sequence viewed with data(). + * The function size() returns the number of elements in the sequence, and + * empty() informs whether there is any element in the sequence. + * + * You can slice Span from the beginning of the sequence (first()), from the end + * of the sequence (last()) or from an arbitrary point of the sequence (subspan()). + * + * @par Size encoding + * + * The size of the sequence can be encoded in the type itself or in the value of + * the instance with the help of the template parameter Extent: + * + * - Span: Span over a sequence of 6 elements. + * - Span: Span over an arbitrary long sequence. + * + * When the size is encoded in the type itself, it is guaranteed that the Span + * view is a valid sequence (not empty() and not NULL) - unless Extent equals 0. + * The type system also prevents automatic conversion from Span of different + * sizes. Finally, the Span object is internally represented as a single pointer. + * + * When the size of the sequence viewed is encoded in the Span value, Span + * instances can view an empty sequence. The function empty() helps client code + * decide whether Span is viewing valid content or not. + * + * @par Example + * + * - Encoding fixed size array: Array values in parameter decays automatically + * to pointer, which leaves room for subtitle bugs: + * + * @code + typedef uint8_t mac_address_t[6]; + void process_mac(mac_address_t); + + // compile just fine + uint8_t *invalid_value = NULL; + process_mac(invalid_value); + + + // correct way + typedef Span mac_address_t; + void process_mac(mac_address_t); + + // compilation error + uint8_t *invalid_value = NULL; + process_mac(invalid_value); + + // compilation ok + uint8_t valid_value[6]; + process_mac(valid_value); + * @endcode + * + * - Arbitrary buffer: When dealing with multiple buffers, it becomes painful to + * keep track of every buffer size and pointer. + * + * @code + const uint8_t options_tag[OPTIONS_TAG_SIZE]; + + struct parsed_value_t { + uint8_t *header; + uint8_t *options; + uint8_t *payload; + size_t payload_size; + } + + parsed_value_t parse(uint8_t *buffer, size_t buffer_size) + { + parsed_value_t parsed_value { 0 }; + + if (buffer != NULL && buffer_size <= MINIMAL_BUFFER_SIZE) { + return parsed_value; + } + + parsed_value.header = buffer; + parsed_value.header_size = BUFFER_HEADER_SIZE; + + if (memcmp(buffer + HEADER_OPTIONS_INDEX, options_tag, sizeof(options_tag)) == 0) { + options = buffer + BUFFER_HEADER_SIZE; + payload = buffer + BUFFER_HEADER_SIZE + OPTIONS_SIZE; + payload_size = buffer_size - BUFFER_HEADER_SIZE + OPTIONS_SIZE; + } else { + payload = buffer + BUFFER_HEADER_SIZE; + payload_size = buffer_size - BUFFER_HEADER_SIZE; + } + + return parsed_value; + } + + + //with Span + struct parsed_value_t { + Span header; + Span options; + Span payload; + } + + parsed_value_t parse(const Span &buffer) + { + parsed_value_t parsed_value; + + if (buffer.size() <= MINIMAL_BUFFER_SIZE) { + return parsed_value; + } + + parsed_value.header = buffer.first(BUFFER_HEADER_SIZE); + + if (buffer.subspan() == option_tag) { + options = buffer.supspan(parsed_value.header.size(), OPTIONS_SIZE); + } + + payload = buffer.subspan(parsed_value.header.size() + parsed_value.options.size()); + + return parsed_value; + } + * @endcode + * + * @note You can create Span instances with the help of the function template + * make_Span() and make_const_Span(). + * + * @note Span objects can be implicitly converted to Span objects + * where required. + * + * @tparam ElementType type of objects the Span views. + * + * @tparam Extent The size of the contiguous sequence viewed. The default value + * SPAN_DYNAMIC_SIZE is special because it allows construction of Span objects of + * any size (set at runtime). + */ +template +struct Span { + + /** + * Type of the element contained + */ + typedef ElementType element_type; + + /** + * Type of the index. + */ + typedef ptrdiff_t index_type; + + /** + * Pointer to an ElementType + */ + typedef element_type *pointer; + + /** + * Reference to an ElementType + */ + typedef element_type &reference; + + /** + * Iterator to an ElementType + */ + typedef pointer iterator; + + /** + * Reverse iterator to an ElementType + */ + typedef std::reverse_iterator reverse_iterator; + + /** + * Size of the Extent; -1 if dynamic. + */ + static const index_type extent = Extent; + + MBED_STATIC_ASSERT(Extent >= 0, "Invalid extent for a Span"); + + /** + * Construct an empty Span. + * + * @post a call to size() returns 0, and data() returns NULL. + * + * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or + * Extent != 0 . + */ + Span() : + _data(NULL) + { + MBED_STATIC_ASSERT( + Extent == 0, + "Cannot default construct a static-extent Span (unless Extent is 0)" + ); + } + + /** + * Construct a Span from a pointer to a buffer and its size. + * + * @param ptr Pointer to the beginning of the data viewed. + * + * @param count Number of elements viewed. + * + * @pre [ptr, ptr + count) must be be a valid range. + * @pre count must be equal to Extent. + * + * @post a call to size() returns Extent, and data() returns @p ptr. + */ + Span(pointer ptr, index_type count) : + _data(ptr) + { + MBED_ASSERT(count == Extent); + MBED_ASSERT(Extent == 0 || ptr != NULL); + } + + /** + * Construct a Span from the range [first, last). + * + * @param first Pointer to the beginning of the data viewed. + * @param last End of the range (element after the last element). + * + * @pre [first, last) must be be a valid range. + * @pre first <= last. + * @pre last - first must be equal to Extent. + * + * @post a call to size() returns Extent, and data() returns @p first. + */ + Span(pointer first, pointer last) : + _data(first) + { + MBED_ASSERT(first <= last); + MBED_ASSERT((last - first) == Extent); + MBED_ASSERT(Extent == 0 || first != NULL); + } + + // AStyle ignore, not handling correctly below + // *INDENT-OFF* + /** + * Construct a Span from the reference to an array. + * + * @param elements Reference to the array viewed. + * + * @post a call to size() returns Extent, and data() returns a + * pointer to elements. + */ + Span(element_type (&elements)[Extent]): + _data(elements) { } + + /** + * Construct a Span object from another Span of the same size. + * + * @param other The Span object used to construct this. + * + * @note For Span with a positive extent, this function is not accessible. + * + * @note OtherElementType(*)[] must be convertible to ElementType(*)[]. + */ + template + Span(const Span &other): + _data(other.data()) + { + MBED_STATIC_ASSERT( + (span_detail::is_convertible::value), + "OtherElementType(*)[] should be convertible to ElementType (*)[]" + ); + } + // *INDENT-ON* + + /** + * Return the size of the sequence viewed. + * + * @return The size of the sequence viewed. + */ + index_type size() const + { + return Extent; + } + + /** + * Return if the sequence is empty or not. + * + * @return true if the sequence is empty and false otherwise. + */ + bool empty() const + { + return size() == 0; + } + + /** + * Return an iterator to the first element of the sequence. + * + * @return An iterator to the first element of the sequence. + */ + iterator begin() const + { + return _data; + } + + /** + * Return an iterator to the element following the last element of the sequence. + * + * @return An iterator to the element following the last element of the sequence. + */ + iterator end() const + { + return _data + Extent; + } + + /** + * Return a reverse_iterator to the first element of the reversed sequence. + * + * @return A reverse_iterator to the first element of the reversed sequence. + */ + reverse_iterator rbegin() const + { + return reverse_iterator(end()); + } + + /** + * Return a reverse_iterator to the element following the last element of the reversed sequence. + * + * @return A reverse_iterator to the element following the last element of the reversed sequence. + */ + reverse_iterator rend() const + { + return reverse_iterator(begin()); + } + + /** + * Returns a reference to the element at position @p index. + * + * @param index Index of the element to access. + * + * @return A reference to the element at the index specified in input. + * + * @pre 0 <= index < Extent. + */ + reference operator[](index_type index) const + { +#ifdef MBED_DEBUG + MBED_ASSERT(0 <= index && index < Extent); +#endif + return _data[index]; + } + + /** + * Return a pointer to the first element of the sequence or NULL if the Span + * is empty(). + * + * @return The pointer to the first element of the Span. + */ + pointer data() const + { + return _data; + } + + /** + * Create a new Span over the first @p Count elements of the existing view. + * + * @tparam Count The number of element viewed by the new Span + * + * @return A new Span over the first @p Count elements. + * + * @pre Count >= 0 && Count <= size(). + */ + template + Span first() const + { + MBED_STATIC_ASSERT( + (0 <= Count) && (Count <= Extent), + "Invalid subspan extent" + ); + return Span(_data, Count); + } + + /** + * Create a new Span over the last @p Count elements of the existing view. + * + * @tparam Count The number of element viewed by the new Span. + * + * @return A new Span over the last @p Count elements. + * + * @pre Count >= 0 && Count <= size(). + */ + template + Span last() const + { + MBED_STATIC_ASSERT( + (0 <= Count) && (Count <= Extent), + "Invalid subspan extent" + ); + return Span(_data + (Extent - Count), Count); + } + + // AStyle ignore, not handling correctly below + // *INDENT-OFF* + /** + * Create a subspan that is a view of other Count elements; the view starts at + * element Offset. + * + * @tparam Offset The offset of the first element viewed by the subspan. + * + * @tparam Count The number of elements present in the subspan. If Count + * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and + * containing the rest of the elements is returned. + * + * @return A subspan of this starting at Offset and Count long. + */ + template + Span + subspan() const + { + MBED_STATIC_ASSERT( + 0 <= Offset && Offset <= Extent, + "Invalid subspan offset" + ); + MBED_STATIC_ASSERT( + (Count == SPAN_DYNAMIC_EXTENT) || + (0 <= Count && (Count + Offset) <= Extent), + "Invalid subspan count" + ); + return Span( + _data + Offset, + Count == SPAN_DYNAMIC_EXTENT ? Extent - Offset : Count + ); + } + // *INDENT-ON* + + /** + * Create a new Span over the first @p count elements of the existing view. + * + * @param count The number of element viewed by the new Span. + * + * @return A new Span over the first @p count elements. + */ + Span first(index_type count) const + { + MBED_ASSERT(0 <= count && count <= Extent); + return Span(_data, count); + } + + /** + * Create a new Span over the last @p count elements of the existing view. + * + * @param count The number of elements viewed by the new Span. + * + * @return A new Span over the last @p count elements. + */ + Span last(index_type count) const + { + MBED_ASSERT(0 <= count && count <= Extent); + return Span( + _data + (Extent - count), + count + ); + } + + /** + * Create a subspan that is a view of other count elements; the view starts at + * element offset. + * + * @param offset The offset of the first element viewed by the subspan. + * + * @param count The number of elements present in the subspan. If Count + * is equal to SPAN_DYNAMIC_EXTENT, then a span starting at offset and + * containing the rest of the elements is returned. + * + * @return + */ + Span subspan( + index_type offset, index_type count = SPAN_DYNAMIC_EXTENT + ) const + { + MBED_ASSERT(0 <= offset && offset <= Extent); + MBED_ASSERT( + (count == SPAN_DYNAMIC_EXTENT) || + (0 <= count && (count + offset) <= Extent) + ); + return Span( + _data + offset, + count == SPAN_DYNAMIC_EXTENT ? Extent - offset : count + ); + } + +private: + pointer _data; +}; + +/** + * Span specialization that handle dynamic size. + */ +template +struct Span { + /** + * Type of the element contained. + */ + typedef ElementType element_type; + + /** + * Type of the index. + */ + typedef ptrdiff_t index_type; + + /** + * Pointer to an ElementType. + */ + typedef element_type *pointer; + + /** + * Reference to an ElementType. + */ + typedef element_type &reference; + + /** + * Iterator to an ElementType + */ + typedef pointer iterator; + + /** + * Reverse iterator to an ElementType + */ + typedef std::reverse_iterator reverse_iterator; + + /** + * Size of the Extent; -1 if dynamic. + */ + static const index_type extent = SPAN_DYNAMIC_EXTENT; + + /** + * Construct an empty Span. + * + * @post a call to size() returns 0, and data() returns NULL. + * + * @note This function is not accessible if Extent != SPAN_DYNAMIC_EXTENT or + * Extent != 0 . + */ + Span() : + _data(NULL), _size(0) { } + + /** + * Construct a Span from a pointer to a buffer and its size. + * + * @param ptr Pointer to the beginning of the data viewed. + * + * @param count Number of elements viewed. + * + * @pre [ptr, ptr + count) must be be a valid range. + * @pre count must be equal to extent. + * + * @post a call to size() returns count, and data() returns @p ptr. + */ + Span(pointer ptr, index_type count) : + _data(ptr), _size(count) + { + MBED_ASSERT(count >= 0); + MBED_ASSERT(ptr != NULL || count == 0); + } + + /** + * Construct a Span from the range [first, last). + * + * @param first Pointer to the beginning of the data viewed. + * @param last End of the range (element after the last element). + * + * @pre [first, last) must be be a valid range. + * @pre first <= last. + * + * @post a call to size() returns the result of (last - first), and + * data() returns @p first. + */ + Span(pointer first, pointer last) : + _data(first), _size(last - first) + { + MBED_ASSERT(first <= last); + MBED_ASSERT(first != NULL || (last - first) == 0); + } + + // AStyle ignore, not handling correctly below + // *INDENT-OFF* + /** + * Construct a Span from the reference to an array. + * + * @param elements Reference to the array viewed. + * + * @tparam Count Number of elements of T presents in the array. + * + * @post a call to size() returns Count, and data() returns a + * pointer to elements. + */ + template + Span(element_type (&elements)[Count]): + _data(elements), _size(Count) { } + + /** + * Construct a Span object from another Span. + * + * @param other The Span object used to construct this. + * + * @note For Span with a positive extent, this function is not accessible. + * + * @note OtherElementType(*)[] must be convertible to ElementType(*)[]. + */ + template + Span(const Span &other): + _data(other.data()), _size(other.size()) + { + MBED_STATIC_ASSERT( + (span_detail::is_convertible::value), + "OtherElementType(*)[] should be convertible to ElementType (*)[]" + ); + } + // *INDENT-ON* + + /** + * Return the size of the array viewed. + * + * @return The number of elements present in the array viewed. + */ + index_type size() const + { + return _size; + } + + /** + * Return if the sequence viewed is empty or not. + * + * @return true if the sequence is empty and false otherwise. + */ + bool empty() const + { + return size() == 0; + } + + /** + * Return an iterator to the first element of the sequence. + * + * @return An iterator to the first element of the sequence. + */ + iterator begin() const + { + return _data; + } + + /** + * Return an iterator to the element following the last element of the sequence. + * + * @return An iterator to the element following the last element of the sequence. + */ + iterator end() const + { + return _data + _size; + } + + /** + * Return a reverse_iterator to the first element of the reversed sequence. + * + * @return A reverse_iterator to the first element of the reversed sequence. + */ + reverse_iterator rbegin() const + { + return reverse_iterator(end()); + } + + /** + * Return a reverse_iterator to the element following the last element of the reversed sequence. + * + * @return A reverse_iterator to the element following the last element of the reversed sequence. + */ + reverse_iterator rend() const + { + return reverse_iterator(begin()); + } + + /** + * Access to an element of the sequence. + * + * @param index Element index to access. + * + * @return A reference to the element at the index specified in input. + * + * @pre index is less than size(). + */ + reference operator[](index_type index) const + { +#ifdef MBED_DEBUG + MBED_ASSERT(0 <= index && index < _size); +#endif + return _data[index]; + } + + /** + * Get the raw pointer to the sequence viewed. + * + * @return The raw pointer to the first element viewed. + */ + pointer data() const + { + return _data; + } + + /** + * Create a new Span over the first @p Count elements of the existing view. + * + * @tparam Count The number of elements viewed by the new Span. + * + * @return A new Span over the first @p Count elements. + * + * @pre Count >= 0 && Count <= size(). + */ + template + Span first() const + { + MBED_ASSERT((Count >= 0) && (Count <= _size)); + return Span(_data, Count); + } + + /** + * Create a new Span over the last @p Count elements of the existing view. + * + * @tparam Count The number of elements viewed by the new Span. + * + * @return A new Span over the last @p Count elements. + * + * @pre Count >= 0 && Count <= size(). + */ + template + Span last() const + { + MBED_ASSERT((0 <= Count) && (Count <= _size)); + return Span(_data + (_size - Count), Count); + } + + /** + * Create a subspan that is a view other Count elements; the view starts at + * element Offset. + * + * @tparam Offset The offset of the first element viewed by the subspan. + * + * @tparam Count The number of elements present in the subspan. If Count + * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and + * containing the rest of the elements is returned. + * + * @return A subspan of this starting at Offset and Count long. + */ + template + Span + subspan() const + { + MBED_ASSERT(0 <= Offset && Offset <= _size); + MBED_ASSERT( + (Count == SPAN_DYNAMIC_EXTENT) || + (0 <= Count && (Count + Offset) <= _size) + ); + return Span( + _data + Offset, + Count == SPAN_DYNAMIC_EXTENT ? _size - Offset : Count + ); + } + + /** + * Create a new Span over the first @p count elements of the existing view. + * + * @param count The number of elements viewed by the new Span. + * + * @return A new Span over the first @p count elements. + */ + Span first(index_type count) const + { + MBED_ASSERT(0 <= count && count <= _size); + return Span(_data, count); + } + + /** + * Create a new Span over the last @p count elements of the existing view. + * + * @param count The number of elements viewed by the new Span. + * + * @return A new Span over the last @p count elements. + */ + Span last(index_type count) const + { + MBED_ASSERT(0 <= count && count <= _size); + return Span( + _data + (_size - count), + count + ); + } + + /** + * Create a subspan that is a view of other count elements; the view starts at + * element offset. + * + * @param offset The offset of the first element viewed by the subspan. + * + * @param count The number of elements present in the subspan. If Count + * is equal to SPAN_DYNAMIC_EXTENT, then a Span starting at offset and + * containing the rest of the elements is returned. + * + * @return A subspan of this starting at offset and count long. + */ + Span subspan( + index_type offset, index_type count = SPAN_DYNAMIC_EXTENT + ) const + { + MBED_ASSERT(0 <= offset && offset <= _size); + MBED_ASSERT( + (count == SPAN_DYNAMIC_EXTENT) || + (0 <= count && (count + offset) <= _size) + ); + return Span( + _data + offset, + count == SPAN_DYNAMIC_EXTENT ? _size - offset : count + ); + } + +private: + pointer _data; + index_type _size; +}; + +/** + * Equality operator between two Span objects. + * + * @param lhs Left side of the binary operation. + * @param rhs Right side of the binary operation. + * + * @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) +{ + if (lhs.size() != rhs.size()) { + return false; + } + + if (lhs.data() == rhs.data()) { + return true; + } + + return std::equal(lhs.data(), lhs.data() + lhs.size(), rhs.data()); +} + +// AStyle ignore, not handling correctly below +// *INDENT-OFF* +/** + * Equality operation between a Span and a reference to a C++ array. + * + * @param lhs Left side of the binary operation. + * @param rhs Right side of the binary operation. + * + * @return True if elements in input have the same size and the same content and + * false otherwise. + */ +template +bool operator==(const Span &lhs, T (&rhs)[RhsExtent]) +{ + return lhs == Span(rhs); +} + +/** + * Equality operation between a Span and a reference to a C++ array. + * + * @param lhs Left side of the binary operation. + * @param rhs Right side of the binary operation. + * + * @return True if elements in input have the same size and the same content + * and false otherwise. + */ +template +bool operator==(T (&lhs)[LhsExtent], const Span &rhs) +{ + return Span(lhs) == rhs; +} + +/** + * Not equal operator + * + * @param lhs Left side of the binary operation. + * @param rhs Right side of the binary operation. + * + * @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) +{ + return !(lhs == rhs); +} + +/** + * Not Equal operation between a Span and a reference to a C++ array. + * + * @param lhs Left side of the binary operation. + * @param rhs Right side of the binary operation. + * + * @return True if elements in input have the same size and the same content + * and false otherwise. + */ +template +bool operator!=(const Span &lhs, T (&rhs)[RhsExtent]) +{ + return !(lhs == Span(rhs)); +} + +/** + * Not Equal operation between a Span and a reference to a C++ array. + * + * @param lhs Left side of the binary operation. + * @param rhs Right side of the binary operation. + * + * @return True if elements in input have the same size and the same content + * and false otherwise. + */ +template +bool operator!=(T (&lhs)[LhsExtent], const Span &rhs) +{ + return !(Span(lhs) == rhs); +} + +/** + * Generate a Span from a reference to a C/C++ array. + * + * @tparam T Type of elements held in elements. + * @tparam Extent Number of items held in elements. + * + * @param elements The reference to the array viewed. + * + * @return The Span to elements. + * + * @note This helper avoids the typing of template parameter when Span is + * created 'inline'. + * + * @relates Span + */ +template +Span make_Span(T (&elements)[Size]) +{ + return Span(elements); +} + +/** + * Generate a Span from a pointer to a C/C++ array. + * + * @tparam Extent Number of items held in elements. + * @tparam T Type of elements held in elements. + * + * @param elements The reference to the array viewed. + * + * @return The Span to elements. + * + * @note This helper avoids the typing of template parameter when Span is + * created 'inline'. + */ +template +Span make_Span(T *elements) +{ + return Span(elements, Extent); +} + +/** + * Generate a Span from a C/C++ pointer and the size of the array. + * + * @tparam T Type of elements held in array_ptr. + * + * @param array_ptr The pointer to the array viewed. + * @param array_size The number of T elements in the array. + * + * @return The Span to array_ptr with a size of array_size. + * + * @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) +{ + return Span(array_ptr, array_size); +} + +/** + * Generate a Span to a const content from a reference to a C/C++ array. + * + * @tparam T Type of elements held in elements. + * @tparam Extent Number of items held in elements. + * + * @param elements The array viewed. + * @return The Span to elements. + * + * @note This helper avoids the typing of template parameter when Span is + * created 'inline'. + */ +template +Span make_const_Span(const T (&elements)[Extent]) +{ + return Span(elements); +} +// *INDENT-ON* +/** + * Generate a Span to a const content from a pointer to a C/C++ array. + * + * @tparam Extent Number of items held in elements. + * @tparam T Type of elements held in elements. + * + * @param elements The reference to the array viewed. + * + * @return The Span to elements. + * + * @note This helper avoids the typing of template parameter when Span is + * created 'inline'. + * + * @relates Span + */ +template +Span make_const_Span(const T *elements) +{ + return Span(elements, Extent); +} + +/** + * Generate a Span to a const content from a C/C++ pointer and the size of the + * array. + * + * @tparam T Type of elements held in array_ptr. + * + * @param array_ptr The pointer to the array to viewed. + * @param array_size The number of T elements in the array. + * + * @return The Span to array_ptr with a size of array_size. + * + * @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) +{ + return Span(array_ptr, array_size); +} + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif /* MBED_PLATFORM_SPAN_H_ */ diff --git a/platform/include/platform/Stream.h b/platform/include/platform/Stream.h new file mode 100644 index 0000000..03bc7dc --- /dev/null +++ b/platform/include/platform/Stream.h @@ -0,0 +1,102 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_STREAM_H +#define MBED_STREAM_H + +#include "platform/platform.h" +#include "platform/FileLike.h" +#include "platform/NonCopyable.h" +#include "platform/mbed_toolchain.h" +#include +#include + +namespace mbed { +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_Stream Stream class + * @{ + */ + +extern void mbed_set_unbuffered_stream(std::FILE *_file); + +/** File stream + * + * @note Synchronization level: Set by subclass + */ +class Stream : public FileLike, private NonCopyable { + +public: + Stream(const char *name = NULL); + virtual ~Stream(); + +#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY + int putc(int c); + int puts(const char *s); + int getc(); + char *gets(char *s, int size); + 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 *() + { + return _file; + } + +#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY + virtual int close(); + virtual ssize_t write(const void *buffer, size_t length); + virtual ssize_t read(void *buffer, size_t length); + virtual off_t seek(off_t offset, int whence); + virtual off_t tell(); + virtual void rewind(); + virtual int isatty(); + virtual int sync(); + virtual off_t size(); + +protected: + virtual int _putc(int c) = 0; + virtual int _getc() = 0; + +#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY + std::FILE *_file; +#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY + + /** Acquire exclusive access to this object. + */ + virtual void lock() + { + // Stub + } + + /** Release exclusive access to this object. + */ + virtual void unlock() + { + // Stub + } +}; +/**@}*/ + +/**@}*/ +} // namespace mbed + +#endif + diff --git a/platform/include/platform/Transaction.h b/platform/include/platform/Transaction.h new file mode 100644 index 0000000..1d8d4cd --- /dev/null +++ b/platform/include/platform/Transaction.h @@ -0,0 +1,89 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015-2019 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_TRANSACTION_H +#define MBED_TRANSACTION_H + +#include "platform/platform.h" + +namespace mbed { +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_Transaction Transaction class + * @{ + */ + +/** Transaction structure + */ +typedef struct { + void *tx_buffer; /**< Tx buffer */ + size_t tx_length; /**< Length of Tx buffer*/ + void *rx_buffer; /**< Rx buffer */ + size_t rx_length; /**< Length of Rx buffer */ + uint32_t event; /**< Event for a transaction */ + event_callback_t callback; /**< User's callback */ + uint8_t width; /**< Buffer's word width (8, 16, 32, 64) */ +} transaction_t; + +/** Transaction class defines a transaction. + * + * @note Synchronization level: Not protected + */ +template +class Transaction { +public: + Transaction(Class *tpointer, const transaction_t &transaction) : _obj(tpointer), _data(transaction) + { + } + + Transaction() : _obj(), _data() + { + } + + ~Transaction() + { + } + + /** Get object's instance for the transaction + * + * @return The object which was stored + */ + Class *get_object() + { + return _obj; + } + + /** Get the transaction + * + * @return The transaction which was stored + */ + transaction_t *get_transaction() + { + return &_data; + } + +private: + Class *_obj; + transaction_t _data; +}; +/**@}*/ + +/**@}*/ +} + +#endif diff --git a/platform/include/platform/internal/CThunkBase.h b/platform/include/platform/internal/CThunkBase.h new file mode 100644 index 0000000..212ff44 --- /dev/null +++ b/platform/include/platform/internal/CThunkBase.h @@ -0,0 +1,88 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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 __CTHUNK_BASE_H__ +#define __CTHUNK_BASE_H__ + +/** \defgroup platform-internal-api Platform + * \ingroup mbed-os-internal + */ + +/* IRQ/Exception compatible thunk entry function */ +typedef void (*CThunkEntry)(void); + +/** + * \defgroup platform_CThunkBase CThunkBase class + * \ingroup platform-internal-api + * @{ + */ +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/include/platform/internal/mbed_atomic_impl.h b/platform/include/platform/internal/mbed_atomic_impl.h new file mode 100644 index 0000000..b29a0ae --- /dev/null +++ b/platform/include/platform/internal/mbed_atomic_impl.h @@ -0,0 +1,1358 @@ +/* + * Copyright (c) 2015-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 + * + * 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_ATOMIC_IMPL_H__ +#define __MBED_ATOMIC_IMPL_H__ + +#ifndef __MBED_UTIL_ATOMIC_H__ +#error "mbed_atomic_impl.h is designed to be included only by mbed_atomic.h" +#endif + +#include +#include "cmsis.h" +#include "platform/mbed_assert.h" +#include "platform/mbed_toolchain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef MBED_DEBUG +/* Plain loads must not have "release" or "acquire+release" order */ +#define MBED_CHECK_LOAD_ORDER(order) MBED_ASSERT((order) != mbed_memory_order_release && (order) != mbed_memory_order_acq_rel) + +/* Plain stores must not have "consume", "acquire" or "acquire+release" order */ +#define MBED_CHECK_STORE_ORDER(order) MBED_ASSERT((order) != mbed_memory_order_consume && (order) != mbed_memory_order_acquire && (order) != mbed_memory_order_acq_rel) + +/* Compare exchange needs failure order no stronger than success, and failure can't be "release" or "acquire+release" */ +#define MBED_CHECK_CAS_ORDER(success, failure) \ + MBED_ASSERT((failure) <= (success) && (failure) != mbed_memory_order_release && (failure) != mbed_memory_order_acq_rel) +#else +#define MBED_CHECK_LOAD_ORDER(order) (void)0 +#define MBED_CHECK_STORE_ORDER(order) (void)0 +#define MBED_CHECK_CAS_ORDER(success, failure) (void)0 +#endif + +/* This is currently just to silence unit tests, so no better test required */ +#ifdef __MBED__ +#define MBED_ATOMIC_PTR_SIZE 32 +#else +#define MBED_ATOMIC_PTR_SIZE 64 +#endif + +/* Place barrier after a load or read-modify-write if a consume or acquire operation */ +#define MBED_ACQUIRE_BARRIER(order) do { \ + if ((order) & (mbed_memory_order_consume|mbed_memory_order_acquire)) { \ + MBED_BARRIER(); \ + } } while (0) + +/* Place barrier before a store or read-modify-write if a release operation */ +#define MBED_RELEASE_BARRIER(order) do { \ + if ((order) & mbed_memory_order_release) { \ + MBED_BARRIER(); \ + } } while (0) + +/* Place barrier after a plain store if a sequentially consistent */ +#define MBED_SEQ_CST_BARRIER(order) do { \ + if ((order) == mbed_memory_order_seq_cst) { \ + MBED_BARRIER(); \ + } } while (0) + + + +#if MBED_EXCLUSIVE_ACCESS + +/* This header file provides C inline definitions for atomic functions. */ +/* For C99 inline semantic compatibility, mbed_atomic_impl.c has out-of-line definitions. */ + +/****************************** ASSEMBLER **********************************/ + +// Fiddle about with constraints. These work for GCC and clang, but +// IAR appears to be restricted to having only a single constraint, +// so we can't do immediates. +#if MBED_EXCLUSIVE_ACCESS_THUMB1 +#define MBED_DOP_REG "l" // Need low register to get 16-bit 3-op ADD/SUB +#define MBED_CMP_IMM "I" // CMP 8-bit immediate +#define MBED_SUB3_IMM "L" // -7 to +7 +#else +#define MBED_DOP_REG "r" // Can use 32-bit 3-op ADD/SUB, so any registers +#define MBED_CMP_IMM "IL" // CMP or CMN, 12-bit immediate +#define MBED_SUB3_IMM "IL" // SUB or ADD, 12-bit immediate +#endif + +#if defined __clang__ || defined __GNUC__ +#define DO_MBED_LOCKFREE_EXCHG_ASM(M) \ + __asm volatile ( \ + ".syntax unified\n\t" \ + "LDREX"#M "\t%[oldValue], %[value]\n\t" \ + "STREX"#M "\t%[fail], %[newValue], %[value]\n\t" \ + : [oldValue] "=&r" (oldValue), \ + [fail] "=&r" (fail), \ + [value] "+Q" (*valuePtr) \ + : [newValue] "r" (newValue) \ + : \ + ) +#elif defined __ICCARM__ +/* In IAR "r" means low register if Thumbv1 (there's no way to specify any register...) */ +#define DO_MBED_LOCKFREE_EXCHG_ASM(M) \ + asm volatile ( \ + "LDREX"#M "\t%[oldValue], [%[valuePtr]]\n" \ + "STREX"#M "\t%[fail], %[newValue], [%[valuePtr]]\n" \ + : [oldValue] "=&r" (oldValue), \ + [fail] "=&r" (fail) \ + : [valuePtr] "r" (valuePtr), \ + [newValue] "r" (newValue) \ + : "memory" \ + ) +#endif + +#if defined __clang__ || defined __GNUC__ +#define DO_MBED_LOCKFREE_NEWVAL_2OP_ASM(OP, Constants, M) \ + __asm volatile ( \ + ".syntax unified\n\t" \ + "LDREX"#M "\t%[newValue], %[value]\n\t" \ + #OP "\t%[newValue], %[arg]\n\t" \ + "STREX"#M "\t%[fail], %[newValue], %[value]\n\t" \ + : [newValue] "=&" MBED_DOP_REG (newValue), \ + [fail] "=&r" (fail), \ + [value] "+Q" (*valuePtr) \ + : [arg] Constants MBED_DOP_REG (arg) \ + : "cc" \ + ) +#elif defined __ICCARM__ +/* In IAR "r" means low register if Thumbv1 (there's no way to specify any register...) */ +/* IAR does not support "ADDS reg, reg", so write as 3-operand */ +#define DO_MBED_LOCKFREE_NEWVAL_2OP_ASM(OP, Constants, M) \ + asm volatile ( \ + "LDREX"#M "\t%[newValue], [%[valuePtr]]\n" \ + #OP "\t%[newValue], %[newValue], %[arg]\n" \ + "STREX"#M "\t%[fail], %[newValue], [%[valuePtr]]\n" \ + : [newValue] "=&r" (newValue), \ + [fail] "=&r" (fail) \ + : [valuePtr] "r" (valuePtr), \ + [arg] "r" (arg) \ + : "memory", "cc" \ + ) +#endif + +#if defined __clang__ || defined __GNUC__ +#define DO_MBED_LOCKFREE_OLDVAL_3OP_ASM(OP, Constants, M) \ + __asm volatile ( \ + ".syntax unified\n\t" \ + "LDREX"#M "\t%[oldValue], %[value]\n\t" \ + #OP "\t%[newValue], %[oldValue], %[arg]\n\t" \ + "STREX"#M "\t%[fail], %[newValue], %[value]\n\t" \ + : [oldValue] "=&" MBED_DOP_REG (oldValue), \ + [newValue] "=&" MBED_DOP_REG (newValue), \ + [fail] "=&r" (fail), \ + [value] "+Q" (*valuePtr) \ + : [arg] Constants MBED_DOP_REG (arg) \ + : "cc" \ + ) +#elif defined __ICCARM__ +/* In IAR "r" means low register if Thumbv1 (there's no way to specify any register...) */ +#define DO_MBED_LOCKFREE_OLDVAL_3OP_ASM(OP, Constants, M) \ + asm volatile ( \ + "LDREX"#M "\t%[oldValue], [%[valuePtr]]\n" \ + #OP "\t%[newValue], %[oldValue], %[arg]\n" \ + "STREX"#M "\t%[fail], %[newValue], [%[valuePtr]]\n" \ + : [oldValue] "=&r" (oldValue), \ + [newValue] "=&r" (newValue), \ + [fail] "=&r" (fail) \ + : [valuePtr] "r" (valuePtr), \ + [arg] "r" (arg) \ + : "memory", "cc" \ + ) +#endif + +/* Bitwise operations are harder to do in ARMv8-M baseline - there + * are only 2-operand versions of the instructions. + */ +#if defined __clang__ || defined __GNUC__ +#define DO_MBED_LOCKFREE_OLDVAL_2OP_ASM(OP, Constants, M) \ + __asm volatile ( \ + ".syntax unified\n\t" \ + "LDREX"#M "\t%[oldValue], %[value]\n\t" \ + "MOV" "\t%[newValue], %[oldValue]\n\t" \ + #OP "\t%[newValue], %[arg]\n\t" \ + "STREX"#M "\t%[fail], %[newValue], %[value]\n\t" \ + : [oldValue] "=&r" (oldValue), \ + [newValue] "=&l" (newValue), \ + [fail] "=&r" (fail), \ + [value] "+Q" (*valuePtr) \ + : [arg] Constants "l" (arg) \ + : "cc" \ + ) +#elif defined __ICCARM__ +#define DO_MBED_LOCKFREE_OLDVAL_2OP_ASM(OP, Constants, M) \ + asm volatile ( \ + "LDREX"#M "\t%[oldValue], [%[valuePtr]]\n" \ + "MOV" "\t%[newValue], %[oldValue]\n" \ + #OP "\t%[newValue], %[arg]\n" \ + "STREX"#M "\t%[fail], %[newValue], [%[valuePtr]]\n" \ + : [oldValue] "=&r" (oldValue), \ + [newValue] "=&r" (newValue), \ + [fail] "=&r" (fail) \ + : [valuePtr] "r" (valuePtr), \ + [arg] "r" (arg) \ + : "memory", "cc" \ + ) +#endif + +/* Note that we split ARM and Thumb implementations for CAS, as + * the key distinction is the handling of conditions. Thumb-2 IT is + * partially deprecated, so avoid it, making Thumb-1 and Thumb-2 + * implementations the same. + */ +#if MBED_EXCLUSIVE_ACCESS_ARM +#if defined __clang__ || defined __GNUC__ +#define DO_MBED_LOCKFREE_CAS_WEAK_ASM(M) \ + __asm volatile ( \ + ".syntax unified\n\t" \ + "LDREX"#M "\t%[oldValue], %[value]\n\t" \ + "SUBS" "\t%[fail], %[oldValue], %[expectedValue]\n\t"\ + "STREX"#M"EQ\t%[fail], %[desiredValue], %[value]\n\t" \ + : [oldValue] "=&r" (oldValue), \ + [fail] "=&r" (fail), \ + [value] "+Q" (*ptr) \ + : [desiredValue] "r" (desiredValue), \ + [expectedValue] "ILr" (expectedValue) \ + : "cc" \ + ) +#elif defined __ICCARM__ +#define DO_MBED_LOCKFREE_CAS_WEAK_ASM(M) \ + asm volatile ( \ + "LDREX"#M "\t%[oldValue], [%[valuePtr]]\n" \ + "SUBS" "\t%[fail], %[oldValue], %[expectedValue]\n" \ + "STREX"#M"EQ\t%[fail], %[desiredValue], [%[valuePtr]]\n"\ + : [oldValue] "=&r" (oldValue), \ + [fail] "=&r" (fail) \ + : [desiredValue] "r" (desiredValue), \ + [expectedValue] "r" (expectedValue), \ + [valuePtr] "r" (ptr), \ + : "memory", "cc" \ + ) +#endif +#else // MBED_EXCLUSIVE_ACCESS_ARM +#if defined __clang__ || defined __GNUC__ +#define DO_MBED_LOCKFREE_CAS_WEAK_ASM(M) \ + __asm volatile ( \ + ".syntax unified\n\t" \ + "LDREX"#M "\t%[oldValue], %[value]\n\t" \ + "SUBS" "\t%[fail], %[oldValue], %[expectedValue]\n\t"\ + "BNE" "\t%=f\n\t" \ + "STREX"#M "\t%[fail], %[desiredValue], %[value]\n" \ + "%=:" \ + : [oldValue] "=&" MBED_DOP_REG (oldValue), \ + [fail] "=&" MBED_DOP_REG (fail), \ + [value] "+Q" (*ptr) \ + : [desiredValue] "r" (desiredValue), \ + [expectedValue] MBED_SUB3_IMM MBED_DOP_REG (expectedValue) \ + : "cc" \ + ) +#elif defined __ICCARM__ +#define DO_MBED_LOCKFREE_CAS_WEAK_ASM(M) \ + asm volatile ( \ + "LDREX"#M "\t%[oldValue], [%[valuePtr]]\n" \ + "SUBS" "\t%[fail], %[oldValue], %[expectedValue]\n" \ + "BNE" "\tdone\n\t" \ + "STREX"#M "\t%[fail], %[desiredValue], [%[valuePtr]]\n"\ + "done:" \ + : [oldValue] "=&r" (oldValue), \ + [fail] "=&r" (fail) \ + : [desiredValue] "r" (desiredValue), \ + [expectedValue] "r" (expectedValue), \ + [valuePtr] "r" (ptr) \ + : "memory", "cc" \ + ) +#endif +#endif // MBED_EXCLUSIVE_ACCESS_ARM + +/* For strong CAS, conditional execution is complex enough to + * not be worthwhile, so all implementations look like Thumb-1. + * (This is the operation for which STREX returning 0 for success + * is beneficial.) + */ +#if defined __clang__ || defined __GNUC__ +#define DO_MBED_LOCKFREE_CAS_STRONG_ASM(M) \ + __asm volatile ( \ + ".syntax unified\n\t" \ + "\n%=:\n\t" \ + "LDREX"#M "\t%[oldValue], %[value]\n\t" \ + "SUBS" "\t%[fail], %[oldValue], %[expectedValue]\n\t"\ + "BNE" "\t%=f\n" \ + "STREX"#M "\t%[fail], %[desiredValue], %[value]\n\t" \ + "CMP" "\t%[fail], #0\n\t" \ + "BNE" "\t%=b\n" \ + "%=:" \ + : [oldValue] "=&" MBED_DOP_REG (oldValue), \ + [fail] "=&" MBED_DOP_REG (fail), \ + [value] "+Q" (*ptr) \ + : [desiredValue] "r" (desiredValue), \ + [expectedValue] MBED_SUB3_IMM MBED_DOP_REG (expectedValue) \ + : "cc" \ + ) +#elif defined __ICCARM__ +#define DO_MBED_LOCKFREE_CAS_STRONG_ASM(M) \ + asm volatile ( \ + "retry:\n" \ + "LDREX"#M "\t%[oldValue], [%[valuePtr]]\n" \ + "SUBS" "\t%[fail], %[oldValue], %[expectedValue]\n" \ + "BNE" "\tdone\n" \ + "STREX"#M "\t%[fail], %[desiredValue], [%[valuePtr]]\n"\ + "CMP" "\t%[fail], #0\n" \ + "BNE" "\tretry\n" \ + "done:" \ + : [oldValue] "=&r" (oldValue), \ + [fail] "=&r" (fail) \ + : [desiredValue] "r" (desiredValue), \ + [expectedValue] "r" (expectedValue), \ + [valuePtr] "r" (ptr) \ + : "memory", "cc" \ + ) +#endif + +/********************* LOCK-FREE IMPLEMENTATION MACROS ****************/ + +/* Note care taken with types here. Values which the assembler outputs correctly + * narrowed, or inputs without caring about width, are marked as type T. Other + * values are uint32_t. It's not clear from documentation whether assembler + * assumes anything about widths, but try to signal correctly to get necessary + * narrowing, and avoid unnecessary. + * Tests show that GCC in particular will pass in unnarrowed values - eg passing + * "uint8_t arg = -1" to the assembler as 0xFFFFFFFF. This is fine for, eg, add_u8, + * but wouldn't be for compare_and_exchange_u8. + * On the other hand, it seems to be impossible to stop GCC inserting narrowing + * instructions for the output - it will always put in UXTB for the oldValue of + * an operation. + */ +#define DO_MBED_LOCKFREE_EXCHG_OP(T, fn_suffix, M) \ +inline T core_util_atomic_exchange_##fn_suffix(volatile T *valuePtr, T newValue) \ +{ \ + T oldValue; \ + uint32_t fail; \ + MBED_BARRIER(); \ + DO_MBED_LOCKFREE_EXCHG_ASM(M); \ + MBED_BARRIER(); \ + return oldValue; \ +} \ + \ +MBED_FORCEINLINE T core_util_atomic_exchange_explicit_##fn_suffix( \ + volatile T *valuePtr, T newValue, mbed_memory_order order) \ +{ \ + T oldValue; \ + uint32_t fail; \ + MBED_RELEASE_BARRIER(order); \ + DO_MBED_LOCKFREE_EXCHG_ASM(M); \ + MBED_ACQUIRE_BARRIER(order); \ + return oldValue; \ +} + +#define DO_MBED_LOCKFREE_CAS_WEAK_OP(T, fn_suffix, M) \ +inline bool core_util_atomic_compare_exchange_weak_##fn_suffix(volatile T *ptr, T *expectedCurrentValue, T desiredValue) \ +{ \ + MBED_BARRIER(); \ + T oldValue; \ + uint32_t fail, expectedValue = *expectedCurrentValue; \ + DO_MBED_LOCKFREE_CAS_WEAK_ASM(M); \ + if (fail) { \ + *expectedCurrentValue = oldValue; \ + } \ + MBED_BARRIER(); \ + return !fail; \ +} \ + \ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_##fn_suffix(volatile T *ptr, T *expectedCurrentValue, T desiredValue, mbed_memory_order success, mbed_memory_order failure) \ +{ \ + MBED_CHECK_CAS_ORDER(success, failure); \ + MBED_RELEASE_BARRIER(success); \ + T oldValue; \ + uint32_t fail, expectedValue = *expectedCurrentValue; \ + DO_MBED_LOCKFREE_CAS_WEAK_ASM(M); \ + if (fail) { \ + *expectedCurrentValue = oldValue; \ + } \ + MBED_ACQUIRE_BARRIER(fail ? failure : success); \ + return !fail; \ +} + +#define DO_MBED_LOCKFREE_CAS_STRONG_OP(T, fn_suffix, M) \ +inline bool core_util_atomic_cas_##fn_suffix(volatile T *ptr, T *expectedCurrentValue, T desiredValue) \ +{ \ + MBED_BARRIER(); \ + T oldValue; \ + uint32_t fail, expectedValue = *expectedCurrentValue; \ + DO_MBED_LOCKFREE_CAS_STRONG_ASM(M); \ + if (fail) { \ + *expectedCurrentValue = oldValue; \ + } \ + MBED_BARRIER(); \ + return !fail; \ +} \ + \ +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_##fn_suffix(volatile T *ptr, T *expectedCurrentValue, T desiredValue, mbed_memory_order success, mbed_memory_order failure) \ +{ \ + MBED_CHECK_CAS_ORDER(success, failure); \ + MBED_RELEASE_BARRIER(success); \ + T oldValue; \ + uint32_t fail, expectedValue = *expectedCurrentValue; \ + DO_MBED_LOCKFREE_CAS_STRONG_ASM(M); \ + if (fail) { \ + *expectedCurrentValue = oldValue; \ + } \ + MBED_ACQUIRE_BARRIER(fail ? failure : success); \ + return !fail; \ +} + + +#define DO_MBED_LOCKFREE_NEWVAL_2OP(name, OP, Constants, T, fn_suffix, M) \ +inline T core_util_atomic_##name##_##fn_suffix(volatile T *valuePtr, T arg) \ +{ \ + uint32_t fail, newValue; \ + MBED_BARRIER(); \ + do { \ + DO_MBED_LOCKFREE_NEWVAL_2OP_ASM(OP, Constants, M); \ + } while (fail); \ + MBED_BARRIER(); \ + return (T) newValue; \ +} \ + \ +MBED_FORCEINLINE T core_util_atomic_##name##_explicit_##fn_suffix( \ + volatile T *valuePtr, T arg, mbed_memory_order order) \ +{ \ + uint32_t fail, newValue; \ + MBED_RELEASE_BARRIER(order); \ + do { \ + DO_MBED_LOCKFREE_NEWVAL_2OP_ASM(OP, Constants, M); \ + } while (fail); \ + MBED_ACQUIRE_BARRIER(order); \ + return (T) newValue; \ +} \ + +#define DO_MBED_LOCKFREE_OLDVAL_2OP(name, OP, Constants, T, fn_suffix, M) \ +inline T core_util_atomic_##name##_##fn_suffix(volatile T *valuePtr, T arg) \ +{ \ + T oldValue; \ + uint32_t fail, newValue; \ + MBED_BARRIER(); \ + do { \ + DO_MBED_LOCKFREE_OLDVAL_2OP_ASM(OP, Constants, M); \ + } while (fail); \ + MBED_BARRIER(); \ + return oldValue; \ +} \ + \ +MBED_FORCEINLINE T core_util_atomic_##name##_explicit_##fn_suffix( \ + volatile T *valuePtr, T arg, mbed_memory_order order) \ +{ \ + T oldValue; \ + uint32_t fail, newValue; \ + MBED_RELEASE_BARRIER(order); \ + do { \ + DO_MBED_LOCKFREE_OLDVAL_2OP_ASM(OP, Constants, M); \ + } while (fail); \ + MBED_ACQUIRE_BARRIER(order); \ + return oldValue; \ +} \ + +#define DO_MBED_LOCKFREE_OLDVAL_3OP(name, OP, Constants, T, fn_suffix, M) \ +inline T core_util_atomic_##name##_##fn_suffix(volatile T *valuePtr, T arg) { \ + T oldValue; \ + uint32_t fail, newValue; \ + MBED_BARRIER(); \ + do { \ + DO_MBED_LOCKFREE_OLDVAL_3OP_ASM(OP, Constants, M); \ + } while (fail); \ + MBED_BARRIER(); \ + return oldValue; \ +} \ + \ +MBED_FORCEINLINE T core_util_atomic_##name##_explicit_##fn_suffix( \ + volatile T *valuePtr, T arg, mbed_memory_order order) \ +{ \ + T oldValue; \ + uint32_t fail, newValue; \ + MBED_RELEASE_BARRIER(order); \ + do { \ + DO_MBED_LOCKFREE_OLDVAL_3OP_ASM(OP, Constants, M); \ + } while (fail); \ + MBED_ACQUIRE_BARRIER(order); \ + return oldValue; \ +} \ + +inline bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *valuePtr) +{ + MBED_BARRIER(); + bool oldValue, newValue = true; + uint32_t fail; + do { + DO_MBED_LOCKFREE_EXCHG_ASM(B); + } while (fail); + MBED_BARRIER(); + return oldValue; +} + +MBED_FORCEINLINE bool core_util_atomic_flag_test_and_set_explicit(volatile core_util_atomic_flag *valuePtr, mbed_memory_order order) +{ + MBED_RELEASE_BARRIER(order); + bool oldValue, newValue = true; + uint32_t fail; + do { + DO_MBED_LOCKFREE_EXCHG_ASM(B); + } while (fail); + MBED_ACQUIRE_BARRIER(order); + return oldValue; +} + +/********************* LOCK-FREE IMPLEMENTATION DEFINITIONS ****************/ + +#define DO_MBED_LOCKFREE_EXCHG_OPS() \ + DO_MBED_LOCKFREE_EXCHG_OP(uint8_t, u8, B) \ + DO_MBED_LOCKFREE_EXCHG_OP(uint16_t, u16, H) \ + DO_MBED_LOCKFREE_EXCHG_OP(uint32_t, u32, ) + +#define DO_MBED_LOCKFREE_NEWVAL_2OPS(name, OP, Constants) \ + DO_MBED_LOCKFREE_NEWVAL_2OP(name, OP, Constants, uint8_t, u8, B) \ + DO_MBED_LOCKFREE_NEWVAL_2OP(name, OP, Constants, uint16_t, u16, H) \ + DO_MBED_LOCKFREE_NEWVAL_2OP(name, OP, Constants, uint32_t, u32, ) + +#define DO_MBED_LOCKFREE_OLDVAL_3OPS(name, OP, Constants) \ + DO_MBED_LOCKFREE_OLDVAL_3OP(name, OP, Constants, uint8_t, u8, B) \ + DO_MBED_LOCKFREE_OLDVAL_3OP(name, OP, Constants, uint16_t, u16, H) \ + DO_MBED_LOCKFREE_OLDVAL_3OP(name, OP, Constants, uint32_t, u32, ) + +#define DO_MBED_LOCKFREE_OLDVAL_2OPS(name, OP, Constants) \ + DO_MBED_LOCKFREE_OLDVAL_2OP(name, OP, Constants, uint8_t, u8, B) \ + DO_MBED_LOCKFREE_OLDVAL_2OP(name, OP, Constants, uint16_t, u16, H) \ + DO_MBED_LOCKFREE_OLDVAL_2OP(name, OP, Constants, uint32_t, u32, ) + +#define DO_MBED_LOCKFREE_CAS_STRONG_OPS() \ + DO_MBED_LOCKFREE_CAS_STRONG_OP(uint8_t, u8, B) \ + DO_MBED_LOCKFREE_CAS_STRONG_OP(uint16_t, u16, H) \ + DO_MBED_LOCKFREE_CAS_STRONG_OP(uint32_t, u32, ) + +#define DO_MBED_LOCKFREE_CAS_WEAK_OPS() \ + DO_MBED_LOCKFREE_CAS_WEAK_OP(uint8_t, u8, B) \ + DO_MBED_LOCKFREE_CAS_WEAK_OP(uint16_t, u16, H) \ + DO_MBED_LOCKFREE_CAS_WEAK_OP(uint32_t, u32, ) + +// Note that these macros define a number of functions that are +// not in mbed_atomic.h, like core_util_atomic_and_fetch_u16. +// These are not documented via the doxygen in mbed_atomic.h, so +// for now should be regarded as internal only. They are used by the +// Atomic template as an optimisation though. + +// We always use the "S" form of operations - avoids yet another +// possible unneeded distinction between Thumbv1 and Thumbv2, and +// may reduce code size by allowing 16-bit instructions. +#if !MBED_EXCLUSIVE_ACCESS_THUMB1 +// I constraint is 12-bit modified immediate constant +// L constraint is negated 12-bit modified immediate constant +// (relying on assembler to swap ADD/SUB) +// We could permit J (-4095 to +4095) if we used ADD/SUB +// instead of ADDS/SUBS, but then that would block generation +// of the 16-bit forms. Shame we can't specify "don't care" +// for the "S", or get the GNU multi-alternative to +// choose ADDS/ADD appropriately. + +DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_add, ADDS, "IL") +DO_MBED_LOCKFREE_NEWVAL_2OPS(incr, ADDS, "IL") +DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_sub, SUBS, "IL") +DO_MBED_LOCKFREE_NEWVAL_2OPS(decr, SUBS, "IL") +// K constraint is inverted 12-bit modified immediate constant +// (relying on assembler substituting BIC for AND) +DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_and, ANDS, "IK") +DO_MBED_LOCKFREE_NEWVAL_2OPS(and_fetch, ANDS, "IK") +#if MBED_EXCLUSIVE_ACCESS_ARM +// ARM does not have ORN instruction, so take plain immediates. +DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_or, ORRS, "I") +DO_MBED_LOCKFREE_NEWVAL_2OPS(or_fetch, ORRS, "I") +#else +// Thumb-2 has ORN instruction, and assembler substitutes ORN for ORR. +DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_or, ORRS, "IK") +DO_MBED_LOCKFREE_NEWVAL_2OPS(or_fetch, ORRS, "IK") +#endif +// I constraint is 12-bit modified immediate operand +DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_xor, EORS, "I") +DO_MBED_LOCKFREE_NEWVAL_2OPS(xor_fetch, EORS, "I") +#else // MBED_EXCLUSIVE_ACCESS_THUMB1 +// I constraint is 0-255; J is -255 to -1, suitable for +// 2-op ADD/SUB (relying on assembler to swap ADD/SUB) +// L constraint is -7 to +7, suitable for 3-op ADD/SUB +// (relying on assembler to swap ADD/SUB) +DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_add, ADDS, "L") +DO_MBED_LOCKFREE_NEWVAL_2OPS(incr, ADDS, "IJ") +DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_sub, SUBS, "L") +DO_MBED_LOCKFREE_NEWVAL_2OPS(decr, SUBS, "IJ") +DO_MBED_LOCKFREE_OLDVAL_2OPS(fetch_and, ANDS, "") +DO_MBED_LOCKFREE_NEWVAL_2OPS(and_fetch, ANDS, "") +DO_MBED_LOCKFREE_OLDVAL_2OPS(fetch_or, ORRS, "") +DO_MBED_LOCKFREE_NEWVAL_2OPS(or_fetch, ORRS, "") +DO_MBED_LOCKFREE_OLDVAL_2OPS(fetch_xor, EORS, "") +DO_MBED_LOCKFREE_NEWVAL_2OPS(xor_fetch, EORS, "") +#endif + +DO_MBED_LOCKFREE_EXCHG_OPS() +DO_MBED_LOCKFREE_CAS_STRONG_OPS() +DO_MBED_LOCKFREE_CAS_WEAK_OPS() + +#define DO_MBED_LOCKED_FETCH_OP_ORDERINGS(name) \ + DO_MBED_LOCKED_FETCH_OP_ORDERING(name, uint64_t, u64) +#define DO_MBED_LOCKED_CAS_ORDERINGS(name) \ + DO_MBED_LOCKED_CAS_ORDERING(name, uint64_t, u64) +#else // MBED_EXCLUSIVE_ACCESS +/* All the operations are locked, so need no ordering parameters */ +#define DO_MBED_LOCKED_FETCH_OP_ORDERINGS(name) \ + DO_MBED_LOCKED_FETCH_OP_ORDERING(name, uint8_t, u8) \ + DO_MBED_LOCKED_FETCH_OP_ORDERING(name, uint16_t, u16) \ + DO_MBED_LOCKED_FETCH_OP_ORDERING(name, uint32_t, u32) \ + DO_MBED_LOCKED_FETCH_OP_ORDERING(name, uint64_t, u64) +#define DO_MBED_LOCKED_CAS_ORDERINGS(name) \ + DO_MBED_LOCKED_CAS_ORDERING(name, uint8_t, u8) \ + DO_MBED_LOCKED_CAS_ORDERING(name, uint16_t, u16) \ + DO_MBED_LOCKED_CAS_ORDERING(name, uint32_t, u32) \ + DO_MBED_LOCKED_CAS_ORDERING(name, uint64_t, u64) + +MBED_FORCEINLINE bool core_util_atomic_flag_test_and_set_explicit(volatile core_util_atomic_flag *valuePtr, mbed_memory_order order) +{ + return core_util_atomic_flag_test_and_set(valuePtr); +} +#endif // MBED_EXCLUSIVE_ACCESS + +/********************* OPERATIONS THAT ARE ALWAYS LOCK-FREE ****************/ + +/* Lock-free loads and stores don't need assembler - just aligned accesses */ +/* Silly ordering of `T volatile` is because T can be `void *` */ +#define DO_MBED_LOCKFREE_LOADSTORE(T, V, fn_suffix) \ +MBED_FORCEINLINE T core_util_atomic_load_##fn_suffix(T const V *valuePtr) \ +{ \ + T value = *valuePtr; \ + MBED_BARRIER(); \ + return value; \ +} \ + \ +MBED_FORCEINLINE T core_util_atomic_load_explicit_##fn_suffix(T const V *valuePtr, mbed_memory_order order) \ +{ \ + MBED_CHECK_LOAD_ORDER(order); \ + T value = *valuePtr; \ + MBED_ACQUIRE_BARRIER(order); \ + return value; \ +} \ + \ +MBED_FORCEINLINE void core_util_atomic_store_##fn_suffix(T V *valuePtr, T value) \ +{ \ + MBED_BARRIER(); \ + *valuePtr = value; \ + MBED_BARRIER(); \ +} \ + \ +MBED_FORCEINLINE void core_util_atomic_store_explicit_##fn_suffix(T V *valuePtr, T value, mbed_memory_order order) \ +{ \ + MBED_CHECK_STORE_ORDER(order); \ + MBED_RELEASE_BARRIER(order); \ + *valuePtr = value; \ + MBED_SEQ_CST_BARRIER(order); \ +} + +MBED_FORCEINLINE void core_util_atomic_flag_clear(volatile core_util_atomic_flag *flagPtr) +{ + MBED_BARRIER(); + flagPtr->_flag = false; + MBED_BARRIER(); +} + +MBED_FORCEINLINE void core_util_atomic_flag_clear_explicit(volatile core_util_atomic_flag *flagPtr, mbed_memory_order order) +{ + MBED_CHECK_STORE_ORDER(order); + MBED_RELEASE_BARRIER(order); + flagPtr->_flag = false; + MBED_SEQ_CST_BARRIER(order); +} + +#ifdef __cplusplus +// Temporarily turn off extern "C", so we can provide non-volatile load/store +// overloads for efficiency. All these functions are static inline, so this has +// no linkage effect exactly, it just permits the overloads. +} // extern "C" + +// For efficiency it's worth having non-volatile overloads +MBED_FORCEINLINE void core_util_atomic_flag_clear(core_util_atomic_flag *flagPtr) +{ + MBED_BARRIER(); + flagPtr->_flag = false; + MBED_BARRIER(); +} + +MBED_FORCEINLINE void core_util_atomic_flag_clear_explicit(core_util_atomic_flag *flagPtr, mbed_memory_order order) +{ + MBED_RELEASE_BARRIER(order); + flagPtr->_flag = false; + MBED_SEQ_CST_BARRIER(order); +} + +DO_MBED_LOCKFREE_LOADSTORE(uint8_t,, u8) +DO_MBED_LOCKFREE_LOADSTORE(uint16_t,, u16) +DO_MBED_LOCKFREE_LOADSTORE(uint32_t,, u32) +DO_MBED_LOCKFREE_LOADSTORE(int8_t,, s8) +DO_MBED_LOCKFREE_LOADSTORE(int16_t,, s16) +DO_MBED_LOCKFREE_LOADSTORE(int32_t,, s32) +DO_MBED_LOCKFREE_LOADSTORE(bool,, bool) +DO_MBED_LOCKFREE_LOADSTORE(void *,, ptr) + +#endif + +DO_MBED_LOCKFREE_LOADSTORE(uint8_t, volatile, u8) +DO_MBED_LOCKFREE_LOADSTORE(uint16_t, volatile, u16) +DO_MBED_LOCKFREE_LOADSTORE(uint32_t, volatile, u32) +DO_MBED_LOCKFREE_LOADSTORE(int8_t, volatile, s8) +DO_MBED_LOCKFREE_LOADSTORE(int16_t, volatile, s16) +DO_MBED_LOCKFREE_LOADSTORE(int32_t, volatile, s32) +DO_MBED_LOCKFREE_LOADSTORE(bool, volatile, bool) +DO_MBED_LOCKFREE_LOADSTORE(void *, volatile, ptr) + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* GENERIC VARIANTS - SIGNED, BOOL, POINTERS ****************/ + +MBED_FORCEINLINE int64_t core_util_atomic_load_s64(const volatile int64_t *valuePtr) +{ + return (int64_t)core_util_atomic_load_u64((const volatile uint64_t *)valuePtr); +} + +MBED_FORCEINLINE void core_util_atomic_store_s64(volatile int64_t *valuePtr, int64_t desiredValue) +{ + core_util_atomic_store_u64((volatile uint64_t *)valuePtr, (uint64_t)desiredValue); +} + +#define DO_MBED_SIGNED_CAS_OP(name, T, fn_suffix) \ +MBED_FORCEINLINE bool core_util_atomic_##name##_s##fn_suffix(volatile T *ptr, \ + T *expectedCurrentValue, T desiredValue) \ +{ \ + return core_util_atomic_##name##_u##fn_suffix((volatile u##T *)ptr, \ + (u##T *)expectedCurrentValue, (u##T)desiredValue); \ +} \ + \ +MBED_FORCEINLINE bool core_util_atomic_##name##_explicit_s##fn_suffix(volatile T *ptr, \ + T *expectedCurrentValue, T desiredValue, \ + mbed_memory_order success, mbed_memory_order failure) \ +{ \ + return core_util_atomic_##name##_explicit_u##fn_suffix((volatile u##T *)ptr, \ + (u##T *)expectedCurrentValue, (u##T)desiredValue, success, failure); \ +} + +#define DO_MBED_SIGNED_CAS_OPS(name) \ + DO_MBED_SIGNED_CAS_OP(name, int8_t, 8) \ + DO_MBED_SIGNED_CAS_OP(name, int16_t, 16) \ + DO_MBED_SIGNED_CAS_OP(name, int32_t, 32) \ + DO_MBED_SIGNED_CAS_OP(name, int64_t, 64) + +DO_MBED_SIGNED_CAS_OPS(cas) +DO_MBED_SIGNED_CAS_OPS(compare_exchange_weak) + +MBED_FORCEINLINE bool core_util_atomic_cas_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue) +{ + return core_util_atomic_cas_u8((volatile uint8_t *)ptr, (uint8_t *)expectedCurrentValue, desiredValue); +} + +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue, mbed_memory_order success, mbed_memory_order failure) +{ + return core_util_atomic_cas_explicit_u8((volatile uint8_t *)ptr, (uint8_t *)expectedCurrentValue, desiredValue, success, failure); +} + +inline bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue) +{ +#if MBED_ATOMIC_PTR_SIZE == 32 + return core_util_atomic_cas_u32( + (volatile uint32_t *)ptr, + (uint32_t *)expectedCurrentValue, + (uint32_t)desiredValue); +#else + return core_util_atomic_cas_u64( + (volatile uint64_t *)ptr, + (uint64_t *)expectedCurrentValue, + (uint64_t)desiredValue); +#endif +} + +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue, mbed_memory_order success, mbed_memory_order failure) +{ +#if MBED_ATOMIC_PTR_SIZE == 32 + return core_util_atomic_cas_explicit_u32( + (volatile uint32_t *)ptr, + (uint32_t *)expectedCurrentValue, + (uint32_t)desiredValue, + success, failure); +#else + return core_util_atomic_cas_explicit_u64( + (volatile uint64_t *)ptr, + (uint64_t *)expectedCurrentValue, + (uint64_t)desiredValue, + success, failure); +#endif +} + +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue) +{ + return core_util_atomic_compare_exchange_weak_u8((volatile uint8_t *)ptr, (uint8_t *)expectedCurrentValue, desiredValue); +} + +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue, mbed_memory_order success, mbed_memory_order failure) +{ + return core_util_atomic_compare_exchange_weak_explicit_u8((volatile uint8_t *)ptr, (uint8_t *)expectedCurrentValue, desiredValue, success, failure); +} + +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue) +{ +#if MBED_ATOMIC_PTR_SIZE == 32 + return core_util_atomic_compare_exchange_weak_u32( + (volatile uint32_t *)ptr, + (uint32_t *)expectedCurrentValue, + (uint32_t)desiredValue); +#else + return core_util_atomic_compare_exchange_weak_u64( + (volatile uint64_t *)ptr, + (uint64_t *)expectedCurrentValue, + (uint64_t)desiredValue); +#endif +} + +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue, mbed_memory_order success, mbed_memory_order failure) +{ +#if MBED_ATOMIC_PTR_SIZE == 32 + return core_util_atomic_compare_exchange_weak_explicit_u32( + (volatile uint32_t *)ptr, + (uint32_t *)expectedCurrentValue, + (uint32_t)desiredValue, + success, failure); +#else + return core_util_atomic_compare_exchange_weak_explicit_u64( + (volatile uint64_t *)ptr, + (uint64_t *)expectedCurrentValue, + (uint64_t)desiredValue, + success, failure); +#endif +} + +#define DO_MBED_SIGNED_FETCH_OP(name, T, fn_suffix) \ +MBED_FORCEINLINE T core_util_atomic_##name##_s##fn_suffix(volatile T *valuePtr, T arg) \ +{ \ + return (T)core_util_atomic_##name##_u##fn_suffix((volatile u##T *)valuePtr, (u##T)arg); \ +} + +#define DO_MBED_SIGNED_EXPLICIT_FETCH_OP(name, T, fn_suffix) \ +MBED_FORCEINLINE T core_util_atomic_##name##_explicit_s##fn_suffix(volatile T *valuePtr, T arg, mbed_memory_order order) \ +{ \ + return (T)core_util_atomic_##name##_explicit_u##fn_suffix((volatile u##T *)valuePtr, (u##T)arg, order); \ +} + +#define DO_MBED_SIGNED_FETCH_OPS(name) \ + DO_MBED_SIGNED_FETCH_OP(name, int8_t, 8) \ + DO_MBED_SIGNED_FETCH_OP(name, int16_t, 16) \ + DO_MBED_SIGNED_FETCH_OP(name, int32_t, 32) \ + DO_MBED_SIGNED_FETCH_OP(name, int64_t, 64) + +#define DO_MBED_SIGNED_EXPLICIT_FETCH_OPS(name) \ + DO_MBED_SIGNED_EXPLICIT_FETCH_OP(name, int8_t, 8) \ + DO_MBED_SIGNED_EXPLICIT_FETCH_OP(name, int16_t, 16) \ + DO_MBED_SIGNED_EXPLICIT_FETCH_OP(name, int32_t, 32) \ + DO_MBED_SIGNED_EXPLICIT_FETCH_OP(name, int64_t, 64) + +DO_MBED_SIGNED_FETCH_OPS(exchange) +DO_MBED_SIGNED_FETCH_OPS(incr) +DO_MBED_SIGNED_FETCH_OPS(decr) +DO_MBED_SIGNED_FETCH_OPS(fetch_add) +DO_MBED_SIGNED_FETCH_OPS(fetch_sub) + +DO_MBED_SIGNED_EXPLICIT_FETCH_OPS(exchange) +DO_MBED_SIGNED_EXPLICIT_FETCH_OPS(fetch_add) +DO_MBED_SIGNED_EXPLICIT_FETCH_OPS(fetch_sub) + +MBED_FORCEINLINE bool core_util_atomic_exchange_bool(volatile bool *valuePtr, bool desiredValue) +{ + return (bool)core_util_atomic_exchange_u8((volatile uint8_t *)valuePtr, desiredValue); +} + +MBED_FORCEINLINE bool core_util_atomic_exchange_explicit_bool(volatile bool *valuePtr, bool desiredValue, mbed_memory_order order) +{ + return (bool)core_util_atomic_exchange_explicit_u8((volatile uint8_t *)valuePtr, desiredValue, order); +} + +inline void *core_util_atomic_exchange_ptr(void *volatile *valuePtr, void *desiredValue) +{ +#if MBED_ATOMIC_PTR_SIZE == 32 + return (void *)core_util_atomic_exchange_u32((volatile uint32_t *)valuePtr, (uint32_t)desiredValue); +#else + return (void *)core_util_atomic_exchange_u64((volatile uint64_t *)valuePtr, (uint64_t)desiredValue); +#endif +} + +MBED_FORCEINLINE void *core_util_atomic_exchange_explicit_ptr(void *volatile *valuePtr, void *desiredValue, mbed_memory_order order) +{ +#if MBED_ATOMIC_PTR_SIZE == 32 + return (void *)core_util_atomic_exchange_explicit_u32((volatile uint32_t *)valuePtr, (uint32_t)desiredValue, order); +#else + return (void *)core_util_atomic_exchange_explicit_u64((volatile uint64_t *)valuePtr, (uint64_t)desiredValue, order); +#endif +} + +inline void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta) +{ +#if MBED_ATOMIC_PTR_SIZE == 32 + return (void *)core_util_atomic_incr_u32((volatile uint32_t *)valuePtr, (uint32_t)delta); +#else + return (void *)core_util_atomic_incr_u64((volatile uint64_t *)valuePtr, (uint64_t)delta); +#endif +} + +inline void *core_util_atomic_decr_ptr(void *volatile *valuePtr, ptrdiff_t delta) +{ +#if MBED_ATOMIC_PTR_SIZE == 32 + return (void *)core_util_atomic_decr_u32((volatile uint32_t *)valuePtr, (uint32_t)delta); +#else + return (void *)core_util_atomic_decr_u64((volatile uint64_t *)valuePtr, (uint64_t)delta); +#endif +} + +MBED_FORCEINLINE void *core_util_atomic_fetch_add_ptr(void *volatile *valuePtr, ptrdiff_t arg) +{ +#if MBED_ATOMIC_PTR_SIZE == 32 + return (void *)core_util_atomic_fetch_add_u32((volatile uint32_t *)valuePtr, (uint32_t)arg); +#else + return (void *)core_util_atomic_fetch_add_u64((volatile uint64_t *)valuePtr, (uint64_t)arg); +#endif +} + +MBED_FORCEINLINE void *core_util_atomic_fetch_add_explicit_ptr(void *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) +{ +#if MBED_ATOMIC_PTR_SIZE == 32 + return (void *)core_util_atomic_fetch_add_explicit_u32((volatile uint32_t *)valuePtr, (uint32_t)arg, order); +#else + return (void *)core_util_atomic_fetch_add_explicit_u64((volatile uint64_t *)valuePtr, (uint64_t)arg, order); +#endif +} + +MBED_FORCEINLINE void *core_util_atomic_fetch_sub_ptr(void *volatile *valuePtr, ptrdiff_t arg) +{ +#if MBED_ATOMIC_PTR_SIZE == 32 + return (void *)core_util_atomic_fetch_sub_u32((volatile uint32_t *)valuePtr, (uint32_t)arg); +#else + return (void *)core_util_atomic_fetch_sub_u64((volatile uint64_t *)valuePtr, (uint64_t)arg); +#endif +} + +MBED_FORCEINLINE void *core_util_atomic_fetch_sub_explicit_ptr(void *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) +{ +#if MBED_ATOMIC_PTR_SIZE == 32 + return (void *)core_util_atomic_fetch_sub_explicit_u32((volatile uint32_t *)valuePtr, (uint32_t)arg, order); +#else + return (void *)core_util_atomic_fetch_sub_explicit_u64((volatile uint64_t *)valuePtr, (uint64_t)arg, order); +#endif +} + +/***************** DUMMY EXPLICIT ORDERING FOR LOCKED OPS *****************/ + +/* Need to throw away the ordering information for all locked operations */ +MBED_FORCEINLINE uint64_t core_util_atomic_load_explicit_u64(const volatile uint64_t *valuePtr, MBED_UNUSED mbed_memory_order order) +{ + MBED_CHECK_LOAD_ORDER(order); + return core_util_atomic_load_u64(valuePtr); +} + +MBED_FORCEINLINE int64_t core_util_atomic_load_explicit_s64(const volatile int64_t *valuePtr, MBED_UNUSED mbed_memory_order order) +{ + MBED_CHECK_LOAD_ORDER(order); + return core_util_atomic_load_s64(valuePtr); +} + +MBED_FORCEINLINE void core_util_atomic_store_explicit_u64(volatile uint64_t *valuePtr, uint64_t desiredValue, MBED_UNUSED mbed_memory_order order) +{ + MBED_CHECK_STORE_ORDER(order); + core_util_atomic_store_u64(valuePtr, desiredValue); +} + +MBED_FORCEINLINE void core_util_atomic_store_explicit_s64(volatile int64_t *valuePtr, int64_t desiredValue, MBED_UNUSED mbed_memory_order order) +{ + MBED_CHECK_STORE_ORDER(order); + core_util_atomic_store_s64(valuePtr, desiredValue); +} + +#define DO_MBED_LOCKED_FETCH_OP_ORDERING(name, T, fn_suffix) \ +MBED_FORCEINLINE T core_util_atomic_##name##_explicit_##fn_suffix( \ + volatile T *valuePtr, T arg, MBED_UNUSED mbed_memory_order order) \ +{ \ + return core_util_atomic_##name##_##fn_suffix(valuePtr, arg); \ +} + +#define DO_MBED_LOCKED_CAS_ORDERING(name, T, fn_suffix) \ +MBED_FORCEINLINE bool core_util_atomic_##name##_explicit_##fn_suffix( \ + volatile T *ptr, T *expectedCurrentValue, T desiredValue, \ + MBED_UNUSED mbed_memory_order success, \ + MBED_UNUSED mbed_memory_order failure) \ +{ \ + MBED_CHECK_CAS_ORDER(success, failure); \ + return core_util_atomic_##name##_##fn_suffix(ptr, expectedCurrentValue, desiredValue); \ +} + +DO_MBED_LOCKED_FETCH_OP_ORDERINGS(exchange) +DO_MBED_LOCKED_FETCH_OP_ORDERINGS(fetch_add) +DO_MBED_LOCKED_FETCH_OP_ORDERINGS(fetch_sub) +DO_MBED_LOCKED_FETCH_OP_ORDERINGS(fetch_and) +DO_MBED_LOCKED_FETCH_OP_ORDERINGS(fetch_or) +DO_MBED_LOCKED_FETCH_OP_ORDERINGS(fetch_xor) +DO_MBED_LOCKED_CAS_ORDERINGS(cas) +DO_MBED_LOCKED_CAS_ORDERINGS(compare_exchange_weak) + +#ifdef __cplusplus +} // extern "C" + +/***************** TEMPLATE IMPLEMENTATIONS *****************/ + +/* Each of these groups provides specialisations for the T template for each of + * the small types (there is no base implementation), and the base implementation + * of the T * template. + */ +#define DO_MBED_ATOMIC_LOAD_TEMPLATE(T, fn_suffix) \ +template<> \ +inline T core_util_atomic_load(const volatile T *valuePtr) noexcept \ +{ \ + return core_util_atomic_load_##fn_suffix(valuePtr); \ +} \ + \ +template<> \ +inline T core_util_atomic_load(const T *valuePtr) noexcept \ +{ \ + return core_util_atomic_load_##fn_suffix(valuePtr); \ +} \ + \ +template<> \ +inline T core_util_atomic_load_explicit(const volatile T *valuePtr, mbed_memory_order order) noexcept \ +{ \ + return core_util_atomic_load_explicit_##fn_suffix(valuePtr, order); \ +} \ + \ +template<> \ +inline T core_util_atomic_load_explicit(const T *valuePtr, mbed_memory_order order) noexcept \ +{ \ + return core_util_atomic_load_explicit_##fn_suffix(valuePtr, order); \ +} + +template +inline T *core_util_atomic_load(T *const volatile *valuePtr) noexcept +{ + return (T *) core_util_atomic_load_ptr((void *const volatile *) valuePtr); +} + +template +inline T *core_util_atomic_load(T *const *valuePtr) noexcept +{ + return (T *) core_util_atomic_load_ptr((void *const *) valuePtr); +} + +template +inline T *core_util_atomic_load_explicit(T *const volatile *valuePtr, mbed_memory_order order) noexcept +{ + return (T *) core_util_atomic_load_explicit_ptr((void *const volatile *) valuePtr, order); +} + +template +inline T *core_util_atomic_load_explicit(T *const *valuePtr, mbed_memory_order order) noexcept +{ + return (T *) core_util_atomic_load_explicit_ptr((void *const *) valuePtr, order); +} + +DO_MBED_ATOMIC_LOAD_TEMPLATE(uint8_t, u8) +DO_MBED_ATOMIC_LOAD_TEMPLATE(uint16_t, u16) +DO_MBED_ATOMIC_LOAD_TEMPLATE(uint32_t, u32) +DO_MBED_ATOMIC_LOAD_TEMPLATE(uint64_t, u64) +DO_MBED_ATOMIC_LOAD_TEMPLATE(int8_t, s8) +DO_MBED_ATOMIC_LOAD_TEMPLATE(int16_t, s16) +DO_MBED_ATOMIC_LOAD_TEMPLATE(int32_t, s32) +DO_MBED_ATOMIC_LOAD_TEMPLATE(int64_t, s64) +DO_MBED_ATOMIC_LOAD_TEMPLATE(bool, bool) + +#define DO_MBED_ATOMIC_STORE_TEMPLATE(T, fn_suffix) \ +template<> \ +inline void core_util_atomic_store(volatile T *valuePtr, T val) noexcept \ +{ \ + core_util_atomic_store_##fn_suffix(valuePtr, val); \ +} \ + \ +template<> \ +inline void core_util_atomic_store(T *valuePtr, T val) noexcept \ +{ \ + core_util_atomic_store_##fn_suffix(valuePtr, val); \ +} \ + \ +template<> \ +inline void core_util_atomic_store_explicit(volatile T *valuePtr, T val, mbed_memory_order order) noexcept \ +{ \ + core_util_atomic_store_explicit_##fn_suffix(valuePtr, val, order); \ +} \ + \ +template<> \ +inline void core_util_atomic_store_explicit(T *valuePtr, T val, mbed_memory_order order) noexcept \ +{ \ + core_util_atomic_store_explicit_##fn_suffix(valuePtr, val, order); \ +} + +template +inline void core_util_atomic_store(T *volatile *valuePtr, T *val) noexcept +{ + core_util_atomic_store_ptr((void *volatile *) valuePtr, val); +} + +template +inline void core_util_atomic_store(T **valuePtr, T *val) noexcept +{ + core_util_atomic_store_ptr((void **) valuePtr, val); +} + +template +inline void core_util_atomic_store_explicit(T *volatile *valuePtr, T *val, mbed_memory_order order) noexcept +{ + core_util_atomic_store_ptr((void *volatile *) valuePtr, val, order); +} + +template +inline void core_util_atomic_store_explicit(T **valuePtr, T *val, mbed_memory_order order) noexcept +{ + core_util_atomic_store_ptr((void **) valuePtr, val, order); +} + +DO_MBED_ATOMIC_STORE_TEMPLATE(uint8_t, u8) +DO_MBED_ATOMIC_STORE_TEMPLATE(uint16_t, u16) +DO_MBED_ATOMIC_STORE_TEMPLATE(uint32_t, u32) +DO_MBED_ATOMIC_STORE_TEMPLATE(uint64_t, u64) +DO_MBED_ATOMIC_STORE_TEMPLATE(int8_t, s8) +DO_MBED_ATOMIC_STORE_TEMPLATE(int16_t, s16) +DO_MBED_ATOMIC_STORE_TEMPLATE(int32_t, s32) +DO_MBED_ATOMIC_STORE_TEMPLATE(int64_t, s64) +DO_MBED_ATOMIC_STORE_TEMPLATE(bool, bool) + +#define DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, T, fn_suffix) \ +template<> inline \ +bool core_util_atomic_##tname(volatile T *ptr, T *expectedCurrentValue, T desiredValue) noexcept \ +{ \ + return core_util_atomic_##fname##_##fn_suffix(ptr, expectedCurrentValue, desiredValue); \ +} + +template +inline bool core_util_atomic_compare_exchange_strong(T *volatile *ptr, T **expectedCurrentValue, T *desiredValue) noexcept +{ + return core_util_atomic_cas_ptr((void *volatile *) ptr, (void **) expectedCurrentValue, desiredValue); +} + +template +inline bool core_util_atomic_compare_exchange_weak(T *volatile *ptr, T **expectedCurrentValue, T *desiredValue) noexcept +{ + return core_util_atomic_compare_exchange_weak_ptr((void *volatile *) ptr, (void **) expectedCurrentValue, desiredValue); +} + +#define DO_MBED_ATOMIC_CAS_TEMPLATES(tname, fname) \ + DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, uint8_t, u8) \ + DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, uint16_t, u16) \ + DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, uint32_t, u32) \ + DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, uint64_t, u64) \ + DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, int8_t, s8) \ + DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, int16_t, s16) \ + DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, int32_t, s32) \ + DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, int64_t, s64) \ + DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, bool, bool) + +DO_MBED_ATOMIC_CAS_TEMPLATES(compare_exchange_strong, cas) +DO_MBED_ATOMIC_CAS_TEMPLATES(compare_exchange_weak, compare_exchange_weak) + +#define DO_MBED_ATOMIC_OP_TEMPLATE(name, T, fn_suffix) \ +template<> \ +inline T core_util_atomic_##name(volatile T *valuePtr, T arg) noexcept \ +{ \ + return core_util_atomic_##name##_##fn_suffix(valuePtr, arg); \ +} \ + \ +template<> \ +inline T core_util_atomic_##name##_explicit(volatile T *valuePtr, T arg, \ + mbed_memory_order order) noexcept \ +{ \ + return core_util_atomic_##name##_explicit_##fn_suffix(valuePtr, arg, order); \ +} + + +template<> +inline bool core_util_atomic_exchange(volatile bool *valuePtr, bool arg) noexcept +{ + return core_util_atomic_exchange_bool(valuePtr, arg); +} + +template<> +inline bool core_util_atomic_exchange_explicit(volatile bool *valuePtr, bool arg, mbed_memory_order order) noexcept +{ + return core_util_atomic_exchange_explicit_bool(valuePtr, arg, order); +} + +template +inline T *core_util_atomic_exchange(T *volatile *valuePtr, T *arg) noexcept +{ + return (T *) core_util_atomic_exchange_ptr((void *volatile *) valuePtr, arg); +} + +template +inline T *core_util_atomic_exchange_explicit(T *volatile *valuePtr, T *arg, mbed_memory_order order) noexcept +{ + return (T *) core_util_atomic_fetch_add_explicit_ptr((void *volatile *) valuePtr, arg, order); +} + +template +inline T *core_util_atomic_fetch_add(T *volatile *valuePtr, ptrdiff_t arg) noexcept +{ + return (T *) core_util_atomic_fetch_add_ptr((void *volatile *) valuePtr, arg * sizeof(T)); +} + +template +inline T *core_util_atomic_fetch_add_explicit(T *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) noexcept +{ + return (T *) core_util_atomic_fetch_add_explicit_ptr((void *volatile *) valuePtr, arg * sizeof(T), order); +} + +template +inline T *core_util_atomic_fetch_sub(T *volatile *valuePtr, ptrdiff_t arg) noexcept +{ + return (T *) core_util_atomic_fetch_sub_ptr((void *volatile *) valuePtr, arg * sizeof(T)); +} + +template +inline T *core_util_atomic_fetch_sub_explicit(T *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) noexcept +{ + return (T *) core_util_atomic_fetch_sub_explicit_ptr((void *volatile *) valuePtr, arg * sizeof(T), order); +} + + +#define DO_MBED_ATOMIC_OP_U_TEMPLATES(name) \ + DO_MBED_ATOMIC_OP_TEMPLATE(name, uint8_t, u8) \ + DO_MBED_ATOMIC_OP_TEMPLATE(name, uint16_t, u16) \ + DO_MBED_ATOMIC_OP_TEMPLATE(name, uint32_t, u32) \ + DO_MBED_ATOMIC_OP_TEMPLATE(name, uint64_t, u64) + +#define DO_MBED_ATOMIC_OP_S_TEMPLATES(name) \ + DO_MBED_ATOMIC_OP_TEMPLATE(name, int8_t, s8) \ + DO_MBED_ATOMIC_OP_TEMPLATE(name, int16_t, s16) \ + DO_MBED_ATOMIC_OP_TEMPLATE(name, int32_t, s32) \ + DO_MBED_ATOMIC_OP_TEMPLATE(name, int64_t, s64) + +#define DO_MBED_ATOMIC_MANUAL_PRE_OP_TEMPLATE(name, T, fn_suffix, postname, OP) \ +template<> \ +inline T core_util_atomic_##name(volatile T *valuePtr, T arg) noexcept \ +{ \ + return core_util_atomic_##postname##_##fn_suffix(valuePtr, arg) OP; \ +} \ + \ +template<> \ +inline T core_util_atomic_##name##_explicit(volatile T *valuePtr, T arg, \ + mbed_memory_order order) noexcept \ +{ \ + return core_util_atomic_##postname##_explicit_##fn_suffix(valuePtr, arg, order) OP; \ +} + +DO_MBED_ATOMIC_OP_U_TEMPLATES(exchange) +DO_MBED_ATOMIC_OP_S_TEMPLATES(exchange) +DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_add) +DO_MBED_ATOMIC_OP_S_TEMPLATES(fetch_add) +DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_sub) +DO_MBED_ATOMIC_OP_S_TEMPLATES(fetch_sub) +DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_and) +DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_or) +DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_xor) + +namespace mstd { +namespace impl { + +// Use custom assembler forms for pre-ops where available, else construct from post-ops +#if MBED_EXCLUSIVE_ACCESS +#define DO_MBED_ATOMIC_PRE_OP_TEMPLATES(name, postname, OP) \ + template T core_util_atomic_##name(volatile T *valuePtr, T arg) noexcept; \ + template T core_util_atomic_##name##_explicit(volatile T *valuePtr, T arg, mbed_memory_order order) noexcept; \ + DO_MBED_ATOMIC_OP_TEMPLATE(name, uint8_t, u8) \ + DO_MBED_ATOMIC_OP_TEMPLATE(name, uint16_t, u16) \ + DO_MBED_ATOMIC_OP_TEMPLATE(name, uint32_t, u32) \ + DO_MBED_ATOMIC_MANUAL_PRE_OP_TEMPLATE(name, uint64_t, u64, postname, OP) +#else +#define DO_MBED_ATOMIC_PRE_OP_TEMPLATES(name, postname, OP) \ + template T core_util_atomic_##name(volatile T *valuePtr, T arg) noexcept; \ + template T core_util_atomic_##name##_explicit(volatile T *valuePtr, T arg, mbed_memory_order order) noexcept; \ + DO_MBED_ATOMIC_MANUAL_PRE_OP_TEMPLATE(name, uint8_t, u8, postname, OP) \ + DO_MBED_ATOMIC_MANUAL_PRE_OP_TEMPLATE(name, uint16_t, u16, postname, OP) \ + DO_MBED_ATOMIC_MANUAL_PRE_OP_TEMPLATE(name, uint32_t, u32, postname, OP) \ + DO_MBED_ATOMIC_MANUAL_PRE_OP_TEMPLATE(name, uint64_t, u64, postname, OP) +#endif + +// *INDENT-OFF* +DO_MBED_ATOMIC_PRE_OP_TEMPLATES(incr, fetch_add, + arg) +DO_MBED_ATOMIC_PRE_OP_TEMPLATES(decr, fetch_sub, - arg) +DO_MBED_ATOMIC_PRE_OP_TEMPLATES(and_fetch, fetch_and, & arg) +DO_MBED_ATOMIC_PRE_OP_TEMPLATES(or_fetch, fetch_or, | arg) +DO_MBED_ATOMIC_PRE_OP_TEMPLATES(xor_fetch, fetch_xor, ^ arg) +// *INDENT-ON* + +} +} + +#endif // __cplusplus + +#undef MBED_DOP_REG +#undef MBED_CMP_IMM +#undef MBED_SUB3_IMM +#undef DO_MBED_LOCKFREE_EXCHG_ASM +#undef DO_MBED_LOCKFREE_NEWVAL_2OP_ASM +#undef DO_MBED_LOCKFREE_OLDVAL_3OP_ASM +#undef DO_MBED_LOCKFREE_OLDVAL_2OP_ASM +#undef DO_MBED_LOCKFREE_CAS_WEAK_ASM +#undef DO_MBED_LOCKFREE_CAS_STRONG_ASM +#undef DO_MBED_LOCKFREE_LOADSTORE +#undef DO_MBED_LOCKFREE_EXCHG_OP +#undef DO_MBED_LOCKFREE_CAS_WEAK_OP +#undef DO_MBED_LOCKFREE_CAS_STRONG_OP +#undef DO_MBED_LOCKFREE_NEWVAL_2OP +#undef DO_MBED_LOCKFREE_OLDVAL_2OP +#undef DO_MBED_LOCKFREE_OLDVAL_3OP +#undef DO_MBED_LOCKFREE_EXCHG_OPS +#undef DO_MBED_LOCKFREE_NEWVAL_2OPS +#undef DO_MBED_LOCKFREE_OLDVAL_2OPS +#undef DO_MBED_LOCKFREE_OLDVAL_3OPS +#undef DO_MBED_LOCKFREE_CAS_WEAK_OPS +#undef DO_MBED_LOCKFREE_CAS_STRONG_OPS +#undef DO_MBED_SIGNED_CAS_OP +#undef DO_MBED_SIGNED_CAS_OPS +#undef DO_MBED_SIGNED_FETCH_OP +#undef DO_MBED_SIGNED_EXPLICIT_FETCH_OP +#undef DO_MBED_SIGNED_FETCH_OPS +#undef DO_MBED_SIGNED_EXPLICIT_FETCH_OPS +#undef DO_MBED_LOCKED_FETCH_OP_ORDERINGS +#undef DO_MBED_LOCKED_CAS_ORDERINGS +#undef MBED_ACQUIRE_BARRIER +#undef MBED_RELEASE_BARRIER +#undef MBED_SEQ_CST_BARRIER +#undef DO_MBED_ATOMIC_LOAD_TEMPLATE +#undef DO_MBED_ATOMIC_STORE_TEMPLATE +#undef DO_MBED_ATOMIC_EXCHANGE_TEMPLATE +#undef DO_MBED_ATOMIC_CAS_TEMPLATE +#undef DO_MBED_ATOMIC_CAS_TEMPLATES +#undef DO_MBED_ATOMIC_FETCH_TEMPLATE +#undef DO_MBED_ATOMIC_FETCH_U_TEMPLATES +#undef DO_MBED_ATOMIC_FETCH_S_TEMPLATES + +#endif diff --git a/platform/include/platform/internal/mbed_fault_handler.h b/platform/include/platform/internal/mbed_fault_handler.h new file mode 100644 index 0000000..53813a4 --- /dev/null +++ b/platform/include/platform/internal/mbed_fault_handler.h @@ -0,0 +1,112 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-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_FAULT_HANDLER_H +#define MBED_FAULT_HANDLER_H + +#include "mbed_toolchain.h" +#include "mbed_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//Fault context struct +#ifdef TARGET_CORTEX_M +//WARNING: DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES in except.S files. +//Offset of these registers are used by fault handler in except.S +typedef struct { + uint32_t R0_reg; + uint32_t R1_reg; + uint32_t R2_reg; + uint32_t R3_reg; + uint32_t R4_reg; + uint32_t R5_reg; + uint32_t R6_reg; + uint32_t R7_reg; + uint32_t R8_reg; + uint32_t R9_reg; + uint32_t R10_reg; + uint32_t R11_reg; + uint32_t R12_reg; + uint32_t SP_reg; + uint32_t LR_reg; + uint32_t PC_reg; + uint32_t xPSR; + uint32_t PSP; + uint32_t MSP; + uint32_t EXC_RETURN; + uint32_t CONTROL; +} mbed_fault_context_t; +#elif defined TARGET_CORTEX_A +// This is not currently used, but would be a plausible implementation +typedef struct { + uint32_t R0_reg; + uint32_t R1_reg; + uint32_t R2_reg; + uint32_t R3_reg; + uint32_t R4_reg; + uint32_t R5_reg; + uint32_t R6_reg; + uint32_t R7_reg; + uint32_t R8_reg; + uint32_t R9_reg; + uint32_t R10_reg; + uint32_t R11_reg; + uint32_t R12_reg; + uint32_t SP_reg; + uint32_t LR_reg; + uint32_t PC_reg; + uint32_t CPSR; + uint32_t SP_usr; + uint32_t LR_usr; +} mbed_fault_context_t; +#else +// Dummy for mbed_crash_data_t +typedef struct { +} mbed_fault_context_t; +#endif + + +//Fault type definitions +#ifdef TARGET_CORTEX_M +//WARNING: DO NOT CHANGE THESE VALUES WITHOUT MAKING CORRESPONDING CHANGES in except.S files. +#define HARD_FAULT_EXCEPTION (0x10) //Keep some gap between values for any future insertion/expansion +#define MEMMANAGE_FAULT_EXCEPTION (0x20) +#define BUS_FAULT_EXCEPTION (0x30) +#define USAGE_FAULT_EXCEPTION (0x40) +#endif + +//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_fault_handler.c) to print the information without using C-lib support. +MBED_NORETURN void mbed_fault_handler(uint32_t fault_type, const mbed_fault_context_t *mbed_fault_context_in); + +/** + * Call this function to retrieve the fault context after a fatal exception which triggered a system reboot. The function retrieves the fault context stored in crash-report ram area which is preserved over reboot. + * @param fault_context Pointer to mbed_fault_context_t struct allocated by the caller. This is the mbed_fault_context_t info captured as part of the fatal exception which triggered the reboot. + * @return 0 or MBED_SUCCESS on success. + * MBED_ERROR_INVALID_ARGUMENT in case of invalid error_info pointer + * MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system + * + */ +mbed_error_status_t mbed_get_reboot_fault_context(mbed_fault_context_t *fault_context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/include/platform/mbed_application.h b/platform/include/platform/mbed_application.h new file mode 100644 index 0000000..37619e2 --- /dev/null +++ b/platform/include/platform/mbed_application.h @@ -0,0 +1,54 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 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_APPLICATION_H +#define MBED_APPLICATION_H + +#include + +#if defined(__CORTEX_M0PLUS) || defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__CORTEX_M7)\ + || defined(__CORTEX_M23) || defined(__CORTEX_A9) || defined(__CORTEX_M33) +#define MBED_APPLICATION_SUPPORT 1 +#else +#define MBED_APPLICATION_SUPPORT 0 +#endif + +#if MBED_APPLICATION_SUPPORT +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Start the application at the given address. This function does + * not return. It is the applications responsibility for flushing to + * or powering down external components such as filesystems or + * socket connections before calling this function. For Cortex-M + * devices this function powers down generic system components such as + * the NVIC and set the vector table to that of the new image followed + * by jumping to the reset handler of the new image. + * + * @param address Starting address of next application to run + */ +void mbed_start_application(uintptr_t address); + +#ifdef __cplusplus +} +#endif +#endif + +#endif + diff --git a/platform/include/platform/mbed_assert.h b/platform/include/platform/mbed_assert.h new file mode 100644 index 0000000..7df16b8 --- /dev/null +++ b/platform/include/platform/mbed_assert.h @@ -0,0 +1,127 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_ASSERT_H +#define MBED_ASSERT_H + +#include "platform/mbed_toolchain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_Assert Assert macros + * @{ + */ + +/** 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 Expression to be checked. + * @param file File where assertation failed. + * @param line Failing assertation line number. + */ +MBED_NORETURN void mbed_assert_internal(const char *expr, const char *file, int line); + +#ifdef __cplusplus +} +#endif + +/** MBED_ASSERT + * Declare runtime assertions: results in runtime error if condition is false + * + * @note + * Use of MBED_ASSERT is limited to Debug and Develop builds. + * + * @code + * + * int Configure(serial_t *obj) { + * MBED_ASSERT(obj); + * } + * @endcode + */ +#ifdef NDEBUG +#define MBED_ASSERT(expr) ((void)0) + +#else +#define MBED_ASSERT(expr) \ +do { \ + if (!(expr)) { \ + mbed_assert_internal(#expr, __FILE__, __LINE__); \ + } \ +} while (0) +#endif + + +/** MBED_STATIC_ASSERT + * Declare compile-time assertions, results in compile-time error if condition is false + * + * The assertion acts as a declaration that can be placed at file scope, in a + * code block (except after a label), or as a member of a C++ class/struct/union. + * + * @code + * MBED_STATIC_ASSERT(MBED_MAJOR_VERSION >= 6, + * "The mbed-os library must be at least version 6.0.0"); + * + * int main() { + * MBED_STATIC_ASSERT(sizeof(int) >= sizeof(char), + * "An int must be larger than a char"); + * } + * @endcode + * + * @deprecated This feature is now no longer necessary with the minimum + * supported language versions. It will be removed in a forthcoming release. + * Use `static_assert` instead. For C this is provided by ``, and + * for C++ it is a built-in keyword. + */ +#if defined(__cplusplus) +#define MBED_STATIC_ASSERT(expr, msg) static_assert(expr, msg) +#else +#define MBED_STATIC_ASSERT(expr, msg) _Static_assert(expr, msg) +#endif + +/** MBED_STRUCT_STATIC_ASSERT + * Declare compile-time assertions, results in compile-time error if condition is false + * + * Previous supported compiler languages would not allow static_assert to be + * used within a struct or a class. This is no longer the case. This macro + * exists for backwards compatibility. + * + * @code + * struct thing { + * MBED_STRUCT_STATIC_ASSERT(2 + 2 == 4, + * "Hopefully the universe is mathematically consistent"); + * }; + * @endcode + * + * @deprecated This feature is now no longer necessary with the minimum + * supported language versions. It will be removed in a forthcoming release. + * Use `static_assert` instead. For C this is provided by ``, and + * for C++ it is a built-in keyword. + */ +#define MBED_STRUCT_STATIC_ASSERT(expr, message) MBED_STATIC_ASSERT(expr, message) + +#endif + +/**@}*/ + +/**@}*/ + diff --git a/platform/include/platform/mbed_atomic.h b/platform/include/platform/mbed_atomic.h new file mode 100644 index 0000000..28e2cb2 --- /dev/null +++ b/platform/include/platform/mbed_atomic.h @@ -0,0 +1,998 @@ + +/* + * Copyright (c) 2015-2019, 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 __MBED_UTIL_ATOMIC_H__ +#define __MBED_UTIL_ATOMIC_H__ + +#include "cmsis.h" + +#include +#include +#include +#include "platform/mbed_toolchain.h" + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_atomic atomic functions + * + * Atomic functions function analogously to C11 and C++11 - loads have + * acquire semantics, stores have release semantics, and atomic operations + * are sequentially consistent. Atomicity is enforced both between threads and + * interrupt handlers. + * + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Memory order constraints for atomic operations. Intended semantics + * are as per C++11. + */ +typedef enum mbed_memory_order { + /* Bits 0 = consume + * 1 = acquire (explicitly requested, or implied by seq.cst) + * 2 = release (explicitly requested, or implied by seq.cst) + * 4 = sequentially consistent + */ + mbed_memory_order_relaxed = 0x00, + mbed_memory_order_consume = 0x01, + mbed_memory_order_acquire = 0x02, + mbed_memory_order_release = 0x04, + mbed_memory_order_acq_rel = 0x06, + mbed_memory_order_seq_cst = 0x16 +} mbed_memory_order; + +// if __EXCLUSIVE_ACCESS rtx macro not defined, we need to get this via own-set architecture macros +#ifndef MBED_EXCLUSIVE_ACCESS +#ifndef __EXCLUSIVE_ACCESS +#if defined __arm__ || defined __ICC_ARM__ || defined __ARM_ARCH +#if ((__ARM_ARCH_7M__ == 1U) || \ + (__ARM_ARCH_7EM__ == 1U) || \ + (__ARM_ARCH_8M_BASE__ == 1U) || \ + (__ARM_ARCH_8M_MAIN__ == 1U)) || \ + (__ARM_ARCH_7A__ == 1U) +#define MBED_EXCLUSIVE_ACCESS 1U +#define MBED_EXCLUSIVE_ACCESS_THUMB1 (__ARM_ARCH_8M_BASE__ == 1U) +#ifdef __ICCARM__ +#if __CPU_MODE__ == 2 +#define MBED_EXCLUSIVE_ACCESS_ARM 1U +#else +#define MBED_EXCLUSIVE_ACCESS_ARM 0U +#endif +#else +#if !defined (__thumb__) +#define MBED_EXCLUSIVE_ACCESS_ARM 1U +#else +#define MBED_EXCLUSIVE_ACCESS_ARM 0U +#endif +#endif +#elif (__ARM_ARCH_6M__ == 1U) +#define MBED_EXCLUSIVE_ACCESS 0U +#else +#error "Unknown ARM architecture for exclusive access" +#endif // __ARM_ARCH_xxx +#else // __arm__ || defined __ICC_ARM__ || defined __ARM_ARCH +// Seem to be compiling for non-ARM, so stick with critical section implementations +#define MBED_EXCLUSIVE_ACCESS 0U +#endif +#else +#define MBED_EXCLUSIVE_ACCESS __EXCLUSIVE_ACCESS +#endif +#endif + +#if MBED_EXCLUSIVE_ACCESS +#define MBED_INLINE_IF_EX inline +#else +#define MBED_INLINE_IF_EX +#endif + +/** + * A lock-free, primitive atomic flag. + * + * Emulate C11's atomic_flag. The flag is initially in an indeterminate state + * unless explicitly initialized with CORE_UTIL_ATOMIC_FLAG_INIT. + */ +typedef struct core_util_atomic_flag { + uint8_t _flag; +} core_util_atomic_flag; + +/** + * Initializer 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. + */ +MBED_INLINE_IF_EX bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr); + +/** \ copydoc core_util_atomic_flag_test_and_set + * @param order memory ordering constraint + */ +MBED_FORCEINLINE bool core_util_atomic_flag_test_and_set_explicit(volatile core_util_atomic_flag *valuePtr, mbed_memory_order order); + +/** + * Atomic clear. + * + * @param flagPtr Target flag being cleared. + */ +MBED_FORCEINLINE void core_util_atomic_flag_clear(volatile core_util_atomic_flag *flagPtr); + +/** \ copydoc core_util_atomic_flag_clear + * @param order memory ordering constraint + */ +MBED_FORCEINLINE void core_util_atomic_flag_clear_explicit(volatile core_util_atomic_flag *flagPtr, mbed_memory_order order); + + +/** + * 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 + * memory location to a given new value. This is done as a single atomic + * operation. The atomicity guarantees that the new value is calculated based on + * up-to-date information; if the value had been updated by another thread in + * the meantime, the write would fail due to a mismatched expectedCurrentValue. + * + * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect + * you to the article on compare-and swap]. + * + * @param ptr The target memory location. + * @param[in,out] expectedCurrentValue A pointer to some location holding the + * expected current value of the data being set atomically. + * The computed 'desiredValue' should be a function of this current value. + * @note: This is an in-out parameter. In the + * failure case of atomic_cas (where the + * destination isn't set), the pointee of expectedCurrentValue is + * updated with the current value. + * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. + * + * @return true if the memory location was atomically + * updated with the desired value (after verifying + * that it contained the expectedCurrentValue), + * false otherwise. In the failure case, + * exepctedCurrentValue is updated with the new + * value of the target memory location. + * + * pseudocode: + * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { + * if *p != *old { + * *old = *p + * return false + * } + * *p = new + * return true + * } + * + * @note: In the failure case (where the destination isn't set), the value + * pointed to by expectedCurrentValue is instead updated with the current value. + * This property helps writing concise code for the following incr: + * + * function incr(p : pointer to int, a : int) returns int { + * done = false + * value = atomic_load(p) + * while not done { + * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success + * } + * return value + a + * } + * + * However, if the call is made in a loop like this, the atomic_compare_exchange_weak + * functions are to be preferred. + * + * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it + * always succeeds if the current value is expected, as per the pseudocode + * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. + * This call would normally be used when a fail return does not retry. + */ +MBED_INLINE_IF_EX bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue); + +/** \copydoc core_util_atomic_cas_u8 + * @param success memory ordering constraint for successful exchange + * @param failure memory ordering constraint for failure + */ +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_cas_u8 */ +MBED_INLINE_IF_EX bool core_util_atomic_cas_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue); + +/** \copydoc core_util_atomic_cas_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_cas_u8 */ +MBED_INLINE_IF_EX bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue); + +/** \copydoc core_util_atomic_cas_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_cas_u8 */ +bool core_util_atomic_cas_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue); + +/** \copydoc core_util_atomic_cas_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_cas_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_s8(volatile int8_t *ptr, int8_t *expectedCurrentValue, int8_t desiredValue); + +/** \copydoc core_util_atomic_cas_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_s8(volatile int8_t *ptr, int8_t *expectedCurrentValue, int8_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_cas_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_s16(volatile int16_t *ptr, int16_t *expectedCurrentValue, int16_t desiredValue); + +/** \copydoc core_util_atomic_cas_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_s16(volatile int16_t *ptr, int16_t *expectedCurrentValue, int16_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_cas_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_s32(volatile int32_t *ptr, int32_t *expectedCurrentValue, int32_t desiredValue); + +/** \copydoc core_util_atomic_cas_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_s32(volatile int32_t *ptr, int32_t *expectedCurrentValue, int32_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_cas_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_s64(volatile int64_t *ptr, int64_t *expectedCurrentValue, int64_t desiredValue); + +/** \copydoc core_util_atomic_cas_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_s64(volatile int64_t *ptr, int64_t *expectedCurrentValue, int64_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_cas_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue); + +/** \copydoc core_util_atomic_cas_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_cas_u8 */ +inline bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue); + +/** \copydoc core_util_atomic_cas_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_cas_explicit_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue, mbed_memory_order success, mbed_memory_order failure); + + + +/** + * 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 + * memory location to a given new value. This is done as a single atomic + * operation. The atomicity guarantees that the new value is calculated based on + * up-to-date information; if the value had been updated by another thread in + * the meantime, the write would fail due to a mismatched expectedCurrentValue. + * + * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect + * you to the article on compare-and swap]. + * + * @param ptr The target memory location. + * @param[in,out] expectedCurrentValue A pointer to some location holding the + * expected current value of the data being set atomically. + * The computed 'desiredValue' should be a function of this current value. + * @note: This is an in-out parameter. In the + * failure case of atomic_cas (where the + * destination isn't set), the pointee of expectedCurrentValue is + * updated with the current value. + * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. + * + * @return true if the memory location was atomically + * updated with the desired value (after verifying + * that it contained the expectedCurrentValue), + * false otherwise. In the failure case, + * exepctedCurrentValue is updated with the new + * value of the target memory location. + * + * pseudocode: + * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { + * if *p != *old or spurious failure { + * *old = *p + * return false + * } + * *p = new + * return true + * } + * + * @note: In the failure case (where the destination isn't set), the value + * pointed to by expectedCurrentValue is instead updated with the current value. + * This property helps writing concise code for the following incr: + * + * function incr(p : pointer to int, a : int) returns int { + * done = false + * value = *p // This fetch operation need not be atomic. + * while not done { + * done = atomic_compare_exchange_weak(p, &value, value + a) // *value gets updated automatically until success + * } + * return value + a + * } + * + * @note: This corresponds to the C11 "atomic_compare_exchange_weak" - it + * may spuriously fail if the current value is expected, as per the pseudocode + * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. + * This call would normally be used when a fail return will cause a retry anyway, + * saving the need for an extra loop inside the cas operation. + */ +MBED_INLINE_IF_EX bool core_util_atomic_compare_exchange_weak_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue); + +/** \copydoc core_util_atomic_compare_exchange_weak_u8 + * @param success memory ordering constraint for successful exchange + * @param failure memory ordering constraint for failure + */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ +MBED_INLINE_IF_EX bool core_util_atomic_compare_exchange_weak_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue); + +/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ +MBED_INLINE_IF_EX bool core_util_atomic_compare_exchange_weak_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue); + +/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ +bool core_util_atomic_compare_exchange_weak_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue); + +/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_s8(volatile int8_t *ptr, int8_t *expectedCurrentValue, int8_t desiredValue); + +/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_s8(volatile int8_t *ptr, int8_t *expectedCurrentValue, int8_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_s16(volatile int16_t *ptr, int16_t *expectedCurrentValue, int16_t desiredValue); + +/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_s16(volatile int16_t *ptr, int16_t *expectedCurrentValue, int16_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_s32(volatile int32_t *ptr, int32_t *expectedCurrentValue, int32_t desiredValue); + +/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_s32(volatile int32_t *ptr, int32_t *expectedCurrentValue, int32_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_s64(volatile int64_t *ptr, int64_t *expectedCurrentValue, int64_t desiredValue); + +/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_s64(volatile int64_t *ptr, int64_t *expectedCurrentValue, int64_t desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue); + +/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue, mbed_memory_order success, mbed_memory_order failure); + +/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue); + +/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue, mbed_memory_order success, mbed_memory_order failure); + + +/** + * Atomic load. + * @param valuePtr Target memory location. + * @return The loaded value. + */ +MBED_FORCEINLINE uint8_t core_util_atomic_load_u8(const volatile uint8_t *valuePtr); + +/** + * \copydoc core_util_atomic_load_u8 + * @param order memory ordering constraint + */ +MBED_FORCEINLINE uint8_t core_util_atomic_load_explicit_u8(const volatile uint8_t *valuePtr, mbed_memory_order order); + +/** \copydoc core_util_atomic_load_u8 */ +MBED_FORCEINLINE uint16_t core_util_atomic_load_u16(const volatile uint16_t *valuePtr); + +/** \copydoc core_util_atomic_load_explicit_u8 */ +MBED_FORCEINLINE uint16_t core_util_atomic_load_explicit_u16(const volatile uint16_t *valuePtr, mbed_memory_order order); + +/** \copydoc core_util_atomic_load_u8 */ +MBED_FORCEINLINE uint32_t core_util_atomic_load_u32(const volatile uint32_t *valuePtr); + +/** \copydoc core_util_atomic_load_explicit_u8 */ +MBED_FORCEINLINE uint32_t core_util_atomic_load_explicit_u32(const volatile uint32_t *valuePtr, mbed_memory_order order); + +/** \copydoc core_util_atomic_load_u8 */ +uint64_t core_util_atomic_load_u64(const volatile uint64_t *valuePtr); + +/** \copydoc core_util_atomic_load_explicit_u8 */ +MBED_FORCEINLINE uint64_t core_util_atomic_load_explicit_u64(const volatile uint64_t *valuePtr, mbed_memory_order order); + +/** \copydoc core_util_atomic_load_u8 */ +MBED_FORCEINLINE int8_t core_util_atomic_load_s8(const volatile int8_t *valuePtr); + +/** \copydoc core_util_atomic_load_explicit_u8 */ +MBED_FORCEINLINE int8_t core_util_atomic_load_explicit_s8(const volatile int8_t *valuePtr, mbed_memory_order order); + +/** \copydoc core_util_atomic_load_u8 */ +MBED_FORCEINLINE int16_t core_util_atomic_load_s16(const volatile int16_t *valuePtr); + +/** \copydoc core_util_atomic_load_explicit_u8 */ +MBED_FORCEINLINE int16_t core_util_atomic_load_explicit_s16(const volatile int16_t *valuePtr, mbed_memory_order order); + +/** \copydoc core_util_atomic_load_u8 */ +MBED_FORCEINLINE int32_t core_util_atomic_load_s32(const volatile int32_t *valuePtr); + +/** \copydoc core_util_atomic_load_explicit_u8 */ +MBED_FORCEINLINE int32_t core_util_atomic_load_explicit_s32(const volatile int32_t *valuePtr, mbed_memory_order order); + +/** \copydoc core_util_atomic_load_u8 */ +MBED_FORCEINLINE int64_t core_util_atomic_load_s64(const volatile int64_t *valuePtr); + +/** \copydoc core_util_atomic_load_u8 */ +MBED_FORCEINLINE int64_t core_util_atomic_load_explicit_s64(const volatile int64_t *valuePtr, MBED_UNUSED mbed_memory_order order); + +/** \copydoc core_util_atomic_load_u8 */ +MBED_FORCEINLINE bool core_util_atomic_load_bool(const volatile bool *valuePtr); + +/** \copydoc core_util_atomic_load_u8 */ +MBED_FORCEINLINE bool core_util_atomic_load_explicit_bool(const volatile bool *valuePtr, mbed_memory_order order); + +/** \copydoc core_util_atomic_load_u8 */ +MBED_FORCEINLINE void *core_util_atomic_load_ptr(void *const volatile *valuePtr); + +/** \copydoc core_util_atomic_load_u8 */ +MBED_FORCEINLINE void *core_util_atomic_load_explicit_ptr(void *const volatile *valuePtr, mbed_memory_order order); + +/** + * Atomic store. + * @param valuePtr Target memory location. + * @param desiredValue The value to store. + */ +MBED_FORCEINLINE void core_util_atomic_store_u8(volatile uint8_t *valuePtr, uint8_t desiredValue); + +/** + * \copydoc core_util_atomic_store_u8 + * @param order memory ordering constraint + */ +MBED_FORCEINLINE void core_util_atomic_store_explicit_u8(volatile uint8_t *valuePtr, uint8_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_store_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_u16(volatile uint16_t *valuePtr, uint16_t desiredValue); + +/** \copydoc core_util_atomic_store_explicit_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_explicit_u16(volatile uint16_t *valuePtr, uint16_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_store_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_u32(volatile uint32_t *valuePtr, uint32_t desiredValue); + +/** \copydoc core_util_atomic_store_explicit_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_explicit_u32(volatile uint32_t *valuePtr, uint32_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_store_u8 */ +void core_util_atomic_store_u64(volatile uint64_t *valuePtr, uint64_t desiredValue); + +/** \copydoc core_util_atomic_store_explicit_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_explicit_u64(volatile uint64_t *valuePtr, uint64_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_store_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_s8(volatile int8_t *valuePtr, int8_t desiredValue); + +/** \copydoc core_util_atomic_store_explicit_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_explicit_s8(volatile int8_t *valuePtr, int8_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_store_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_s16(volatile int16_t *valuePtr, int16_t desiredValue); + +/** \copydoc core_util_atomic_store_explicit_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_explicit_s16(volatile int16_t *valuePtr, int16_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_store_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_s32(volatile int32_t *valuePtr, int32_t desiredValue); + +/** \copydoc core_util_atomic_store_explicit_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_explicit_s32(volatile int32_t *valuePtr, int32_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_store_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_s64(volatile int64_t *valuePtr, int64_t desiredValue); + +/** \copydoc core_util_atomic_store_explicit_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_explicit_s64(volatile int64_t *valuePtr, int64_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_store_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_bool(volatile bool *valuePtr, bool desiredValue); + +/** \copydoc core_util_atomic_store_explicit_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_explicit_bool(volatile bool *valuePtr, bool desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_store_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_ptr(void *volatile *valuePtr, void *desiredValue); + +/** \copydoc core_util_atomic_store_explicit_u8 */ +MBED_FORCEINLINE void core_util_atomic_store_explicit_ptr(void *volatile *valuePtr, void *desiredValue, mbed_memory_order order); + +/** + * Atomic exchange. + * @param valuePtr Target memory location. + * @param desiredValue The value to store. + * @return The previous value. + */ +MBED_INLINE_IF_EX uint8_t core_util_atomic_exchange_u8(volatile uint8_t *valuePtr, uint8_t desiredValue); + +/** \copydoc core_util_atomic_exchange_u8 + * @param order memory ordering constraint + */ +MBED_FORCEINLINE uint8_t core_util_atomic_exchange_explicit_u8(volatile uint8_t *valuePtr, uint8_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_exchange_u8 */ +MBED_INLINE_IF_EX uint16_t core_util_atomic_exchange_u16(volatile uint16_t *valuePtr, uint16_t desiredValue); + +/** \copydoc core_util_atomic_exchange_explicit_u8 */ +MBED_FORCEINLINE uint16_t core_util_atomic_exchange_explicit_u16(volatile uint16_t *valuePtr, uint16_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_exchange_u8 */ +MBED_INLINE_IF_EX uint32_t core_util_atomic_exchange_u32(volatile uint32_t *valuePtr, uint32_t desiredValue); + +/** \copydoc core_util_atomic_exchange_explicit_u8 */ +MBED_FORCEINLINE uint32_t core_util_atomic_exchange_explicit_u32(volatile uint32_t *valuePtr, uint32_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_exchange_u8 */ +uint64_t core_util_atomic_exchange_u64(volatile uint64_t *valuePtr, uint64_t desiredValue); + +/** \copydoc core_util_atomic_exchange_explicit_u8 */ +MBED_FORCEINLINE uint64_t core_util_atomic_exchange_explicit_u64(volatile uint64_t *valuePtr, uint64_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_exchange_u8 */ +MBED_FORCEINLINE int8_t core_util_atomic_exchange_s8(volatile int8_t *valuePtr, int8_t desiredValue); + +/** \copydoc core_util_atomic_exchange_explicit_u8 */ +MBED_FORCEINLINE int8_t core_util_atomic_exchange_explicit_s8(volatile int8_t *valuePtr, int8_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_exchange_u8 */ +MBED_FORCEINLINE int16_t core_util_atomic_exchange_s16(volatile int16_t *valuePtr, int16_t desiredValue); + +/** \copydoc core_util_atomic_exchange_explicit_u8 */ +MBED_FORCEINLINE int16_t core_util_atomic_exchange_explicit_s16(volatile int16_t *valuePtr, int16_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_exchange_u8 */ +MBED_FORCEINLINE int32_t core_util_atomic_exchange_s32(volatile int32_t *valuePtr, int32_t desiredValue); + +/** \copydoc core_util_atomic_exchange_explicit_u8 */ +MBED_FORCEINLINE int32_t core_util_atomic_exchange_explicit_s32(volatile int32_t *valuePtr, int32_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_exchange_u8 */ +MBED_FORCEINLINE int64_t core_util_atomic_exchange_s64(volatile int64_t *valuePtr, int64_t desiredValue); + +/** \copydoc core_util_atomic_exchange_explicit_u8 */ +MBED_FORCEINLINE int64_t core_util_atomic_exchange_explicit_s64(volatile int64_t *valuePtr, int64_t desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_exchange_u8 */ +MBED_FORCEINLINE bool core_util_atomic_exchange_bool(volatile bool *valuePtr, bool desiredValue); + +/** \copydoc core_util_atomic_exchange_explicit_u8 */ +MBED_FORCEINLINE bool core_util_atomic_exchange_explicit_bool(volatile bool *valuePtr, bool desiredValue, mbed_memory_order order); + +/** \copydoc core_util_atomic_exchange_u8 */ +inline void *core_util_atomic_exchange_ptr(void *volatile *valuePtr, void *desiredValue); + +/** \copydoc core_util_atomic_exchange_explicit_u8 */ +MBED_FORCEINLINE void *core_util_atomic_exchange_explicit_ptr(void *volatile *valuePtr, void *desiredValue, mbed_memory_order order); + +/** + * Atomic increment. + * @param valuePtr Target memory location being incremented. + * @param delta The amount being incremented. + * @return The new incremented value. + */ +MBED_INLINE_IF_EX uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta); + +/** \copydoc core_util_atomic_incr_u8 */ +MBED_INLINE_IF_EX uint16_t core_util_atomic_incr_u16(volatile uint16_t *valuePtr, uint16_t delta); + +/** \copydoc core_util_atomic_incr_u8 */ +MBED_INLINE_IF_EX uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta); + +/** \copydoc core_util_atomic_incr_u8 */ +uint64_t core_util_atomic_incr_u64(volatile uint64_t *valuePtr, uint64_t delta); + +/** \copydoc core_util_atomic_incr_u8 */ +MBED_FORCEINLINE int8_t core_util_atomic_incr_s8(volatile int8_t *valuePtr, int8_t delta); + +/** \copydoc core_util_atomic_incr_u8 */ +MBED_FORCEINLINE int16_t core_util_atomic_incr_s16(volatile int16_t *valuePtr, int16_t delta); + +/** \copydoc core_util_atomic_incr_u8 */ +MBED_FORCEINLINE int32_t core_util_atomic_incr_s32(volatile int32_t *valuePtr, int32_t delta); + +/** \copydoc core_util_atomic_incr_u8 */ +MBED_FORCEINLINE int64_t core_util_atomic_incr_s64(volatile int64_t *valuePtr, int64_t delta); + +/** \copydoc core_util_atomic_incr_u8 */ +inline void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta); + +/** + * Atomic decrement. + * @param valuePtr Target memory location being decremented. + * @param delta The amount being decremented. + * @return The new decremented value. + */ +MBED_INLINE_IF_EX uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t delta); + +/** \copydoc core_util_atomic_decr_u8 */ +MBED_INLINE_IF_EX uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t delta); + +/** \copydoc core_util_atomic_decr_u8 */ +MBED_INLINE_IF_EX uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta); + +/** \copydoc core_util_atomic_decr_u8 */ +uint64_t core_util_atomic_decr_u64(volatile uint64_t *valuePtr, uint64_t delta); + +/** \copydoc core_util_atomic_decr_u8 */ +MBED_FORCEINLINE int8_t core_util_atomic_decr_s8(volatile int8_t *valuePtr, int8_t delta); + +/** \copydoc core_util_atomic_decr_u8 */ +MBED_FORCEINLINE int16_t core_util_atomic_decr_s16(volatile int16_t *valuePtr, int16_t delta); + +/** \copydoc core_util_atomic_decr_u8 */ +MBED_FORCEINLINE int32_t core_util_atomic_decr_s32(volatile int32_t *valuePtr, int32_t delta); + +/** \copydoc core_util_atomic_decr_u8 */ +MBED_FORCEINLINE int64_t core_util_atomic_decr_s64(volatile int64_t *valuePtr, int64_t delta); + +/** \copydoc core_util_atomic_decr_u8 */ +inline void *core_util_atomic_decr_ptr(void *volatile *valuePtr, ptrdiff_t delta); + +/** + * Atomic add. + * @param valuePtr Target memory location being modified. + * @param arg The argument for the addition. + * @return The original value. + */ +MBED_INLINE_IF_EX uint8_t core_util_atomic_fetch_add_u8(volatile uint8_t *valuePtr, uint8_t arg); + +/** \copydoc core_util_atomic_fetch_add_u8 + * @param order memory ordering constraint + */ +MBED_FORCEINLINE uint8_t core_util_atomic_fetch_add_explicit_u8(volatile uint8_t *valuePtr, uint8_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_add_u8 */ +MBED_INLINE_IF_EX uint16_t core_util_atomic_fetch_add_u16(volatile uint16_t *valuePtr, uint16_t arg); + +/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ +MBED_FORCEINLINE uint16_t core_util_atomic_fetch_add_explicit_u16(volatile uint16_t *valuePtr, uint16_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_add_u8 */ +MBED_INLINE_IF_EX uint32_t core_util_atomic_fetch_add_u32(volatile uint32_t *valuePtr, uint32_t arg); + +/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ +MBED_FORCEINLINE uint32_t core_util_atomic_fetch_add_explicit_u32(volatile uint32_t *valuePtr, uint32_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_add_u8 */ +uint64_t core_util_atomic_fetch_add_u64(volatile uint64_t *valuePtr, uint64_t arg); + +/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ +MBED_FORCEINLINE uint64_t core_util_atomic_fetch_add_explicit_u64(volatile uint64_t *valuePtr, uint64_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_add_u8 */ +MBED_FORCEINLINE int8_t core_util_atomic_fetch_add_s8(volatile int8_t *valuePtr, int8_t arg); + +/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ +MBED_FORCEINLINE int8_t core_util_atomic_fetch_add_explicit_s8(volatile int8_t *valuePtr, int8_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_add_u8 */ +MBED_FORCEINLINE int16_t core_util_atomic_fetch_add_s16(volatile int16_t *valuePtr, int16_t arg); + +/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ +MBED_FORCEINLINE int16_t core_util_atomic_fetch_add_explicit_s16(volatile int16_t *valuePtr, int16_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_add_u8 */ +MBED_FORCEINLINE int32_t core_util_atomic_fetch_add_s32(volatile int32_t *valuePtr, int32_t arg); + +/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ +MBED_FORCEINLINE int32_t core_util_atomic_fetch_add_explicit_s32(volatile int32_t *valuePtr, int32_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_add_u8 */ +MBED_FORCEINLINE int64_t core_util_atomic_fetch_add_s64(volatile int64_t *valuePtr, int64_t arg); + +/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ +MBED_FORCEINLINE int64_t core_util_atomic_fetch_add_explicit_s64(volatile int64_t *valuePtr, int64_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_add_u8 */ +MBED_FORCEINLINE void *core_util_atomic_fetch_add_ptr(void *volatile *valuePtr, ptrdiff_t arg); + +/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ +MBED_FORCEINLINE void *core_util_atomic_fetch_add_explicit_ptr(void *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order); + +/** + * Atomic subtract. + * @param valuePtr Target memory location being modified. + * @param arg The argument for the subtraction. + * @return The original value. + */ +MBED_INLINE_IF_EX uint8_t core_util_atomic_fetch_sub_u8(volatile uint8_t *valuePtr, uint8_t arg); + +/** \copydoc core_util_atomic_fetch_sub_u8 + * @param order memory ordering constraint + */ +MBED_FORCEINLINE uint8_t core_util_atomic_fetch_sub_explicit_u8(volatile uint8_t *valuePtr, uint8_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_sub_u8 */ +MBED_INLINE_IF_EX uint16_t core_util_atomic_fetch_sub_u16(volatile uint16_t *valuePtr, uint16_t arg); + +/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ +MBED_FORCEINLINE uint16_t core_util_atomic_fetch_sub_explicit_u16(volatile uint16_t *valuePtr, uint16_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_sub_u8 */ +MBED_INLINE_IF_EX uint32_t core_util_atomic_fetch_sub_u32(volatile uint32_t *valuePtr, uint32_t arg); + +/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ +MBED_FORCEINLINE uint32_t core_util_atomic_fetch_sub_explicit_u32(volatile uint32_t *valuePtr, uint32_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_sub_u8 */ +uint64_t core_util_atomic_fetch_sub_u64(volatile uint64_t *valuePtr, uint64_t arg); + +/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ +MBED_FORCEINLINE uint64_t core_util_atomic_fetch_sub_explicit_u64(volatile uint64_t *valuePtr, uint64_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_sub_u8 */ +MBED_FORCEINLINE int8_t core_util_atomic_fetch_sub_s8(volatile int8_t *valuePtr, int8_t arg); + +/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ +MBED_FORCEINLINE int8_t core_util_atomic_fetch_sub_explicit_s8(volatile int8_t *valuePtr, int8_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_sub_u8 */ +MBED_FORCEINLINE int16_t core_util_atomic_fetch_sub_s16(volatile int16_t *valuePtr, int16_t arg); + +/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ +MBED_FORCEINLINE int16_t core_util_atomic_fetch_sub_explicit_s16(volatile int16_t *valuePtr, int16_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_sub_u8 */ +MBED_FORCEINLINE int32_t core_util_atomic_fetch_sub_s32(volatile int32_t *valuePtr, int32_t arg); + +/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ +MBED_FORCEINLINE int32_t core_util_atomic_fetch_sub_explicit_s32(volatile int32_t *valuePtr, int32_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_sub_u8 */ +MBED_FORCEINLINE int64_t core_util_atomic_fetch_sub_s64(volatile int64_t *valuePtr, int64_t arg); + +/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ +MBED_FORCEINLINE int64_t core_util_atomic_fetch_sub_explicit_s64(volatile int64_t *valuePtr, int64_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_sub_u8 */ +MBED_FORCEINLINE void *core_util_atomic_fetch_sub_ptr(void *volatile *valuePtr, ptrdiff_t arg); + +/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ +MBED_FORCEINLINE void *core_util_atomic_fetch_sub_explicit_ptr(void *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order); + +/** + * Atomic bitwise and. + * @param valuePtr Target memory location being modified. + * @param arg The argument for the bitwise operation. + * @return The original value. + */ +MBED_INLINE_IF_EX uint8_t core_util_atomic_fetch_and_u8(volatile uint8_t *valuePtr, uint8_t arg); + +/** \copydoc core_util_atomic_fetch_and_u8 + * @param order memory ordering constraint + */ +MBED_FORCEINLINE uint8_t core_util_atomic_fetch_and_explicit_u8(volatile uint8_t *valuePtr, uint8_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_and_u8 */ +MBED_INLINE_IF_EX uint16_t core_util_atomic_fetch_and_u16(volatile uint16_t *valuePtr, uint16_t arg); + +/** \copydoc core_util_atomic_fetch_and_explicit_u8 */ +MBED_FORCEINLINE uint16_t core_util_atomic_fetch_and_explicit_u16(volatile uint16_t *valuePtr, uint16_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_and_u8 */ +MBED_INLINE_IF_EX uint32_t core_util_atomic_fetch_and_u32(volatile uint32_t *valuePtr, uint32_t arg); + +/** \copydoc core_util_atomic_fetch_and_explicit_u8 */ +MBED_FORCEINLINE uint32_t core_util_atomic_fetch_and_explicit_u32(volatile uint32_t *valuePtr, uint32_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_and_u8 */ +uint64_t core_util_atomic_fetch_and_u64(volatile uint64_t *valuePtr, uint64_t arg); + +/** \copydoc core_util_atomic_fetch_and_explicit_u8 */ +MBED_FORCEINLINE uint64_t core_util_atomic_fetch_and_explicit_u64(volatile uint64_t *valuePtr, uint64_t arg, mbed_memory_order order); + +/** + * Atomic bitwise inclusive or. + * @param valuePtr Target memory location being modified. + * @param arg The argument for the bitwise operation. + * @return The original value. + */ +MBED_INLINE_IF_EX uint8_t core_util_atomic_fetch_or_u8(volatile uint8_t *valuePtr, uint8_t arg); + +/** \copydoc core_util_atomic_fetch_or_u8 + * @param order memory ordering constraint + */ +MBED_FORCEINLINE uint8_t core_util_atomic_fetch_or_explicit_u8(volatile uint8_t *valuePtr, uint8_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_or_u8 */ +MBED_INLINE_IF_EX uint16_t core_util_atomic_fetch_or_u16(volatile uint16_t *valuePtr, uint16_t arg); + +/** \copydoc core_util_atomic_fetch_or_explicit_u8 */ +MBED_FORCEINLINE uint16_t core_util_atomic_fetch_or_explicit_u16(volatile uint16_t *valuePtr, uint16_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_or_u8 */ +MBED_INLINE_IF_EX uint32_t core_util_atomic_fetch_or_u32(volatile uint32_t *valuePtr, uint32_t arg); + +/** \copydoc core_util_atomic_fetch_or_explicit_u8 */ +MBED_FORCEINLINE uint32_t core_util_atomic_fetch_or_explicit_u32(volatile uint32_t *valuePtr, uint32_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_or_u8 */ +uint64_t core_util_atomic_fetch_or_u64(volatile uint64_t *valuePtr, uint64_t arg); + +/** \copydoc core_util_atomic_fetch_or_explicit_u8 */ +MBED_FORCEINLINE uint64_t core_util_atomic_fetch_or_explicit_u64(volatile uint64_t *valuePtr, uint64_t arg, mbed_memory_order order); + +/** + * Atomic bitwise exclusive or. + * @param valuePtr Target memory location being modified. + * @param arg The argument for the bitwise operation. + * @return The original value. + */ +MBED_INLINE_IF_EX uint8_t core_util_atomic_fetch_xor_u8(volatile uint8_t *valuePtr, uint8_t arg); + +/** \copydoc core_util_atomic_fetch_xor_u8 + * @param order memory ordering constraint + */ +MBED_FORCEINLINE uint8_t core_util_atomic_fetch_xor_explicit_u8(volatile uint8_t *valuePtr, uint8_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_xor_u8 */ +MBED_INLINE_IF_EX uint16_t core_util_atomic_fetch_xor_u16(volatile uint16_t *valuePtr, uint16_t arg); + +/** \copydoc core_util_atomic_fetch_xor_explicit_u8 */ +MBED_FORCEINLINE uint16_t core_util_atomic_fetch_xor_explicit_u16(volatile uint16_t *valuePtr, uint16_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_xor_u8 */ +MBED_INLINE_IF_EX uint32_t core_util_atomic_fetch_xor_u32(volatile uint32_t *valuePtr, uint32_t arg); + +/** \copydoc core_util_atomic_fetch_xor_explicit_u8 */ +MBED_FORCEINLINE uint32_t core_util_atomic_fetch_xor_explicit_u32(volatile uint32_t *valuePtr, uint32_t arg, mbed_memory_order order); + +/** \copydoc core_util_atomic_fetch_xor_u8 */ +uint64_t core_util_atomic_fetch_xor_u64(volatile uint64_t *valuePtr, uint64_t arg); + +/** \copydoc core_util_atomic_fetch_xor_explicit_u8 */ +MBED_FORCEINLINE uint64_t core_util_atomic_fetch_xor_explicit_u64(volatile uint64_t *valuePtr, uint64_t arg, mbed_memory_order order); + +#ifdef __cplusplus +} // extern "C" + +#include + +// For each operation, two overloaded templates: +// * one for non-pointer types, which has implementations based on the +// u8/u16/u32/u64/s8/s16/s32/s64/bool functions above. No base implementation. +// * one for any pointer type, generically implemented based on ptr function above. +// +// Templates use standard C/C++ naming - old incr/decr/cas forms are not provided. +// +// The `type_identity_t` used here means "same type as T", blocking template +// argument deduction. It forces type selection based on the type of the actual pointer +// to the atomic. If just `T` was used, the following would be ambiguous: +// core_util_atomic_store(&my_uint8_t, 1) - it wouldn't be able to select between T +// being uint8_t and int. + +/** \copydoc core_util_atomic_load_u8 */ +template T core_util_atomic_load(const volatile T *valuePtr) noexcept; +/** \copydoc core_util_atomic_load_u8 */ +template T core_util_atomic_load(const T *valuePtr) noexcept; +/** \copydoc core_util_atomic_store_u8 */ +template void core_util_atomic_store(volatile T *valuePtr, mstd::type_identity_t desiredValue) noexcept; +/** \copydoc core_util_atomic_store_u8 */ +template void core_util_atomic_store(T *valuePtr, mstd::type_identity_t desiredValue) noexcept; +/** \copydoc core_util_atomic_exchange_u8 */ +template T core_util_atomic_exchange(volatile T *ptr, mstd::type_identity_t desiredValue) noexcept; +/** \copydoc core_util_atomic_cas_u8 */ +template bool core_util_atomic_compare_exchange_strong(volatile T *ptr, mstd::type_identity_t *expectedCurrentValue, mstd::type_identity_t desiredValue) noexcept; +/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ +template bool core_util_atomic_compare_exchange_weak(volatile T *ptr, mstd::type_identity_t *expectedCurrentValue, mstd::type_identity_t desiredValue) noexcept; +/** \copydoc core_util_fetch_add_u8 */ +template T core_util_atomic_fetch_add(volatile T *valuePtr, mstd::type_identity_t arg) noexcept; +/** \copydoc core_util_fetch_sub_u8 */ +template T core_util_atomic_fetch_sub(volatile T *valuePtr, mstd::type_identity_t arg) noexcept; +/** \copydoc core_util_fetch_and_u8 */ +template T core_util_atomic_fetch_and(volatile T *valuePtr, mstd::type_identity_t arg) noexcept; +/** \copydoc core_util_fetch_or_u8 */ +template T core_util_atomic_fetch_or(volatile T *valuePtr, mstd::type_identity_t arg) noexcept; +/** \copydoc core_util_fetch_xor_u8 */ +template T core_util_atomic_fetch_xor(volatile T *valuePtr, mstd::type_identity_t arg) noexcept; + +/** \copydoc core_util_atomic_load_explicit_u8 */ +template T core_util_atomic_load_explicit(const volatile T *valuePtr, mbed_memory_order order) noexcept; +/** \copydoc core_util_atomic_load_explicit_u8 */ +template T core_util_atomic_load_explicit(const T *valuePtr, mbed_memory_order order) noexcept; +/** \copydoc core_util_atomic_store_explicit_u8 */ +template void core_util_atomic_store_explicit(volatile T *valuePtr, mstd::type_identity_t desiredValue, mbed_memory_order order) noexcept; +/** \copydoc core_util_atomic_store_explicit_u8 */ +template void core_util_atomic_store_explicit(T *valuePtr, mstd::type_identity_t desiredValue, mbed_memory_order order) noexcept; +/** \copydoc core_util_atomic_exchange_explicit_u8 */ +template T core_util_atomic_exchange_explicit(volatile T *ptr, mstd::type_identity_t desiredValue, mbed_memory_order order) noexcept; +/** \copydoc core_util_atomic_cas_explicit_u8 */ +template bool core_util_atomic_compare_exchange_strong_explicit(volatile T *ptr, mstd::type_identity_t *expectedCurrentValue, mstd::type_identity_t desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept; +/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ +template bool core_util_atomic_compare_exchange_weak_explicit(volatile T *ptr, mstd::type_identity_t *expectedCurrentValue, mstd::type_identity_t desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept; +/** \copydoc core_util_fetch_add_explicit_u8 */ +template T core_util_atomic_fetch_add_explicit(volatile T *valuePtr, mstd::type_identity_t arg, mbed_memory_order order) noexcept; +/** \copydoc core_util_fetch_sub_explicit_u8 */ +template T core_util_atomic_fetch_sub_explicit(volatile T *valuePtr, mstd::type_identity_t arg, mbed_memory_order order) noexcept; +/** \copydoc core_util_fetch_and_explicit_u8 */ +template T core_util_atomic_fetch_and_explicit(volatile T *valuePtr, mstd::type_identity_t arg, mbed_memory_order order) noexcept; +/** \copydoc core_util_fetch_or_explicit_u8 */ +template T core_util_atomic_fetch_or_explicit(volatile T *valuePtr, mstd::type_identity_t arg, mbed_memory_order order) noexcept; +/** \copydoc core_util_fetch_xor_explicit_u8 */ +template T core_util_atomic_fetch_xor_explicit(volatile T *valuePtr, mstd::type_identity_t arg, mbed_memory_order order) noexcept; + +/** \copydoc core_util_atomic_load_ptr */ +template inline T *core_util_atomic_load(T *const volatile *valuePtr) noexcept; +/** \copydoc core_util_atomic_load_ptr */ +template inline T *core_util_atomic_load(T *const *valuePtr) noexcept; +/** \copydoc core_util_atomic_store_ptr */ +template inline void core_util_atomic_store(T *volatile *valuePtr, mstd::type_identity_t *desiredValue) noexcept; +/** \copydoc core_util_atomic_store_ptr */ +template inline void core_util_atomic_store(T **valuePtr, mstd::type_identity_t *desiredValue) noexcept; +/** \copydoc core_util_atomic_exchange_ptr */ +template inline T *core_util_atomic_exchange(T *volatile *valuePtr, mstd::type_identity_t *desiredValue) noexcept; +/** \copydoc core_util_atomic_cas_ptr */ +template inline bool core_util_atomic_compare_exchange_strong(T *volatile *ptr, mstd::type_identity_t **expectedCurrentValue, mstd::type_identity_t *desiredValue) noexcept; +/** \copydoc core_util_atomic_compare_exchange_weak_ptr */ +template inline bool core_util_atomic_compare_exchange_weak(T *volatile *ptr, mstd::type_identity_t **expectedCurrentValue, mstd::type_identity_t *desiredValue) noexcept; +/** \copydoc core_util_fetch_add_ptr */ +template inline T *core_util_atomic_fetch_add(T *volatile *valuePtr, ptrdiff_t arg) noexcept; +/** \copydoc core_util_fetch_sub_ptr */ +template inline T *core_util_atomic_fetch_sub(T *volatile *valuePtr, ptrdiff_t arg) noexcept; + +/** \copydoc core_util_atomic_load_explicit_ptr */ +template inline T *core_util_atomic_load_explicit(T *const volatile *valuePtr, mbed_memory_order order) noexcept; +/** \copydoc core_util_atomic_load_explicit_ptr */ +template inline T *core_util_atomic_load_explicit(T *const *valuePtr, mbed_memory_order order) noexcept; +/** \copydoc core_util_atomic_store_explicit_ptr */ +template inline void core_util_atomic_store_explicit(T *volatile *valuePtr, mstd::type_identity_t *desiredValue, mbed_memory_order order) noexcept; +/** \copydoc core_util_atomic_store_explicit_ptr */ +template inline void core_util_atomic_store_explicit(T **valuePtr, mstd::type_identity_t *desiredValue, mbed_memory_order order) noexcept; +/** \copydoc core_util_atomic_exchange_explicit_ptr */ +template inline T *core_util_atomic_exchange_explicit(T *volatile *valuePtr, mstd::type_identity_t *desiredValue, mbed_memory_order order) noexcept; +/** \copydoc core_util_atomic_cas_explicit_ptr */ +template inline bool core_util_atomic_compare_exchange_strong_explicit(T *volatile *ptr, mstd::type_identity_t **expectedCurrentValue, mstd::type_identity_t *desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept; +/** \copydoc core_util_atomic_compare_exchange_weak_explicit_ptr */ +template inline bool core_util_atomic_compare_exchange_weak_explicit(T *volatile *ptr, mstd::type_identity_t **expectedCurrentValue, mstd::type_identity_t *desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept; +/** \copydoc core_util_fetch_add_explicit_ptr */ +template inline T *core_util_atomic_fetch_add_explicit(T *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) noexcept; +/** \copydoc core_util_fetch_sub_explicit_ptr */ +template inline T *core_util_atomic_fetch_sub_explicit(T *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) noexcept; + +#endif // __cplusplus + +/**@}*/ + +/**@}*/ + +/* Hide the implementation away */ +#include "platform/internal/mbed_atomic_impl.h" + +#endif // __MBED_UTIL_ATOMICL_H__ + + + diff --git a/platform/include/platform/mbed_chrono.h b/platform/include/platform/mbed_chrono.h new file mode 100644 index 0000000..210d64b --- /dev/null +++ b/platform/include/platform/mbed_chrono.h @@ -0,0 +1,128 @@ + +/* + * Copyright (c) 2015-2019, 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 __MBED_CHRONO_H__ +#define __MBED_CHRONO_H__ + +#include "mbed_toolchain.h" +#include +#include +#include +#include + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_chrono chrono utilities + * + * Additions and variations of std::chrono + * + * - unsigned 32-bit variants of standard signed 64-bit duration types + * - centiseconds and deciseconds + * @{ + */ +namespace mbed { + +/* Extensions declared in mbed::chrono, following pattern of std::chrono */ +namespace chrono { + +/* Add deciseconds and centiseconds - may be + * useful to use lower precision when not messing with templating. + */ +using deciseconds = std::chrono::duration; +using centiseconds = std::chrono::duration; + +/** 32-bit microsecond duration type + * + * Standard std::chrono::microseconds is signed 64-bit. For some purposes + * it's more efficient to process small times as 32-bit. And when doing so, + * as we likely need to worry about wrapping, use of an unsigned + * value to process modulo 2**32 is appropriate. + */ +using microseconds_u32 = std::chrono::duration; + +/** 32-bit millisecond duration type + * + * Standard std::chrono::milliseconds is signed 64-bit. For some purposes + * it's more efficient to process times as 32-bit. And when doing so, + * as we likely need to worry about wrapping, use of an unsigned + * value to process modulo 2**32 is appropriate. + */ +using milliseconds_u32 = std::chrono::duration; + +} // namespace chrono + +inline namespace literals { + +inline namespace chrono_literals { + +/** User-defined literal for deciseconds (1/10 of a second) + * + * Useful in case we might change kernel tick frequency to be slower - with tick frequency 1000Hz, it is + * possible to assign 500ms to a KernelClock::duration, but that would fail at slower rates. + * + * Example use: + * + * using namespace mbed::chrono_literals; + * + * ThisThread::sleep_for(5_ds); + */ +constexpr chrono::deciseconds operator "" _ds(unsigned long long x) +{ + chrono::deciseconds::rep val = static_cast(x); + assert(val >= 0 && static_cast(val) == x); + return chrono::deciseconds(val); +} + +/** User-defined literal for centiseconds (1/100 of a second) + * + * Useful in case we might change kernel tick frequency to be slower - with tick frequency 1000Hz, it is + * possible to assign 500ms to a KernelClock::duration, but that would fail at slower rates. + * + * Example use: + * + * using namespace mbed::chrono_literals; + * + * ThisThread::sleep_for(1_cs); + */ +constexpr chrono::centiseconds operator "" _cs(unsigned long long x) +{ + chrono::centiseconds::rep val = static_cast(x); + assert(val >= 0 && static_cast(val) == x); + return chrono::centiseconds(val); +} + +} // inline namespace chrono_literals + +} // inline namespace literals + +namespace chrono { + +using namespace chrono_literals; + +} // namespace chrono + +} // namespace mbed + +/**@}*/ + +/**@}*/ + +#endif // __MBED_CHRONO_H__ + diff --git a/platform/include/platform/mbed_critical.h b/platform/include/platform/mbed_critical.h new file mode 100644 index 0000000..9213794 --- /dev/null +++ b/platform/include/platform/mbed_critical.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015-2019, 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 __MBED_UTIL_CRITICAL_H__ +#define __MBED_UTIL_CRITICAL_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup platform-public-api */ +/** @{*/ +/** + * \defgroup platform_critical critical section function + * @{ + */ + +/** Determine the current interrupts enabled state + * + * 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 underlying implementation + * differs. + * @return true if interrupts are enabled, false otherwise + */ +bool core_util_are_interrupts_enabled(void); + +/** Determine if this code is executing from an interrupt + * + * 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 underlying implementation + * differs. + * @return true if in an isr, false otherwise + */ +bool core_util_is_isr_active(void); + +/** Mark the start of a critical section + * + * This function should be called to mark the start of a critical section of code. + * @note + * NOTES: + * 1) The use of this style of critical section is targetted at C based implementations. + * 2) These critical sections can be nested. + * 3) The interrupt enable state on entry to the first critical section (of a nested set, or single + * section) will be preserved on exit from the section. + * 4) This implementation will currently only work on code running in privileged mode. + */ +void core_util_critical_section_enter(void); + +/** Mark the end of a critical section + * + * This function should be called to mark the end of a critical section of code. + * @note + * NOTES: + * 1) The use of this style of critical section is targetted at C based implementations. + * 2) These critical sections can be nested. + * 3) The interrupt enable state on entry to the first critical section (of a nested set, or single + * section) will be preserved on exit from the section. + * 4) This implementation will currently only work on code running in privileged mode. + */ +void core_util_critical_section_exit(void); + +/** + * Determine if we are currently in a critical section + * + * @return true if in a critical section, false otherwise. + */ +bool core_util_in_critical_section(void); + +/**@}*/ + +/**@}*/ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __MBED_UTIL_CRITICAL_H__ diff --git a/platform/include/platform/mbed_debug.h b/platform/include/platform/mbed_debug.h new file mode 100644 index 0000000..ed5e60d --- /dev/null +++ b/platform/include/platform/mbed_debug.h @@ -0,0 +1,85 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_DEBUG_H +#define MBED_DEBUG_H +#if DEVICE_STDIO_MESSAGES +#include +#include +#endif +#include "platform/mbed_toolchain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_debug Debug functions + * @{ + */ + +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 + * + * @param format printf-style format string, followed by variables + */ +static inline void debug(const char *format, ...) +{ +#if DEVICE_STDIO_MESSAGES && !defined(NDEBUG) + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); +#endif +} + + +/** Conditionally output a debug message + * + * NOTE: If the condition is constant false (== 0) and the compiler optimization + * level is greater than 0, then the whole function will be compiled away. + * + * @param condition output only if condition is true (!= 0) + * @param format printf-style format string, followed by variables + */ +static inline void debug_if(int condition, const char *format, ...) +{ +#if DEVICE_STDIO_MESSAGES && !defined(NDEBUG) + if (condition) { + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + } +#endif +} + + +#ifdef __cplusplus +} +#endif + +#endif + +/**@}*/ + +/**@}*/ + diff --git a/platform/include/platform/mbed_enum_flags.h b/platform/include/platform/mbed_enum_flags.h new file mode 100644 index 0000000..edeee31 --- /dev/null +++ b/platform/include/platform/mbed_enum_flags.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2020 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 MBED_SCOPED_ENUM_FLAGS_H +#define MBED_SCOPED_ENUM_FLAGS_H + +#include + +#define ENUM_FLAG_BITWISE_OPERATOR(T, OP) \ +inline constexpr T operator OP(T lhs, T rhs) \ +{ \ + return T (static_cast>(lhs) OP \ + static_cast>(rhs)); \ +} + + +#define ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, OP) \ +inline constexpr T &operator OP(T &lhs, T rhs) \ +{ \ + return lhs = lhs OP rhs; \ +} + + +/** + * @brief Applies bitwise operators to a enum class defined elsewhere. + * + * @param T The enum class typename + * + * This macro applies the bitwise negate, AND, OR, XOR operators and the + * corresponding assignment operators to an existing enum class. The macro + * uses underlying type traits to convert back and forth. + * + * Usage: + * @code + * external_enum.h: + * + * enum class SpokenLanguages : uint8_t { + * Sindarin = (1 << 0), + * Westron = (1 << 1), + * Rohirric = (1 << 2), + * BlackSpeech = (1 << 3) + * }; + * + * my_code.cpp: + * + * #include "mbed_enum_flags.h" + * #include "external_enum.h" + * + * MBED_ENUM_FLAG_APPLY_OPERATORS(SpokenLanguages); + * + * SpokenLanguages gandalf = SpokenLanguages::Sindarin | SpokenLanguages::Westron | + * SpokenLanguages::Rohirric | SpokenLanguages::BlackSpeech; + * @endcode + * + */ +#define MBED_ENUM_FLAG_APPLY_OPERATORS(T) \ + inline constexpr T operator ~(T lhs) \ + { \ + return T(~static_cast>(lhs)); \ + } \ + ENUM_FLAG_BITWISE_OPERATOR(T, |) \ + ENUM_FLAG_BITWISE_OPERATOR(T, ^) \ + ENUM_FLAG_BITWISE_OPERATOR(T, &) \ + ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, |=) \ + ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, ^=) \ + ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, &=) \ + static_assert(true, "This assert true is to require a semicolon to terminate the macro.") \ + + +/** @private + * + * @brief Bitwise definition macro with underlying type. + * + * Not part of public API. Do not use directly. Use MBED_SCOPED_ENUM_FLAGS instead. + */ +#define SCOPED_ENUM_FLAGS_TYPED(T, UNDERLYING_T) \ + enum class T : UNDERLYING_T; \ + MBED_ENUM_FLAG_APPLY_OPERATORS(T); \ + enum class T : UNDERLYING_T + +/** @private + * + * @brief Bitwise definition macro with default underlying type. + * + * Not part of public API. Do not use directly. Use MBED_SCOPED_ENUM_FLAGS instead. + */ +#define SCOPED_ENUM_FLAGS_UNTYPED(T) \ + enum class T; \ + MBED_ENUM_FLAG_APPLY_OPERATORS(T); \ + enum class T + +#define MBED_SCOPED_ENUM_FLAGS_CHOOSER(_1, _2, NAME, ...) NAME + +/** + * @brief Creates an enum class with bitwise operator overloads. + * + * @param T The enum class typename + * @param UNDERLYING_T Optional: specify the underlying integral type. If + * omitted, the enum class underlying type will be the + * compiler default. + * + * This macro creates both the enum class type and defines NOT, AND, OR, and + * XOR operators. It also defines as three bitwise assignment operators, AND, + * OR, and XOR. It allows for the scoped nature of the enum class, but adds back + * the bitwise operators that were missing. + * + * This macro uses type traits to convert between the underlying type and back + * again for the bitwise operations. + * + * Usage: + * @code + * my_nice_enum_class_with_flags.h: + * + * MBED_SCOPED_ENUM_FLAGS(MyFlagName) { + * HasEars = (1 << 0), + * HasFur = (1 << 1), + * LaysEggs = (1 << 2), + * Meows = (1 << 3), + * Polydactyl = (1 << 30) + * }; + * + * MBED_SCOPED_ENUM_FLAGS(SpokenLanguages, uint8_t) { + * Sindarin = (1 << 0), + * Westron = (1 << 1), + * Rohirric = (1 << 2), + * BlackSpeech = (1 << 3) + * }; + * + * my_enum_class_flag_consumer.h: + * + * class EnumEater { + * public: + * EnumEater(MyFlagName flags) : _flags(flags) {} + * + * static MyFlagName DefaultFlags = MyFlagName::HasEars | MyFlagName::Meows; + * + * bool is_cat() const { + * return ((_flags & DefaultFlags) == DefaultFlags) && + * ((_flags & MyFlagName::LaysEggs) == MyFlagName()); + * } + * private: + * MyFlagName _flags; + * }; + * + * bool is_Gandalf(SpokenLanguages flags) { + * return flags == (SpokenLanguages::Sindarin | SpokenLanguages::Westron | + * SpokenLanguages::SpeaksRohirric | SpokenLanguages::BlackSpeech); + * } + * @endcode + * + */ +#define MBED_SCOPED_ENUM_FLAGS(...) MBED_SCOPED_ENUM_FLAGS_CHOOSER(__VA_ARGS__, SCOPED_ENUM_FLAGS_TYPED, SCOPED_ENUM_FLAGS_UNTYPED)(__VA_ARGS__) + +#endif //MBED_SCOPED_ENUM_FLAGS_H diff --git a/platform/include/platform/mbed_error.h b/platform/include/platform/mbed_error.h new file mode 100644 index 0000000..5c01bda --- /dev/null +++ b/platform/include/platform/mbed_error.h @@ -0,0 +1,1183 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_ERROR_H +#define MBED_ERROR_H + +#include +#include "platform/mbed_retarget.h" +#include "platform/mbed_toolchain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_error Error functions + * @{ + */ + +/** Define this macro to include filenames in error context. For release builds, do not include filename to save memory. + * MBED_PLATFORM_CONF_ERROR_FILENAME_CAPTURE_ENABLED + */ + +/** Define this macro to enable error history + * MBED_PLATFORM_CONF_ERROR_HIST_ENABLED + */ + +#ifndef MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN +#define MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN 16 +#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_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 +#endif + +#define MBED_ERROR_STATUS_CODE_MASK (0x0000FFFF) +#define MBED_ERROR_STATUS_CODE_UNSHIFTED_MASK (0x0000FFFF) +#define MBED_ERROR_STATUS_CODE_POS (0) +#define MBED_ERROR_STATUS_CODE_FIELD_SIZE (16) + +#define MBED_ERROR_STATUS_MODULE_MASK (0x00FF0000) +#define MBED_ERROR_STATUS_MODULE_UNSHIFTED_MASK (0x000000FF) +#define MBED_ERROR_STATUS_MODULE_POS (16) +#define MBED_ERROR_STATUS_MODULE_FIELD_SIZE (8) + +#define MBED_ERROR_STATUS_TYPE_MASK (0x60000000) +#define MBED_ERROR_STATUS_TYPE_UNSHIFTED_MASK (0x00000003) +#define MBED_ERROR_STATUS_TYPE_POS (29) +#define MBED_ERROR_STATUS_TYPE_FIELD_SIZE (2) + +/* mbed_error_status_t Status Encoding */ +//|31(1 bit) Always Negative|30-29(2 bits) |28-24 | 23-16(8 bits) | 15-0(16 bits) | +//|-1 |TYPE |(unused/reserved) | MODULE TYPE | ERROR CODE | + +#define MAKE_MBED_ERROR(type, module, error_code) (mbed_error_status_t) \ + ((0x80000000) | \ + ((mbed_error_status_t) (error_code & MBED_ERROR_STATUS_CODE_UNSHIFTED_MASK) << MBED_ERROR_STATUS_CODE_POS) | \ + ((mbed_error_status_t) (module & MBED_ERROR_STATUS_MODULE_UNSHIFTED_MASK) << MBED_ERROR_STATUS_MODULE_POS) | \ + ((mbed_error_status_t) (type & MBED_ERROR_STATUS_TYPE_UNSHIFTED_MASK) << MBED_ERROR_STATUS_TYPE_POS)) + +#define MBED_GET_ERROR_TYPE( error_status ) ((error_status & MBED_ERROR_STATUS_TYPE_MASK) >> MBED_ERROR_STATUS_TYPE_POS) +#define MBED_GET_ERROR_MODULE( error_status ) ((error_status & MBED_ERROR_STATUS_MODULE_MASK) >> MBED_ERROR_STATUS_MODULE_POS) +#define MBED_GET_ERROR_CODE( error_status ) (int)((MBED_GET_ERROR_TYPE( error_status ) == MBED_ERROR_TYPE_POSIX)?(-error_status):((error_status & MBED_ERROR_STATUS_CODE_MASK) >> MBED_ERROR_STATUS_CODE_POS)) + +/** mbed_error_status_t description + * + * mbed_error_status_t type represents the error status values under MbedOS. mbed_error_status_t values are signed integers and always be negative.\n + * Internally its encoded as below with bit-fields representing error type, module and error code:\n\n + * mbed_error_status_t Status Encoding:\n + * + \verbatim + | 31 Always Negative | 30-29(2 bits) | 28-24 | 23-16(8 bits) | 15-0(16 bits) | + | -1 | TYPE | (unused/reserved) | MODULE TYPE | ERROR CODE | + \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 + * 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 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. + */ +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. + * @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). + * + */ +#define MBED_DEFINE_POSIX_ERROR( error_name, error_code ) \ + MBED_ERROR_CODE_##error_name = error_code, \ + MBED_ERROR_##error_name = -(MBED_POSIX_ERROR_BASE + error_code) + +/** + * Macro for defining a System error status. This macro is used to define System 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 256 and 4096(inclusive). + * + */ +#define MBED_DEFINE_SYSTEM_ERROR( error_name, error_code ) \ + MBED_ERROR_CODE_##error_name = MBED_SYSTEM_ERROR_BASE + error_code, \ + MBED_ERROR_##error_name = MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, MBED_MODULE_UNKNOWN, MBED_ERROR_CODE_##error_name) + +/** + * Macro for defining a Custom error status. This macro is used to define custom 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 4097 and 65535(inclusive). + * + */ +#define MBED_DEFINE_CUSTOM_ERROR( error_name, error_code ) \ + MBED_ERROR_CODE_##error_name = MBED_CUSTOM_ERROR_BASE + error_code, \ + MBED_ERROR_##error_name = MAKE_MBED_ERROR(MBED_ERROR_TYPE_CUSTOM, MBED_MODULE_UNKNOWN, MBED_ERROR_CODE_##error_name) + + +/** + * Macros for setting a system warning. These macros will log the error, Its a wrapper for calling mbed_warning API. + * There are 2 versions of this macro. MBED_WARNING takes status and message. MBED_WARNING1 takes an additional context specific argument + * @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. + * + * @code + * + * MBED_WARNING( ERROR_INVALID_SIZE, "MyDriver: Invalid size in read" ) + * MBED_WARNING1( ERROR_INVALID_SIZE, "MyDriver: Invalid size in read", size_val ) + * + * @endcode + * @note The macro calls mbed_warning API with filename and line number info without caller explicitly passing them. + * Since this macro is a wrapper for mbed_warning API callers should process the return value from this macro which is the return value from calling mbed_error API. + * + */ +#ifdef NDEBUG +#define MBED_WARNING1( error_status, error_msg, error_value ) mbed_warning( error_status, (const char *)NULL, (uint32_t)error_value, NULL, 0 ) +#define MBED_WARNING( error_status, error_msg ) mbed_warning( error_status, (const char *)NULL, (uint32_t)0, NULL, 0 ) +#else //NDEBUG +#if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED +#define MBED_WARNING1( error_status, error_msg, error_value ) mbed_warning( error_status, (const char *)error_msg, (uint32_t)error_value, (const char *)MBED_FILENAME, __LINE__ ) +#define MBED_WARNING( error_status, error_msg ) mbed_warning( error_status, (const char *)error_msg, (uint32_t)0 , (const char *)MBED_FILENAME, __LINE__ ) +#else //MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED +#define MBED_WARNING1( error_status, error_msg, error_value ) mbed_warning( error_status, (const char *)error_msg, (uint32_t)error_value, NULL, 0 ) +#define MBED_WARNING( error_status, error_msg ) mbed_warning( error_status, (const char *)error_msg, (uint32_t)0, NULL, 0 ) +#endif +#endif + +/** + * Macros for setting a fatal system error. These macros will log the error, prints the error report and halts the system. Its a wrapper for calling mbed_error API. + * There are 2 versions of this macro. MBED_ERROR takes status and message. MBED_ERROR1 takes an additional context specific argument + * @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 Does not return + * + * @code + * + * MBED_ERROR( MBED_ERROR_MUTEX_LOCK_FAILED, "MyDriver: Can't lock driver Mutex" ) + * MBED_ERROR1( MBED_ERROR_MUTEX_LOCK_FAILED, "MyDriver: Can't lock driver Mutex", &my_mutex ) + * + * @endcode + * @note The macro calls mbed_error API with filename and line number info without caller explicitly passing them. + * Since this macro is a wrapper for mbed_error API callers should process the return value from this macro which is the return value from calling mbed_error API. + * + */ +#ifdef NDEBUG +#define MBED_ERROR1( error_status, error_msg, error_value ) mbed_error( error_status, (const char *)NULL, (uint32_t)error_value, NULL, 0 ) +#define MBED_ERROR( error_status, error_msg ) mbed_error( error_status, (const char *)NULL, (uint32_t)0 , NULL, 0 ) +#else //NDEBUG +#if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED +#define MBED_ERROR1( error_status, error_msg, error_value ) mbed_error( error_status, (const char *)error_msg, (uint32_t)error_value, (const char *)MBED_FILENAME, __LINE__ ) +#define MBED_ERROR( error_status, error_msg ) mbed_error( error_status, (const char *)error_msg, (uint32_t)0 , (const char *)MBED_FILENAME, __LINE__ ) +#else //MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED +#define MBED_ERROR1( error_status, error_msg, error_value ) mbed_error( error_status, (const char *)error_msg, (uint32_t)error_value, NULL, 0 ) +#define MBED_ERROR( error_status, error_msg ) mbed_error( error_status, (const char *)error_msg, (uint32_t)0 , NULL, 0 ) +#endif +#endif + +//Error Type definition +/** mbed_error_type_t definition + * @note + * This enumeration defines the Error types supported. The value of these enum values will be encoded into mbed_error_status_t TYPE field.\n + * 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 + * + */ +typedef enum _mbed_error_type_t { + MBED_ERROR_TYPE_SYSTEM = 0, + MBED_ERROR_TYPE_CUSTOM = 1, + //2 is reserved + //Use 3 for POSIX because we are mapping -1 to -255 to POSIX error codes + //and thus we must use 3 to match the type bits in error status representation which are from 0xFFFFFFFF to 0xFFFFFF00 + MBED_ERROR_TYPE_POSIX = 3 +} mbed_error_type_t; + +//Module type/id definitions +/** mbed_module_type_t definition + * @note + * This enumeration defines the module types. The value of these enum values will be encoded into mbed_error_status_t MODULE field.\n\n + * See mbed_error_status_t description for more info.\n + * MBED_MODULE_UNKNOWN - This module type can be used if caller of the mbed_error/mbed_warning doesn't know who is the actual originator of the error.\n + * Other module values can be used to provide more info on who/where the error originated from.\n\n + * For example, if I2C driver is the component originating the error you can use MBED_MODULE_DRIVER_I2C to provide more info.\n + * Its used in call to MBED_MAKE_ERROR/MBED_MAKE_SYSTEM_ERROR/MBED_MAKE_CUSTOM_ERROR macros.\n + * + * @code + * Example: mbed_error_status_t i2c_driver_error = MBED_MAKE_ERROR( MBED_MODULE_DRIVER_I2C, MBED_ERROR_CONFIG_UNSUPPORTED ); + * @endcode + * + * @note + * \n Below are the module code mappings:\n + \verbatim + 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_NETWORK_STATS 24 Network Statistics + + MBED_MODULE_UNKNOWN 255 Unknown module + \endverbatim + * + */ +typedef enum _mbed_module_type { + MBED_MODULE_APPLICATION = 0, + MBED_MODULE_PLATFORM, + MBED_MODULE_KERNEL, + MBED_MODULE_NETWORK_STACK, + MBED_MODULE_HAL, + MBED_MODULE_MEMORY_SUBSYSTEM, + MBED_MODULE_FILESYSTEM, + MBED_MODULE_BLOCK_DEVICE, + MBED_MODULE_DRIVER, + MBED_MODULE_DRIVER_SERIAL, + MBED_MODULE_DRIVER_RTC, + MBED_MODULE_DRIVER_I2C, + MBED_MODULE_DRIVER_SPI, + MBED_MODULE_DRIVER_GPIO, + MBED_MODULE_DRIVER_ANALOG, + MBED_MODULE_DRIVER_DIGITAL, + MBED_MODULE_DRIVER_CAN, + MBED_MODULE_DRIVER_ETHERNET, + MBED_MODULE_DRIVER_CRC, + MBED_MODULE_DRIVER_PWM, + MBED_MODULE_DRIVER_QSPI, + MBED_MODULE_DRIVER_USB, + MBED_MODULE_DRIVER_WATCHDOG, + MBED_MODULE_TARGET_SDK, + MBED_MODULE_BLE, + MBED_MODULE_NETWORK_STATS, + /* Add More entities here as required */ + + MBED_MODULE_UNKNOWN = 255, + MBED_MODULE_MAX = MBED_MODULE_UNKNOWN +} mbed_module_type_t; + +//Use MBED_SUCCESS(=0) or any positive number for successful returns +#define MBED_SUCCESS 0 + +#define MBED_POSIX_ERROR_BASE 0 +#define MBED_SYSTEM_ERROR_BASE 256 +#define MBED_CUSTOM_ERROR_BASE 4096 + +//Error Code definitions +/** 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 + * + * @note + * 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 + * 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 POSIX error codes and the description:\n + * \verbatim + EPERM 1 Operation not permitted + ENOENT 2 No such file or directory + ESRCH 3 No such process + EINTR 4 Interrupted system call + EIO 5 I/O error + ENXIO 6 No such device or address + E2BIG 7 Argument list too long + ENOEXEC 8 Exec format error + EBADF 9 Bad file number + ECHILD 10 No child processes + EAGAIN 11 Try again + ENOMEM 12 Out of memory + EACCES 13 Permission denied + EFAULT 14 Bad address + ENOTBLK 15 Block device required + EBUSY 16 Device or resource busy + EEXIST 17 File exists + EXDEV 18 Cross-device link + ENODEV 19 No such device + ENOTDIR 20 Not a directory + EISDIR 21 Is a directory + EINVAL 22 Invalid argument + ENFILE 23 File table overflow + EMFILE 24 Too many open files + ENOTTY 25 Not a typewriter + ETXTBSY 26 Text file busy + EFBIG 27 File too large + ENOSPC 28 No space left on device + ESPIPE 29 Illegal seek + EROFS 30 Read-only file system + EMLINK 31 Too many links + EPIPE 32 Broken pipe + EDOM 33 Math argument out of domain of func + ERANGE 34 Math result not representable + EDEADLK 35 Resource deadlock would occur + ENAMETOOLONG 36 File name too long + ENOLCK 37 No record locks available + ENOSYS 38 Function not implemented + ENOTEMPTY 39 Directory not empty + ELOOP 40 Too many symbolic links encountered + EWOULDBLOCK EAGAIN Operation would block + ENOMSG 42 No message of desired type + EIDRM 43 Identifier removed + ECHRNG 44 Channel number out of range + EL2NSYNC 45 Level 2 not synchronized + EL3HLT 46 Level 3 halted + EL3RST 47 Level 3 reset + ELNRNG 48 Link number out of range + EUNATCH 49 Protocol driver not attached + ENOCSI 50 No CSI structure available + EL2HLT 51 Level 2 halted + EBADE 52 Invalid exchange + EBADR 53 Invalid request descriptor + EXFULL 54 Exchange full + ENOANO 55 No anode + EBADRQC 56 Invalid request code + EBADSLT 57 Invalid slot + EDEADLOCK EDEADLK Resource deadlock would occur + EBFONT 59 Bad font file format + ENOSTR 60 Device not a stream + ENODATA 61 No data available + ETIME 62 Timer expired + ENOSR 63 Out of streams resources + ENONET 64 Machine is not on the network + ENOPKG 65 Package not installed + EREMOTE 66 Object is remote + ENOLINK 67 Link has been severed + EADV 68 Advertise error + ESRMNT 69 Srmount error + ECOMM 70 Communication error on send + EPROTO 71 Protocol error + EMULTIHOP 72 Multihop attempted + EDOTDOT 73 RFS specific error + EBADMSG 74 Not a data message + EOVERFLOW 75 Value too large for defined data type + ENOTUNIQ 76 Name not unique on network + EBADFD 77 File descriptor in bad state + EREMCHG 78 Remote address changed + ELIBACC 79 Can not access a needed shared library + ELIBBAD 80 Accessing a corrupted shared library + ELIBSCN 81 .lib section in a.out corrupted + ELIBMAX 82 Attempting to link in too many shared libraries + ELIBEXEC 83 Cannot exec a shared library directly + EILSEQ 84 Illegal byte sequence + ERESTART 85 Interrupted system call should be restarted + ESTRPIPE 86 Streams pipe error + EUSERS 87 Too many users + ENOTSOCK 88 Socket operation on non-socket + EDESTADDRREQ 89 Destination address required + EMSGSIZE 90 Message too long + EPROTOTYPE 91 Protocol wrong type for socket + ENOPROTOOPT 92 Protocol not available + EPROTONOSUPPORT 93 Protocol not supported + ESOCKTNOSUPPORT 94 Socket type not supported + EOPNOTSUPP 95 Operation not supported on transport endpoint + EPFNOSUPPORT 96 Protocol family not supported + EAFNOSUPPORT 97 Address family not supported by protocol + EADDRINUSE 98 Address already in use + EADDRNOTAVAIL 99 Cannot assign requested address + ENETDOWN 100 Network is down + ENETUNREACH 101 Network is unreachable + ENETRESET 102 Network dropped connection because of reset + ECONNABORTED 103 Software caused connection abort + ECONNRESET 104 Connection reset by peer + ENOBUFS 105 No buffer space available + EISCONN 106 Transport endpoint is already connected + ENOTCONN 107 Transport endpoint is not connected + ESHUTDOWN 108 Cannot send after transport endpoint shutdown + ETOOMANYREFS 109 Too many references: cannot splice + ETIMEDOUT 110 Connection timed out + ECONNREFUSED 111 Connection refused + EHOSTDOWN 112 Host is down + EHOSTUNREACH 113 No route to host + EALREADY 114 Operation already in progress + EINPROGRESS 115 Operation now in progress + ESTALE 116 Stale NFS file handle + EUCLEAN 117 Structure needs cleaning + ENOTNAM 118 Not a XENIX named type file + ENAVAIL 119 No XENIX semaphores available + EISNAM 120 Is a named type file + EREMOTEIO 121 Remote I/O error + EDQUOT 122 Quota exceeded + ENOMEDIUM 123 No medium found + EMEDIUMTYPE 124 Wrong medium type + ECANCELED 125 Operation Canceled + ENOKEY 126 Required key not available + EKEYEXPIRED 127 Key has expired + EKEYREVOKED 128 Key has been revoked + EKEYREJECTED 129 Key was rejected by service + EOWNERDEAD 130 Owner died + ENOTRECOVERABLE 131 State not recoverable + \endverbatim + * + * @note + * MbedOS System Error codes are defined using the macro MBED_DEFINE_SYSTEM_ERROR\n + * For example MBED_DEFINE_SYSTEM_ERROR( INVALID_ARGUMENT ,1 ) macro defines the following values:\n + * ERROR_CODE_INVALID_ARGUMENT = MBED_SYSTEM_ERROR_BASE+1\n + * ERROR_INVALID_ARGUMENT = MAKE_MBED_ERROR(ERROR_TYPE_SYSTEM, MBED_MODULE_UNKNOWN, ERROR_CODE_INVALID_ARGUMENT)\n + * Its effectively equivalent to:\n + * ERROR_CODE_INVALID_ARGUMENT = 1\n + * ERROR_INVALID_ARGUMENT = 0x80FF0001\n (Note that MODULE field is set to MBED_MODULE_UNKNOWN) + * New System Error codes should be defined using MBED_DEFINE_SYSTEM_ERROR macro and must have an unique error code value\n + * passed as the second argument in the MBED_DEFINE_SYSTEM_ERROR macro.\n\n + * Below are the Mbed System error codes and the description: + * \verbatim + UNKNOWN 256 Unknown error + INVALID_ARGUMENT 257 Invalid Argument + INVALID_DATA 258 Invalid data + INVALID_FORMAT 259 Invalid format + INVALID_INDEX 260 Invalid Index + INVALID_SIZE 261 Invalid Size + INVALID_OPERATION 262 Invalid Operation + NOT_FOUND 263 Not Found + ACCESS_DENIED 264 Access Denied + NOT_SUPPORTED 265 Not supported + BUFFER_FULL 266 Buffer Full + MEDIA_FULL 267 Media/Disk Full + ALREADY_IN_USE 268 Already in use + TIMEOUT 269 Timeout error + NOT_READY 270 Not Ready + FAILED_OPERATION 271 Requested Operation failed + OPERATION_PROHIBITED 272 Operation prohibited + OPERATION_ABORTED 273 Operation failed + WRITE_PROTECTED 274 Attempt to write to write-protected resource + NO_RESPONSE 275 No response + SEMAPHORE_LOCK_FAILED 276 Semaphore lock failed + MUTEX_LOCK_FAILED 277 Mutex lock 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 + CLOSE_FAILED 282 Close failed + READ_FAILED 283 Read failed + WRITE_FAILED 284 Write failed + INITIALIZATION_FAILED 285 Initialization failed + BOOT_FAILURE 286 Boot failure + OUT_OF_MEMORY 287 Out of memory + OUT_OF_RESOURCES 288 Out of resources + ALLOC_FAILED 289 Alloc failed + FREE_FAILED 290 Free failed + OVERFLOW 291 Overflow error + UNDERFLOW 292 Underflow error + STACK_OVERFLOW 293 Stack overflow error + ISR_QUEUE_OVERFLOW 294 ISR queue overflow + TIMER_QUEUE_OVERFLOW 295 Timer Queue overflow + CLIB_SPACE_UNAVAILABLE 296 Standard library error - Space unavailable + CLIB_EXCEPTION 297 Standard library error - Exception + CLIB_MUTEX_INIT_FAILURE 298 Standard library error - Mutex Init failure + CREATE_FAILED 299 Create failed + DELETE_FAILED 300 Delete failed + THREAD_CREATE_FAILED 301 Thread Create failed + THREAD_DELETE_FAILED 302 Thread Delete failed + PROHIBITED_IN_ISR_CONTEXT 303 Operation Prohibited in ISR context + PINMAP_INVALID 304 Pinmap Invalid + RTOS_EVENT 305 Unknown Rtos Error + RTOS_THREAD_EVENT 306 Rtos Thread Error + RTOS_MUTEX_EVENT 307 Rtos Mutex Error + RTOS_SEMAPHORE_EVENT 308 Rtos Semaphore Error + RTOS_MEMORY_POOL_EVENT 309 Rtos Memory Pool Error + RTOS_TIMER_EVENT 310 Rtos Timer Error + RTOS_EVENT_FLAGS_EVENT 311 Rtos Event flags Error + RTOS_MESSAGE_QUEUE_EVENT 312 Rtos Message queue Error + DEVICE_BUSY 313 Device Busy + CONFIG_UNSUPPORTED 314 Configuration not supported + CONFIG_MISMATCH 315 Configuration mismatch + 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 + ASSERTION_FAILED 324 Assertion Failed + AUTHENTICATION_FAILED 325 Authentication Failed + RBP_AUTHENTICATION_FAILED 326 Rollback Protect Authentication Failed + \endverbatim + * + * @note + * Custom Error codes can be defined using the macro DEFINE_CUSTOM_ERROR\n + * This is mainly meant to capture non-generic error codes specific to a device. + * For example DEFINE_CUSTOM_ERROR( MY_CUSTOM_ERROR ,1 ) macro defines the following values:\n + * ERROR_CODE_MY_CUSTOM_ERROR = MBED_CUSTOM_ERROR_BASE+1\n + * ERROR_MY_CUSTOM_ERROR = MAKE_MBED_ERROR(ERROR_TYPE_CUSTOM, MBED_MODULE_UNKNOWN, ERROR_CODE_MY_CUSTOM_ERROR)\n + * Its effectively equivalent to:\n + * ERROR_CODE_MY_CUSTOM_ERROR = 4097\n + * ERROR_MY_CUSTOM_ERROR = 0xA0FF1001\n (Note that MODULE field is set to MBED_MODULE_UNKNOWN) \n\n + * + * @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 + * 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. + * + * 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 + * much more efficient. + * + * @note + * **Searching for error codes in mbed-os source tree:** \n + * If you get an error report as below which you want to search for in mbed-os source tree, first take note of "Error Code" number. \n + * For example, the below error report has an error code of \b 259. Find the error name associated with the error code and in this case its \b INVALID_FORMAT. \n + * Use that error name(\b INVALID_FORMAT) to search the source tree for code locations setting that specific error code. \n + * If the Error module reported is not 255(which indicates unknown module), you can also use that to narrow down to the specific component reporting the error. + * See mbed_module_type_t enum above for module mapping. \n + * + * \verbatim + ++ MbedOS Error Info ++ + 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 + //defintions in mbed_retarget.h + // Error Name Error Code + MBED_DEFINE_POSIX_ERROR(EPERM, EPERM), /* 1 Operation not permitted */ + MBED_DEFINE_POSIX_ERROR(ENOENT, ENOENT), /* 2 No such file or directory */ + MBED_DEFINE_POSIX_ERROR(ESRCH, ESRCH), /* 3 No such process */ + MBED_DEFINE_POSIX_ERROR(EINTR, EINTR), /* 4 Interrupted system call */ + MBED_DEFINE_POSIX_ERROR(EIO, EIO), /* 5 I/O error */ + MBED_DEFINE_POSIX_ERROR(ENXIO, ENXIO), /* 6 No such device or address */ + MBED_DEFINE_POSIX_ERROR(E2BIG, E2BIG), /* 7 Argument list too long */ + MBED_DEFINE_POSIX_ERROR(ENOEXEC, ENOEXEC), /* 8 Exec format error */ + MBED_DEFINE_POSIX_ERROR(EBADF, EBADF), /* 9 Bad file number */ + MBED_DEFINE_POSIX_ERROR(ECHILD, ECHILD), /* 10 No child processes */ + MBED_DEFINE_POSIX_ERROR(EAGAIN, EAGAIN), /* 11 Try again */ + MBED_DEFINE_POSIX_ERROR(ENOMEM, ENOMEM), /* 12 Out of memory */ + MBED_DEFINE_POSIX_ERROR(EACCES, EACCES), /* 13 Permission denied */ + MBED_DEFINE_POSIX_ERROR(EFAULT, EFAULT), /* 14 Bad address */ + MBED_DEFINE_POSIX_ERROR(ENOTBLK, ENOTBLK), /* 15 Block device required */ + MBED_DEFINE_POSIX_ERROR(EBUSY, EBUSY), /* 16 Device or resource busy */ + MBED_DEFINE_POSIX_ERROR(EEXIST, EEXIST), /* 17 File exists */ + MBED_DEFINE_POSIX_ERROR(EXDEV, EXDEV), /* 18 Cross-device link */ + MBED_DEFINE_POSIX_ERROR(ENODEV, ENODEV), /* 19 No such device */ + MBED_DEFINE_POSIX_ERROR(ENOTDIR, ENOTDIR), /* 20 Not a directory */ + MBED_DEFINE_POSIX_ERROR(EISDIR, EISDIR), /* 21 Is a directory */ + MBED_DEFINE_POSIX_ERROR(EINVAL, EINVAL), /* 22 Invalid argument */ + MBED_DEFINE_POSIX_ERROR(ENFILE, ENFILE), /* 23 File table overflow */ + MBED_DEFINE_POSIX_ERROR(EMFILE, EMFILE), /* 24 Too many open files */ + MBED_DEFINE_POSIX_ERROR(ENOTTY, ENOTTY), /* 25 Not a typewriter */ + MBED_DEFINE_POSIX_ERROR(ETXTBSY, ETXTBSY), /* 26 Text file busy */ + MBED_DEFINE_POSIX_ERROR(EFBIG, EFBIG), /* 27 File too large */ + MBED_DEFINE_POSIX_ERROR(ENOSPC, ENOSPC), /* 28 No space left on device */ + MBED_DEFINE_POSIX_ERROR(ESPIPE, ESPIPE), /* 29 Illegal seek */ + MBED_DEFINE_POSIX_ERROR(EROFS, EROFS), /* 30 Read-only file system */ + MBED_DEFINE_POSIX_ERROR(EMLINK, EMLINK), /* 31 Too many links */ + MBED_DEFINE_POSIX_ERROR(EPIPE, EPIPE), /* 32 Broken pipe */ + MBED_DEFINE_POSIX_ERROR(EDOM, EDOM), /* 33 Math argument out of domain of func */ + MBED_DEFINE_POSIX_ERROR(ERANGE, ERANGE), /* 34 Math result not representable */ + MBED_DEFINE_POSIX_ERROR(EDEADLK, EDEADLK), /* 35 Resource deadlock would occur */ + MBED_DEFINE_POSIX_ERROR(ENAMETOOLONG, ENAMETOOLONG), /* 36 File name too long */ + MBED_DEFINE_POSIX_ERROR(ENOLCK, ENOLCK), /* 37 No record locks available */ + MBED_DEFINE_POSIX_ERROR(ENOSYS, ENOSYS), /* 38 Function not implemented */ + MBED_DEFINE_POSIX_ERROR(ENOTEMPTY, ENOTEMPTY), /* 39 Directory not empty */ + MBED_DEFINE_POSIX_ERROR(ELOOP, ELOOP), /* 40 Too many symbolic links encountered */ + MBED_DEFINE_POSIX_ERROR(EWOULDBLOCK, EAGAIN), /* EAGAIN Operation would block */ + MBED_DEFINE_POSIX_ERROR(ENOMSG, ENOMSG), /* 42 No message of desired type */ + MBED_DEFINE_POSIX_ERROR(EIDRM, EIDRM), /* 43 Identifier removed */ + MBED_DEFINE_POSIX_ERROR(ECHRNG, ECHRNG), /* 44 Channel number out of range */ + MBED_DEFINE_POSIX_ERROR(EL2NSYNC, EL2NSYNC), /* 45 Level 2 not synchronized */ + MBED_DEFINE_POSIX_ERROR(EL3HLT, EL3HLT), /* 46 Level 3 halted */ + MBED_DEFINE_POSIX_ERROR(EL3RST, EL3RST), /* 47 Level 3 reset */ + MBED_DEFINE_POSIX_ERROR(ELNRNG, ELNRNG), /* 48 Link number out of range */ + MBED_DEFINE_POSIX_ERROR(EUNATCH, EUNATCH), /* 49 Protocol driver not attached */ + MBED_DEFINE_POSIX_ERROR(ENOCSI, ENOCSI), /* 50 No CSI structure available */ + MBED_DEFINE_POSIX_ERROR(EL2HLT, EL2HLT), /* 51 Level 2 halted */ + MBED_DEFINE_POSIX_ERROR(EBADE, EBADE), /* 52 Invalid exchange */ + MBED_DEFINE_POSIX_ERROR(EBADR, EBADR), /* 53 Invalid request descriptor */ + MBED_DEFINE_POSIX_ERROR(EXFULL, EXFULL), /* 54 Exchange full */ + MBED_DEFINE_POSIX_ERROR(ENOANO, ENOANO), /* 55 No anode */ + MBED_DEFINE_POSIX_ERROR(EBADRQC, EBADRQC), /* 56 Invalid request code */ + MBED_DEFINE_POSIX_ERROR(EBADSLT, EBADSLT), /* 57 Invalid slot */ + MBED_DEFINE_POSIX_ERROR(EDEADLOCK, EDEADLK), /* EDEADLK Resource deadlock would occur */ + MBED_DEFINE_POSIX_ERROR(EBFONT, EBFONT), /* 59 Bad font file format */ + MBED_DEFINE_POSIX_ERROR(ENOSTR, ENOSTR), /* 60 Device not a stream */ + MBED_DEFINE_POSIX_ERROR(ENODATA, ENODATA), /* 61 No data available */ + MBED_DEFINE_POSIX_ERROR(ETIME, ETIME), /* 62 Timer expired */ + MBED_DEFINE_POSIX_ERROR(ENOSR, ENOSR), /* 63 Out of streams resources */ + MBED_DEFINE_POSIX_ERROR(ENONET, ENONET), /* 64 Machine is not on the network */ + MBED_DEFINE_POSIX_ERROR(ENOPKG, ENOPKG), /* 65 Package not installed */ + MBED_DEFINE_POSIX_ERROR(EREMOTE, EREMOTE), /* 66 Object is remote */ + MBED_DEFINE_POSIX_ERROR(ENOLINK, ENOLINK), /* 67 Link has been severed */ + MBED_DEFINE_POSIX_ERROR(EADV, EADV), /* 68 Advertise error */ + MBED_DEFINE_POSIX_ERROR(ESRMNT, ESRMNT), /* 69 Srmount error */ + MBED_DEFINE_POSIX_ERROR(ECOMM, ECOMM), /* 70 Communication error on send */ + MBED_DEFINE_POSIX_ERROR(EPROTO, EPROTO), /* 71 Protocol error */ + MBED_DEFINE_POSIX_ERROR(EMULTIHOP, EMULTIHOP), /* 72 Multihop attempted */ + MBED_DEFINE_POSIX_ERROR(EDOTDOT, EDOTDOT), /* 73 RFS specific error */ + MBED_DEFINE_POSIX_ERROR(EBADMSG, EBADMSG), /* 74 Not a data message */ + MBED_DEFINE_POSIX_ERROR(EOVERFLOW, EOVERFLOW), /* 75 Value too large for defined data type */ + MBED_DEFINE_POSIX_ERROR(ENOTUNIQ, ENOTUNIQ), /* 76 Name not unique on network */ + MBED_DEFINE_POSIX_ERROR(EBADFD, EBADFD), /* 77 File descriptor in bad state */ + MBED_DEFINE_POSIX_ERROR(EREMCHG, EREMCHG), /* 78 Remote address changed */ + MBED_DEFINE_POSIX_ERROR(ELIBACC, ELIBACC), /* 79 Can not access a needed shared library */ + MBED_DEFINE_POSIX_ERROR(ELIBBAD, ELIBBAD), /* 80 Accessing a corrupted shared library */ + MBED_DEFINE_POSIX_ERROR(ELIBSCN, ELIBSCN), /* 81 .lib section in a.out corrupted */ + MBED_DEFINE_POSIX_ERROR(ELIBMAX, ELIBMAX), /* 82 Attempting to link in too many shared libraries */ + MBED_DEFINE_POSIX_ERROR(ELIBEXEC, ELIBEXEC), /* 83 Cannot exec a shared library directly */ + MBED_DEFINE_POSIX_ERROR(EILSEQ, EILSEQ), /* 84 Illegal byte sequence */ + MBED_DEFINE_POSIX_ERROR(ERESTART, ERESTART), /* 85 Interrupted system call should be restarted */ + MBED_DEFINE_POSIX_ERROR(ESTRPIPE, ESTRPIPE), /* 86 Streams pipe error */ + MBED_DEFINE_POSIX_ERROR(EUSERS, EUSERS), /* 87 Too many users */ + MBED_DEFINE_POSIX_ERROR(ENOTSOCK, ENOTSOCK), /* 88 Socket operation on non-socket */ + MBED_DEFINE_POSIX_ERROR(EDESTADDRREQ, EDESTADDRREQ), /* 89 Destination address required */ + MBED_DEFINE_POSIX_ERROR(EMSGSIZE, EMSGSIZE), /* 90 Message too long */ + MBED_DEFINE_POSIX_ERROR(EPROTOTYPE, EPROTOTYPE), /* 91 Protocol wrong type for socket */ + MBED_DEFINE_POSIX_ERROR(ENOPROTOOPT, ENOPROTOOPT), /* 92 Protocol not available */ + MBED_DEFINE_POSIX_ERROR(EPROTONOSUPPORT, EPROTONOSUPPORT), /* 93 Protocol not supported */ + MBED_DEFINE_POSIX_ERROR(ESOCKTNOSUPPORT, ESOCKTNOSUPPORT), /* 94 Socket type not supported */ + MBED_DEFINE_POSIX_ERROR(EOPNOTSUPP, EOPNOTSUPP), /* 95 Operation not supported on transport endpoint */ + MBED_DEFINE_POSIX_ERROR(EPFNOSUPPORT, EPFNOSUPPORT), /* 96 Protocol family not supported */ + MBED_DEFINE_POSIX_ERROR(EAFNOSUPPORT, EAFNOSUPPORT), /* 97 Address family not supported by protocol */ + MBED_DEFINE_POSIX_ERROR(EADDRINUSE, EADDRINUSE), /* 98 Address already in use */ + MBED_DEFINE_POSIX_ERROR(EADDRNOTAVAIL, EADDRNOTAVAIL), /* 99 Cannot assign requested address */ + MBED_DEFINE_POSIX_ERROR(ENETDOWN, ENETDOWN), /* 100 Network is down */ + MBED_DEFINE_POSIX_ERROR(ENETUNREACH, ENETUNREACH), /* 101 Network is unreachable */ + MBED_DEFINE_POSIX_ERROR(ENETRESET, ENETRESET), /* 102 Network dropped connection because of reset */ + MBED_DEFINE_POSIX_ERROR(ECONNABORTED, ECONNABORTED), /* 103 Software caused connection abort */ + MBED_DEFINE_POSIX_ERROR(ECONNRESET, ECONNRESET), /* 104 Connection reset by peer */ + MBED_DEFINE_POSIX_ERROR(ENOBUFS, ENOBUFS), /* 105 No buffer space available */ + MBED_DEFINE_POSIX_ERROR(EISCONN, EISCONN), /* 106 Transport endpoint is already connected */ + MBED_DEFINE_POSIX_ERROR(ENOTCONN, ENOTCONN), /* 107 Transport endpoint is not connected */ + MBED_DEFINE_POSIX_ERROR(ESHUTDOWN, ESHUTDOWN), /* 108 Cannot send after transport endpoint shutdown */ + MBED_DEFINE_POSIX_ERROR(ETOOMANYREFS, ETOOMANYREFS), /* 109 Too many references: cannot splice */ + MBED_DEFINE_POSIX_ERROR(ETIMEDOUT, ETIMEDOUT), /* 110 Connection timed out */ + MBED_DEFINE_POSIX_ERROR(ECONNREFUSED, ECONNREFUSED), /* 111 Connection refused */ + MBED_DEFINE_POSIX_ERROR(EHOSTDOWN, EHOSTDOWN), /* 112 Host is down */ + MBED_DEFINE_POSIX_ERROR(EHOSTUNREACH, EHOSTUNREACH), /* 113 No route to host */ + MBED_DEFINE_POSIX_ERROR(EALREADY, EALREADY), /* 114 Operation already in progress */ + MBED_DEFINE_POSIX_ERROR(EINPROGRESS, EINPROGRESS), /* 115 Operation now in progress */ + MBED_DEFINE_POSIX_ERROR(ESTALE, ESTALE), /* 116 Stale NFS file handle */ + MBED_DEFINE_POSIX_ERROR(EUCLEAN, EUCLEAN), /* 117 Structure needs cleaning */ + MBED_DEFINE_POSIX_ERROR(ENOTNAM, ENOTNAM), /* 118 Not a XENIX named type file */ + MBED_DEFINE_POSIX_ERROR(ENAVAIL, ENAVAIL), /* 119 No XENIX semaphores available */ + MBED_DEFINE_POSIX_ERROR(EISNAM, EISNAM), /* 120 Is a named type file */ + MBED_DEFINE_POSIX_ERROR(EREMOTEIO, EREMOTEIO), /* 121 Remote I/O error */ + MBED_DEFINE_POSIX_ERROR(EDQUOT, EDQUOT), /* 122 Quota exceeded */ + MBED_DEFINE_POSIX_ERROR(ENOMEDIUM, ENOMEDIUM), /* 123 No medium found */ + MBED_DEFINE_POSIX_ERROR(EMEDIUMTYPE, EMEDIUMTYPE), /* 124 Wrong medium type */ + MBED_DEFINE_POSIX_ERROR(ECANCELED, ECANCELED), /* 125 Operation Canceled */ + MBED_DEFINE_POSIX_ERROR(ENOKEY, ENOKEY), /* 126 Required key not available */ + MBED_DEFINE_POSIX_ERROR(EKEYEXPIRED, EKEYEXPIRED), /* 127 Key has expired */ + MBED_DEFINE_POSIX_ERROR(EKEYREVOKED, EKEYREVOKED), /* 128 Key has been revoked */ + MBED_DEFINE_POSIX_ERROR(EKEYREJECTED, EKEYREJECTED), /* 129 Key was rejected by service */ + MBED_DEFINE_POSIX_ERROR(EOWNERDEAD, EOWNERDEAD), /* 130 Owner died */ + MBED_DEFINE_POSIX_ERROR(ENOTRECOVERABLE, ENOTRECOVERABLE), /* 131 State not recoverable */ + + //Below are MBED SYSTEM ERROR CODE definitions + //MBED SYSTEM ERROR CODE definitions starts at offset MBED_SYSTEM_ERROR_BASE, see above. + // Error Name Error Offset Error Code + MBED_DEFINE_SYSTEM_ERROR(UNKNOWN, 0), /* 256 Unknown error */ + MBED_DEFINE_SYSTEM_ERROR(INVALID_ARGUMENT, 1), /* 257 Invalid Argument */ + 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 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 */ + MBED_DEFINE_SYSTEM_ERROR(UNSUPPORTED, 9), /* 265 Unsupported */ + MBED_DEFINE_SYSTEM_ERROR(BUFFER_FULL, 10), /* 266 Buffer Full */ + MBED_DEFINE_SYSTEM_ERROR(MEDIA_FULL, 11), /* 267 Media/Disk Full */ + MBED_DEFINE_SYSTEM_ERROR(ALREADY_IN_USE, 12), /* 268 Already in use */ + MBED_DEFINE_SYSTEM_ERROR(TIME_OUT, 13), /* 269 Timeout error */ + MBED_DEFINE_SYSTEM_ERROR(NOT_READY, 14), /* 270 Not Ready */ + MBED_DEFINE_SYSTEM_ERROR(FAILED_OPERATION, 15), /* 271 Requested Operation failed */ + MBED_DEFINE_SYSTEM_ERROR(OPERATION_PROHIBITED, 16), /* 272 Operation prohibited */ + 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 Semaphore lock failed */ + MBED_DEFINE_SYSTEM_ERROR(MUTEX_LOCK_FAILED, 21), /* 277 Mutex lock 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 */ + MBED_DEFINE_SYSTEM_ERROR(CLOSE_FAILED, 26), /* 282 Close failed */ + MBED_DEFINE_SYSTEM_ERROR(READ_FAILED, 27), /* 283 Read failed */ + MBED_DEFINE_SYSTEM_ERROR(WRITE_FAILED, 28), /* 284 Write failed */ + MBED_DEFINE_SYSTEM_ERROR(INITIALIZATION_FAILED, 29), /* 285 Initialization failed */ + MBED_DEFINE_SYSTEM_ERROR(BOOT_FAILURE, 30), /* 286 Boot failure */ + MBED_DEFINE_SYSTEM_ERROR(OUT_OF_MEMORY, 31), /* 287 Out of memory */ + MBED_DEFINE_SYSTEM_ERROR(OUT_OF_RESOURCES, 32), /* 288 Out of resources */ + MBED_DEFINE_SYSTEM_ERROR(ALLOC_FAILED, 33), /* 289 Alloc failed */ + MBED_DEFINE_SYSTEM_ERROR(FREE_FAILED, 34), /* 290 Free failed */ + MBED_DEFINE_SYSTEM_ERROR(OVERFLOW, 35), /* 291 Overflow error */ + MBED_DEFINE_SYSTEM_ERROR(UNDERFLOW, 36), /* 292 Underflow error */ + MBED_DEFINE_SYSTEM_ERROR(STACK_OVERFLOW, 37), /* 293 Stack overflow error */ + MBED_DEFINE_SYSTEM_ERROR(ISR_QUEUE_OVERFLOW, 38), /* 294 ISR queue overflow */ + MBED_DEFINE_SYSTEM_ERROR(TIMER_QUEUE_OVERFLOW, 39), /* 295 Timer Queue overflow */ + MBED_DEFINE_SYSTEM_ERROR(CLIB_SPACE_UNAVAILABLE, 40), /* 296 Standard library error - Space unavailable */ + MBED_DEFINE_SYSTEM_ERROR(CLIB_EXCEPTION, 41), /* 297 Standard library error - Exception */ + MBED_DEFINE_SYSTEM_ERROR(CLIB_MUTEX_INIT_FAILURE, 42), /* 298 Standard library error - Mutex Init failure */ + MBED_DEFINE_SYSTEM_ERROR(CREATE_FAILED, 43), /* 299 Create failed */ + MBED_DEFINE_SYSTEM_ERROR(DELETE_FAILED, 44), /* 300 Delete failed */ + MBED_DEFINE_SYSTEM_ERROR(THREAD_CREATE_FAILED, 45), /* 301 Thread Create failed */ + MBED_DEFINE_SYSTEM_ERROR(THREAD_DELETE_FAILED, 46), /* 302 Thread Delete failed */ + MBED_DEFINE_SYSTEM_ERROR(PROHIBITED_IN_ISR_CONTEXT, 47), /* 303 Operation Prohibited in ISR context */ + MBED_DEFINE_SYSTEM_ERROR(PINMAP_INVALID, 48), /* 304 Pinmap Invalid */ + MBED_DEFINE_SYSTEM_ERROR(RTOS_EVENT, 49), /* 305 Unknown Rtos Error */ + MBED_DEFINE_SYSTEM_ERROR(RTOS_THREAD_EVENT, 50), /* 306 Rtos Thread Error */ + MBED_DEFINE_SYSTEM_ERROR(RTOS_MUTEX_EVENT, 51), /* 307 Rtos Mutex Error */ + MBED_DEFINE_SYSTEM_ERROR(RTOS_SEMAPHORE_EVENT, 52), /* 308 Rtos Semaphore Error */ + MBED_DEFINE_SYSTEM_ERROR(RTOS_MEMORY_POOL_EVENT, 53), /* 309 Rtos Memory Pool Error */ + MBED_DEFINE_SYSTEM_ERROR(RTOS_TIMER_EVENT, 54), /* 310 Rtos Timer Error */ + MBED_DEFINE_SYSTEM_ERROR(RTOS_EVENT_FLAGS_EVENT, 55), /* 311 Rtos Event flags Error */ + MBED_DEFINE_SYSTEM_ERROR(RTOS_MESSAGE_QUEUE_EVENT, 56), /* 312 Rtos Message queue Error */ + 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 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 */ + MBED_DEFINE_SYSTEM_ERROR(USAGEFAULT_EXCEPTION, 64), /* 320 UsageFault exception*/ + 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 */ + MBED_DEFINE_SYSTEM_ERROR(AUTHENTICATION_FAILED, 69), /* 325 Authentication Failed */ + MBED_DEFINE_SYSTEM_ERROR(RBP_AUTHENTICATION_FAILED, 70), /* 326 Rollback Protection Authentication Failed */ + MBED_DEFINE_SYSTEM_ERROR(BLE_USE_INCOMPATIBLE_API, 71), /* 327 Concurrent use of incompatible versions of a BLE API */ + MBED_DEFINE_SYSTEM_ERROR(BLE_ILLEGAL_STATE, 72), /* 328 BLE stack entered illegal state */ + + //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 + + //MBED CUSTOM ERROR CODE definitions starts at offset MBED_CUSTOM_ERROR_BASE, see above. + /* Add More/Custom Error Codes here, See example below */ + //DEFINE_CUSTOM_ERROR( MY_CUSTOM_ERROR , 1 ), + +} mbed_error_code_t; + +/** mbed_error_ctx struct + * + * This struct captures the context information at the time of error.\n + * It primarily contains information about the thread where the error originated,\n + * filename/line number of the source file where the error occurred, a context specific error value(error_value)\n + * and the address where the error originated.\n + * + * @note + * Below are the members of mbed_error_ctx struct\n + * error_status mbed_error_status_t value for this error\n + * error_function_address Address where the error occurred\n + * thread_id ID of the thread which generated the error\n + * thread_entry_address Entry function of the thread which generated the error\n + * thread_stack_size Stack Size of the thread which generated the error\n + * thread_stack_mem Stack Top of the thread which generated the error\n + * thread_current_sp Current Stack Pointer of the thread which generated the error\n + * error_value A context/error specific value associated with this error\n + * error_filename Filename where the error originated\n + * error_line_number Line number in error_filename where the error originated\n + */ +typedef struct _mbed_error_ctx { + mbed_error_status_t error_status; + uint32_t error_address; + uint32_t error_value; + uint32_t thread_id; + uint32_t thread_entry_address; + uint32_t thread_stack_size; + uint32_t thread_stack_mem; + uint32_t thread_current_sp; +#ifdef MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN + char error_filename[MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN]; + uint32_t error_line_number; +#endif +#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED + int32_t error_reboot_count;//everytime we write this struct we increment this value by 1, irrespective of time between reboots. Note that the data itself might change, but everytime we reboot due to error we update this count by 1 + int32_t is_error_processed;//once this error is processed set this value to 1 + uint32_t crc_error_ctx;//crc_error_ctx should always be the last member in this struct +#endif +} mbed_error_ctx; + +/** To generate a fatal compile-time error, you can use the pre-processor #error directive. + * + * @param format C string that contains data stream to be printed. + * Code snippets below show valid format. + * + * @code + * #error "That shouldn't have happened!" + * @endcode + * + * If the compiler evaluates this line, it will report the error and stop the compile. + * + * For example, you could use this to check some user-defined compile-time variables: + * + * @code + * #define NUM_PORTS 7 + * #if (NUM_PORTS > 4) + * #error "NUM_PORTS must be less than 4" + * #endif + * @endcode + * + * Reporting Run-Time Errors: + * To generate a fatal run-time error, you can use the mbed error() function. + * + * @code + * error("That shouldn't have happened!"); + * @endcode + * + * If the mbed running the program executes this function, it will print the + * message via the USB serial port, and then die with the blue lights of death! + * + * The message can use printf-style formatting, so you can report variables in the + * message too. For example, you could use this to check a run-time condition: + * + * @code + * if(x >= 5) { + * error("expected x to be less than 5, but got %d", x); + * } + * @endcode + * + * + */ + +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 + * @param module Module generating the error code. If its unknown, pass MBED_MODULE_UNKNOWN. See mbed_module_type_t for module types. + * @param error_code The mbed_error_code_t code to be used in generating the mbed_error_status_t. See mbed_error_code_t for error codes. + * + * @code + * + * mbed_error_status_t driver_error = MBED_MAKE_SYSTEM_ERROR( MODULE_DRIVER_USB, MBED_ERROR_CODE_INITIALIZATION_FAILED ) + * + * @endcode + * @note This macro generate mbed_error_status_t-es with error type set to MBED_ERROR_TYPE_SYSTEM + * + */ +#define MBED_MAKE_SYSTEM_ERROR(module, error_code) MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, module, error_code) + +/** + * Call this Macro to generate a mbed_error_status_t value for a Custom error + * @param module Module generating the error code. If its unknown, pass MBED_MODULE_UNKNOWN. See mbed_module_type_t for module types. + * @param error_code The mbed_error_code_t code to be used in generating the mbed_error_status_t. See mbed_error_code_t for error codes. + * + * @code + * + * mbed_error_status_t custom_error = MBED_MAKE_CUSTOM_ERROR( MBED_MODULE_APPLICATION, 0xDEAD//16-bit custom error code ) + * + * @endcode + * @note This macro generate mbed_error_status_t-es with error type set to MBED_ERROR_TYPE_CUSTOM + * + */ +#define MBED_MAKE_CUSTOM_ERROR(module, error_code) MAKE_MBED_ERROR(MBED_ERROR_TYPE_CUSTOM, module, error_code) + +/** + * Call this Macro to generate a mbed_error_status_t value for a System error + * @param module Module generating the error code. If its unknown, pass MBED_MODULE_UNKNOWN. See mbed_module_type_t for module types. + * @param error_code The mbed_error_code_t code to be used in generating the mbed_error_status_t. See mbed_error_code_t for error codes. + * + * @code + * + * mbed_error_status_t new_error = MBED_MAKE_ERROR( MODULE_DRIVER_USB, MBED_ERROR_INITIALIZATION_FAILED ) + * + * @endcode + * @note This macro generate mbed_error_status_t-es with error type set to MBED_ERROR_TYPE_SYSTEM + * + */ +#define MBED_MAKE_ERROR(module, error_code) MBED_MAKE_SYSTEM_ERROR(module, error_code) + +/** + * 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_ctx Error context structure associated with this error. + * @return void + * + */ +typedef void (*mbed_error_hook_t)(const mbed_error_ctx *error_ctx); + +/** + * Callback/Error hook function. If application implementation needs to receive this callback when an error is reported, + * mbed_error_hook function should be overridden with custom implementation. 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_ctx Error context structure associated with this error. + * @return void + * + */ +void mbed_error_hook(const mbed_error_ctx *error_context); + +/** + * Callback function for reporting error context during boot up. When MbedOS error handling system detects a fatal error + * it will auto-reboot the system(if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED is enabled) after capturing the + * error info in special crash data RAM region. Once rebooted, MbedOS initialization routines will call this function with a pointer to + * the captured mbed_error_ctx structure. If application implementation needs to receive this callback, mbed_error_reboot_callback + * function should be overridden with custom implementation. By default it's defined as a WEAK function in mbed_error.c. + * Note that this callback will be invoked before the system starts executing main() function. So the implementation of + * the callback should be aware any resource limitations/availability of resources which are yet to be initialized by application main(). + * + * @param error_ctx Error context structure associated with this error. + * @return void + * + */ +void mbed_error_reboot_callback(mbed_error_ctx *error_context); + +/** + * Initialize error handling system, this is called by the mbed-os boot sequence. This is not required to be called by Application unless the boot sequence is overridden by the system implementation. + * NOTE: If MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED is enabled and if the current reboot count exceeds MBED_CONF_PLATFORM_ERROR_REBOOT_MAX the system will halt when this function is called, + * and in such cases the caller will not get the control back. Also note that calling this function may trigger mbed_error_reboot_callback() if application side overides mbed_error_reboot_callback(). + * @return MBED_SUCCESS on success. + * + */ + +mbed_error_status_t mbed_error_initialize(void); + +/** + * Call this function to retrieve the error context after a fatal error which triggered a system reboot. The function retrieves the error context stored in crash-report ram area which is preserved over reboot. + * @param error_info Pointer to mbed_error_ctx struct allocated by the caller. This is the mbed_error_ctx info captured as part of the fatal error which triggered the reboot. + * @return 0 or MBED_SUCCESS on success. + * MBED_ERROR_INVALID_ARGUMENT in case of invalid error_info pointer + * MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system + * + */ +mbed_error_status_t mbed_get_reboot_error_info(mbed_error_ctx *error_info); + +/** + * Calling this function resets the current reboot context captured by the system(stored in special crash data RAM region). + * @return MBED_SUCCESS on success. + * MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system + */ +mbed_error_status_t mbed_reset_reboot_error_info(void); + +/** + * Calling this function resets the current reboot count stored as part of error context captured in special crash data RAM region. + * The function will also update the CRC value stored as part of error context accordingly. + * @return MBED_SUCCESS on success. + * MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system + */ +mbed_error_status_t mbed_reset_reboot_count(void); + +/** + * Call this function to set a system error/warning. This function will log the error status with the context info and return to caller. + * + * @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. + * @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 + * + * @code + * + * mbed_error( ERROR_OUT_OF_MEMORY, "Out of memory error", 0, __FILE__, __LINE__ ) + * + * @endcode + * + * @note See MBED_WARNING/MBED_ERROR macros which provides a wrapper on this API + */ +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); + +/** + * Returns the first system error reported. + * @return mbed_error_status_t code logged for the first error or MBED_SUCCESS if no errors are logged. + * + */ +mbed_error_status_t mbed_get_first_error(void); + +/** + * Returns the most recent system error reported. + * @return mbed_error_status_t code logged for the last error or MBED_SUCCESS if no errors are logged. + * + */ +mbed_error_status_t mbed_get_last_error(void); + +/** + * Returns the number of system errors reported after boot. + * @return int Number of errors reported. + * + */ +int mbed_get_error_count(void); + +/** + * Returns whether we are processing a fatal mbed error. + * @return bool Whether a fatal error has occurred. + * + */ +bool mbed_get_error_in_progress(void); + +/** + * Call this function to set a fatal system error and halt the system. This function will log the fatal error with the context info and prints the error report and halts the system. + * + * @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. + * @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 Does not return. + * + * @code + * + * mbed_error( MBED_ERROR_PROHIBITED_OPERATION, "Prohibited operation tried", 0, __FILE__, __LINE__ ) + * + * @endcode + * + * @note See MBED_WARNING/MBED_ERROR macros which provides a wrapper on this API + */ +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. + * This function will be called with error context info whenever system handles a mbed_error/mbed_warning call + * NOTE: This function should be implemented for re-entrancy as multiple threads may invoke mbed_error which may cause error hook to be called. + * @param custom_error_hook mbed_error_status_t status to be set(See mbed_error_status_t enum above for available error status values). + * @return 0 or MBED_SUCCESS on success. + * MBED_ERROR_INVALID_ARGUMENT in case of NULL for custom_error_hook + * + * @code + * + * mbed_error_status_t my_custom_error_hook(mbed_error_status_t error_status, const mbed_error_ctx *error_ctx) { + * //Do something with the error_status or error_ctx + * } + * + * mbed_set_error_hook( my_custom_error_hook ) + * + * @endcode + * @note The error hook function implementation should be re-entrant. + * + * @deprecated You should use an overridden mbed_error_hook() function if you like to catch errors in your application. + * With mbed_set_error_hook() it is not possible to catch errors before your application started. + */ +mbed_error_status_t mbed_set_error_hook(mbed_error_hook_t custom_error_hook); + +/** + * Reads the first error context information captured. + * @param error_info This is the mbed_error_context info captured as part of the first mbed_error call. The caller should pass a pointer to mbed_error_context struct allocated by the caller. + * @return 0 or MBED_SUCCESS on success. + * MBED_ERROR_INVALID_ARGUMENT in case of invalid index + * + */ +mbed_error_status_t mbed_get_first_error_info(mbed_error_ctx *error_info); + +/** + * Reads the last error context information captured. + * @param error_info This is the mbed_error_context info captured as part of the last mbed_error call. The caller should pass a pointer to mbed_error_context struct allocated by the caller. + * @return 0 or MBED_ERROR_SUCCESS on success. + * MBED_ERROR_INVALID_ARGUMENT in case of invalid index + * + */ +mbed_error_status_t mbed_get_last_error_info(mbed_error_ctx *error_info); + +/** + * Clears the last error, first error, error count and all entries in the error history. + * @return 0 or MBED_SUCCESS on success. + * + */ +mbed_error_status_t mbed_clear_all_errors(void); + +/** + * Generates a mbed_error_status_t value based on passed in values for type, module and error code. + * @param error_type Error type based on mbed_error_type_t enum. + * @param module Module type based on mbed_module_type_t enum. + * @param error_code Error codes defined by mbed_error_code_t enum + * @return 0 or MBED_ERROR_SUCCESS on success. + * + */ +mbed_error_status_t mbed_make_error(mbed_error_type_t error_type, mbed_module_type_t module, mbed_error_code_t error_code); + +/** + * Returns the current number of entries in the error history, if there has been more than max number of errors logged the number returned will be max depth of error history. + * @return Current number of entries in the error history. + * + */ +int mbed_get_error_hist_count(void); + +/** + * Reads the error context information for a specific error from error history, specified by the index. + * + * @param index index of the error context entry in the history to be retrieved.\n + * The number of entries in the error history is configured during build and the max index depends on max depth of error history.\n + * index = 0 points to the oldest entry in the history, and index = (max history depth - 1) points to the latest entry in the error history.\n + * @param error_info This is the mbed_error_context info captured as part of the error history. The caller should pass a pointer to mbed_error_context struct allocated by the caller. + * @return 0 or MBED_SUCCESS on success. + * MBED_ERROR_INVALID_ARGUMENT in case of invalid index + * + */ +mbed_error_status_t mbed_get_error_hist_info(int index, mbed_error_ctx *error_info); + +/** + * Saves the error history information to a file + * + * @param path path to the file in the filesystem + * @return 0 or MBED_ERROR_SUCCESS on success. + * MBED_ERROR_WRITE_FAILED if writing to file failed + * MBED_ERROR_INVALID_ARGUMENT if path is not valid + * + * @note Filesystem support is required in order for this function to work. + * + */ +mbed_error_status_t mbed_save_error_hist(const char *path); + +#ifdef __cplusplus +} +#endif + +#endif + +/** @}*/ +/** @}*/ + + diff --git a/platform/include/platform/mbed_interface.h b/platform/include/platform/mbed_interface.h new file mode 100644 index 0000000..f6d0738 --- /dev/null +++ b/platform/include/platform/mbed_interface.h @@ -0,0 +1,189 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_INTERFACE_H +#define MBED_INTERFACE_H + +#include + +#include "platform/mbed_toolchain.h" +#include "device.h" + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_interface Network interface and other utility functions + * @{ + */ + +/* Mbed interface mac address + * if MBED_MAC_ADD_x are zero, interface uid sets mac address, + * otherwise MAC_ADD_x are used. + */ +#define MBED_MAC_ADDR_INTERFACE 0x00 +#define MBED_MAC_ADDR_0 MBED_MAC_ADDR_INTERFACE +#define MBED_MAC_ADDR_1 MBED_MAC_ADDR_INTERFACE +#define MBED_MAC_ADDR_2 MBED_MAC_ADDR_INTERFACE +#define MBED_MAC_ADDR_3 MBED_MAC_ADDR_INTERFACE +#define MBED_MAC_ADDR_4 MBED_MAC_ADDR_INTERFACE +#define MBED_MAC_ADDR_5 MBED_MAC_ADDR_INTERFACE +#define MBED_MAC_ADDRESS_SUM (MBED_MAC_ADDR_0 | MBED_MAC_ADDR_1 | MBED_MAC_ADDR_2 | MBED_MAC_ADDR_3 | MBED_MAC_ADDR_4 | MBED_MAC_ADDR_5) + +#ifdef __cplusplus +extern "C" { +#endif + +#if DEVICE_SEMIHOST + +/** + * \defgroup platform_interface interface functions + * @{ + */ + +/** Functions to control the mbed interface + * + * mbed Microcontrollers have a built-in interface to provide functionality such as + * drag-n-drop download, reset, serial-over-usb, and access to the mbed local file + * system. These functions provide means to control the interface using semihost + * calls it supports. + */ + +/** Determine whether the mbed interface is connected, based on whether debug is enabled + * + * @returns + * 1 if interface is connected, + * 0 otherwise + */ +int mbed_interface_connected(void); + +/** Instruct the mbed interface to reset, as if the reset button had been pressed + * + * @returns + * 1 if successful, + * 0 otherwise (e.g. interface not present) + */ +int mbed_interface_reset(void); + +/** This will disconnect the debug aspect of the interface, so semihosting will be disabled. + * The interface will still support the USB serial aspect + * + * @returns + * 0 if successful, + * -1 otherwise (e.g. interface not present) + */ +int mbed_interface_disconnect(void); + +/** This will disconnect the debug aspect of the interface, and if the USB cable is not + * connected, also power down the interface. If the USB cable is connected, the interface + * will remain powered up and visible to the host + * + * @returns + * 0 if successful, + * -1 otherwise (e.g. interface not present) + */ +int mbed_interface_powerdown(void); + +/** This returns a string containing the 32-character UID of the mbed interface + * This is a weak function that can be overwritten if required + * + * @param uid A 33-byte array to write the null terminated 32-byte string + * + * @returns + * 0 if successful, + * -1 otherwise (e.g. interface not present) + */ +int mbed_interface_uid(char *uid); + +#endif + +/** This returns a unique 6-byte MAC address, based on the interface UID + * If the interface is not present, it returns a default fixed MAC address (00:02:F7:F0:00:00) + * + * This is a weak function that can be overwritten if you want to provide your own mechanism to + * provide a MAC address. + * + * @param mac A 6-byte array to write the MAC address + */ +void mbed_mac_address(char *mac); + +/** Cause the mbed to flash the BLOD (Blue LEDs Of Death) sequence + */ +MBED_NORETURN void mbed_die(void); + +/** Print out an error message. This is typically called when + * handling a crash. + * + * @note Synchronization level: Interrupt safe, as long as the + * FileHandle::write of the stderr device is. See mbed_error_puts + * for more information. + * @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. + * + * @code + * mbed_error_printf("Failed: %s, file: %s, line %d \n", expr, file, line); + * @endcode + * + */ +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. + * + * @note Synchronization level: Interrupt safe, as long as the + * FileHandle::write of the stderr device is. See mbed_error_puts + * for more information. + * + * @param format C string that contains data stream to be printed. + * @param arg Variable arguments list + * + */ +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, as long as the + * FileHandle::write of the stderr device is. The default + * serial console is safe, either buffered or not. If the + * console has not previously been initialized, an attempt + * to use this from interrupt may crash during console initialization. + * Special handling of `mbed_error` relaxes various system traps + * to increase the chance of initialization working. + * + * @param str C string that contains data stream to be printed. + * + */ +void mbed_error_puts(const char *str); + +/** @}*/ + + +#ifdef __cplusplus +} +#endif + +#endif + +/** @}*/ diff --git a/platform/include/platform/mbed_mem_trace.h b/platform/include/platform/mbed_mem_trace.h new file mode 100644 index 0000000..2c5bc40 --- /dev/null +++ b/platform/include/platform/mbed_mem_trace.h @@ -0,0 +1,174 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_MEM_TRACE_H__ +#define __MBED_MEM_TRACE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * enum Memory operation types for tracer + */ +enum { + 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 */ +}; + +/** + * \defgroup platform_mem_trace mem_trace functions + * @{ + */ + +/* Prefix for the output of the default tracer */ +#define MBED_MEM_DEFAULT_TRACER_PREFIX "#" + +/** + * Type of the callback used by the memory tracer. This callback is called when a memory + * allocation operation (malloc, realloc, calloc, free) is called and tracing is enabled + * for that memory allocation function. + * + * @param op the ID of the operation (MBED_MEM_TRACE_MALLOC, MBED_MEM_TRACE_REALLOC, + * MBED_MEM_TRACE_CALLOC or MBED_MEM_TRACE_FREE). + * @param res the result that the memory operation returned (NULL for 'free'). + * @param caller the caller of the memory operation. Note that the value of 'caller' might be + * unreliable. + * + * The rest of the parameters passed 'mbed_mem_trace_cb_t' are the same as the memory operations + * that triggered its call (see 'man malloc' for details): + * + * - for malloc: cb(MBED_MEM_TRACE_MALLOC, res, caller, size). + * - for realloc: cb(MBED_MEM_TRACE_REALLOC, res, caller, ptr, size). + * - for calloc: cb(MBED_MEM_TRACE_CALLOC, res, caller, nmemb, size). + * - for free: cb(MBED_MEM_TRACE_FREE, NULL, caller, ptr). + */ +typedef void (*mbed_mem_trace_cb_t)(uint8_t op, void *res, void *caller, ...); + +/** + * Set the callback used by the memory tracer (use NULL for disable tracing). + * + * @param cb the callback to call on each memory operation. + */ +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 realloc/calloc + */ +void mbed_mem_trace_lock(); + +/** + * Trace unlock. + */ +void mbed_mem_trace_unlock(); + +/** + * Trace a call to 'malloc'. + * @param res the result of running 'malloc'. + * @param size the 'size' argument given to 'malloc'. + * @param caller the caller of the memory operation. + * @return 'res' (the first argument). + */ +void *mbed_mem_trace_malloc(void *res, size_t size, void *caller); + +/** + * Trace a call to 'realloc'. + * @param res the result of running 'realloc'. + * @param ptr the 'ptr' argument given to 'realloc'. + * @param size the 'size' argument given to 'realloc'. + * @param caller the caller of the memory operation. + * @return 'res' (the first argument). + */ +void *mbed_mem_trace_realloc(void *res, void *ptr, size_t size, void *caller); + +/** + * Trace a call to 'calloc'. + * @param res the result of running 'calloc'. + * @param num the 'nmemb' argument given to 'calloc'. + * @param size the 'size' argument given to 'calloc'. + * @param caller the caller of the memory operation. + * @return 'res' (the first argument). + */ +void *mbed_mem_trace_calloc(void *res, size_t num, size_t size, void *caller); + +/** + * Trace a call to 'free'. + * @param ptr the 'ptr' argument given to 'free'. + * @param caller the caller of the memory operation. + */ +void mbed_mem_trace_free(void *ptr, void *caller); + +/** + * Default memory trace callback. DO NOT CALL DIRECTLY. It is meant to be used + * as the second argument of 'mbed_mem_trace_setup'. + * + * The default callback outputs trace data using 'printf', in a format that's + * easily parsable by an external tool. For each memory operation, the callback + * outputs a line that begins with "#:<0xresult>;<0xcaller>-": + * + * @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 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. + * + * The rest of the output depends on the operation being traced: + * + * - for 'malloc': 'size', where 'size' is the original argument to 'malloc'. + * - for 'realloc': '0xptr;size', where 'ptr' (base 16) and 'size' are the original arguments to 'realloc'. + * - for 'calloc': 'nmemb;size', where 'nmemb' and 'size' are the original arguments to 'calloc'. + * - for 'free': '0xptr', where 'ptr' (base 16) is the original argument to 'free'. + * + * Examples: + * + * - "#m:0x20003240;0x600d-50" encodes a 'malloc' that returned 0x20003240, was called + * by the instruction at 0x600D with a the 'size' argument equal to 50. + * - "#f:0x0;0x602f-0x20003240" encodes a 'free' that was called by the instruction at + * 0x602f with the 'ptr' argument equal to 0x20003240. + */ +void mbed_mem_trace_default_callback(uint8_t op, void *res, void *caller, ...); + +/** @}*/ + +#ifdef __cplusplus +} +#endif + +#endif// #ifndef __MBED_MEM_TRACE_H__ + + +/** @}*/ diff --git a/platform/include/platform/mbed_mktime.h b/platform/include/platform/mbed_mktime.h new file mode 100644 index 0000000..0a748c2 --- /dev/null +++ b/platform/include/platform/mbed_mktime.h @@ -0,0 +1,132 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2019 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_MKTIME_H +#define MBED_MKTIME_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_mktime mktime functions + * @{ + */ + +/* Time range across the whole 32-bit range should be supported which means that years in range 1970 - 2106 can be + * encoded. We have two types of RTC devices: + * a) RTCs which handles all leap years in the mentioned year range correctly. Leap year is determined by checking if + * the year counter value is divisible by 400, 100, and 4. No problem here. + * b) RTCs which handles leap years correctly up to 2100. The RTC does a simple bit comparison to see if the two + * lowest order bits of the year counter are zero. In this case 2100 year will be considered + * incorrectly as a leap year, so the last valid point in time will be 28.02.2100 23:59:59 and next day will be + * 29.02.2100 (invalid). So after 28.02.2100 the day counter will be off by a day. + */ +typedef enum { + RTC_FULL_LEAP_YEAR_SUPPORT, + RTC_4_YEAR_LEAP_YEAR_SUPPORT +} rtc_leap_year_support_t; + +/** Compute if a year is a leap year or not. + * + * @param year The year to test it shall be in the range [70:206]. Year 0 is + * translated into year 1900 CE. + * @param leap_year_support use RTC_FULL_LEAP_YEAR_SUPPORT if RTC device is able + * to correctly detect all leap years in range [70:206] otherwise use RTC_4_YEAR_LEAP_YEAR_SUPPORT. + * + * @return true if the year in input is a leap year and false otherwise. + * + * @note For use by the HAL only + * @note Year 2100 is treated differently for devices with full leap year support and devices with + * partial leap year support. Devices with partial leap year support treats 2100 as a leap year. + */ +bool _rtc_is_leap_year(int year, rtc_leap_year_support_t leap_year_support); + +/* Convert a calendar time into time since UNIX epoch as a time_t. + * + * This function is a thread safe (partial) replacement for mktime. It is + * tailored around RTC peripherals needs and is not by any mean a complete + * replacement of mktime. + * + * @param time The calendar time to convert into a time_t since epoch. + * The fields from tm used for the computation are: + * - tm_sec + * - tm_min + * - tm_hour + * - tm_mday + * - tm_mon + * - tm_year + * Other fields are ignored and won't be renormalized by a call to this function. + * A valid calendar time is comprised between: + * the 1st of January 1970 at 00:00:00 to the 7th of February 2106 at 06:28:15. + * @param leap_year_support use RTC_FULL_LEAP_YEAR_SUPPORT if RTC device is able + * to correctly detect all leap years in range [70:206] otherwise use RTC_4_YEAR_LEAP_YEAR_SUPPORT. + * @param seconds holder for the result - calendar time as seconds since UNIX epoch. + * + * @return true on success, false if conversion error occurred. + * + * @note Leap seconds are not supported. + * @note Values in output range from 0 to UINT_MAX. + * @note Full and partial leap years support. + * @note For use by the HAL only + */ +bool _rtc_maketime(const struct tm *time, time_t *seconds, rtc_leap_year_support_t leap_year_support); + +/* Convert a given time in seconds since epoch into calendar time. + * + * This function is a thread safe (partial) replacement for localtime. It is + * tailored around RTC peripherals specification and is not by any means a + * complete of localtime. + * + * @param timestamp The time (in seconds) to convert into calendar time. Valid + * input are in the range [0 : UINT32_MAX]. + * @param calendar_time Pointer to the object which will contain the result of + * the conversion. The tm fields filled by this function are: + * - tm_sec + * - tm_min + * - tm_hour + * - tm_mday + * - tm_mon + * - tm_year + * - tm_wday + * - tm_yday + * The object remains untouched if the time in input is invalid. + * @param leap_year_support use RTC_FULL_LEAP_YEAR_SUPPORT if RTC device is able + * to correctly detect all leap years in range [70:206] otherwise use RTC_4_YEAR_LEAP_YEAR_SUPPORT. + * @return true if the conversion was successful, false otherwise. + * + * @note For use by the HAL only. + * @note Full and partial leap years support. + */ +bool _rtc_localtime(time_t timestamp, struct tm *time_info, rtc_leap_year_support_t leap_year_support); + +/** @}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* MBED_MKTIME_H */ + +/** @}*/ diff --git a/platform/include/platform/mbed_mpu_mgmt.h b/platform/include/platform/mbed_mpu_mgmt.h new file mode 100644 index 0000000..01f9e78 --- /dev/null +++ b/platform/include/platform/mbed_mpu_mgmt.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018-2020, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_MPU_MGMT_H +#define MBED_MPU_MGMT_H + +#include "hal/mpu_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_mpu_mgmt MPU management functions + * @{ + */ + +#if (DEVICE_MPU && MBED_CONF_PLATFORM_USE_MPU) || defined(DOXYGEN_ONLY) + +#define mbed_mpu_manager_init() mbed_mpu_init() + +#define mbed_mpu_manager_deinit() mbed_mpu_free() + +/** Lock ram execute never mode off + * + * This disables the MPU's execute never ram protection and allows + * functions to run from RAM. Execution directly from ram will be + * allowed if this function is invoked at least once (the internal + * counter is non-zero). + * + * Use this locking mechanism for code which needs to execute from + * ram such as flash programming algorithms and ram thunks. + * + * The lock is a counter, can be locked up to USHRT_MAX + * This function is IRQ and thread safe + */ +void mbed_mpu_manager_lock_ram_execution(void); + +/** Unlock ram execute never mode + * + * Use unlocking in pair with mbed_mpu_manager_lock_ram_execution(). + * + * The lock is a counter, should be equally unlocked as locked + * This function is IRQ and thread safe + */ +void mbed_mpu_manager_unlock_ram_execution(void); + +/** Lock rom write never mode off + * + * This disables the MPU's read only ROM protection and allows + * ROM to be written to. Writing to ROM will not result in an MPU + * fault if this function is invoked at least once (the internal + * counter is non-zero). + * + * Use this locking mechanism for code which needs to write to + * ROM such as flash programming algorithms. + * + * The lock is a counter, can be locked up to USHRT_MAX + * This function is IRQ and thread safe + */ +void mbed_mpu_manager_lock_rom_write(void); + +/** Unlock rom write never mode + * + * Use unlocking in pair with mbed_mpu_manager_lock_rom_write(). + * + * The lock is a counter, should be equally unlocked as locked + * This function is IRQ and thread safe + */ +void mbed_mpu_manager_unlock_rom_write(void); + +#else + +#define mbed_mpu_manager_init() (void)0 + +#define mbed_mpu_manager_deinit() (void)0 + +#define mbed_mpu_manager_lock_ram_execution() (void)0 + +#define mbed_mpu_manager_unlock_ram_execution() (void)0 + +#define mbed_mpu_manager_lock_rom_write() (void)0 + +#define mbed_mpu_manager_unlock_rom_write() (void)0 + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +/** @}*/ +/** @}*/ diff --git a/platform/include/platform/mbed_poll.h b/platform/include/platform/mbed_poll.h new file mode 100644 index 0000000..04a71c4 --- /dev/null +++ b/platform/include/platform/mbed_poll.h @@ -0,0 +1,62 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2019 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_POLL_H +#define MBED_POLL_H + +#define POLLIN 0x0001 ///< Data may be read without blocking +#define POLLOUT 0x0010 ///< Data may be written without blocking +#define POLLERR 0x1000 ///< An error has occurred on the device or stream +#define POLLHUP 0x2000 ///< The device has been disconnected +#define POLLNVAL 0x4000 ///< The specified file handle value is invalid + +namespace mbed { + +class FileHandle; + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_poll poll functions + * @{ + */ + +struct pollfh { + FileHandle *fh; + short events; + short revents; +}; + +/** A mechanism to multiplex input/output over a set of file handles(file descriptors). + * For every file handle provided, poll() examines it for any events registered for that particular + * file handle. + * + * @param fhs an array of PollFh struct carrying a FileHandle and bitmasks of events + * @param nfhs number of file handles + * @param timeout timer value to timeout or -1 for loop forever + * + * @return number of file handles selected (for which revents is non-zero). 0 if timed out with nothing selected. -1 for error. + */ +int poll(pollfh fhs[], unsigned nfhs, int timeout); + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif //MBED_POLL_H diff --git a/platform/include/platform/mbed_power_mgmt.h b/platform/include/platform/mbed_power_mgmt.h new file mode 100644 index 0000000..caf1d02 --- /dev/null +++ b/platform/include/platform/mbed_power_mgmt.h @@ -0,0 +1,250 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_POWER_MGMT_H +#define MBED_POWER_MGMT_H + + +#include "platform/mbed_toolchain.h" +#include "hal/ticker_api.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_power_mgmt Power management functions + * @{ + */ + +/** + * @defgroup hal_sleep_manager Sleep manager API + * The sleep manager provides API to automatically select sleep mode. + * + * There are two sleep modes: + * - sleep + * - deepsleep + * + * Use locking/unlocking deepsleep for drivers that depend on features that + * 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 + * + * void driver::handler() + * { + * if (_sensor.get_event()) { + * // any event - we are finished, unlock the deepsleep + * sleep_manager_unlock_deep_sleep(); + * _callback(); + * } + * } + * + * int driver::measure(event_t event, callback_t& callback) + * { + * _callback = callback; + * sleep_manager_lock_deep_sleep(); + * // start async transaction, we are waiting for an event + * 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); +void sleep_tracker_unlock(const char *const filename, int line); + +#define sleep_manager_lock_deep_sleep() \ + do \ + { \ + sleep_manager_lock_deep_sleep_internal(); \ + sleep_tracker_lock(MBED_FILENAME, __LINE__); \ + } while (0); + +#define sleep_manager_unlock_deep_sleep() \ + do \ + { \ + sleep_manager_unlock_deep_sleep_internal(); \ + sleep_tracker_unlock(MBED_FILENAME, __LINE__); \ + } while (0); + +#else + +#define sleep_manager_lock_deep_sleep() \ + sleep_manager_lock_deep_sleep_internal() + +#define sleep_manager_unlock_deep_sleep() \ + sleep_manager_unlock_deep_sleep_internal() + +#endif // MBED_SLEEP_TRACING_ENABLED + +/** Lock the deep sleep mode + * + * This locks the automatic deep mode selection. + * sleep_manager_sleep_auto() will ignore deepsleep mode if + * this function is invoked at least once (the internal counter is non-zero) + * + * Use this locking mechanism for interrupt driven API that are + * running in the background and deepsleep could affect their functionality + * + * The lock is a counter, can be locked up to USHRT_MAX + * This function is IRQ and thread safe + */ +void sleep_manager_lock_deep_sleep_internal(void); + +/** Unlock the deep sleep mode + * + * Use unlocking in pair with sleep_manager_lock_deep_sleep(). + * + * The lock is a counter, should be equally unlocked as locked + * This function is IRQ and thread safe + */ +void sleep_manager_unlock_deep_sleep_internal(void); + +/** Get the status of deep sleep allowance for a target + * + * @return true if a target can go to deepsleep, false otherwise + */ +bool sleep_manager_can_deep_sleep(void); + +/** Check if the target can deep sleep within a period of time + * + * This function in intended for use in testing. The amount + * of time this functions waits for deeps sleep to be available + * is currently 2ms. This may change in the future depending + * on testing requirements. + * + * @return true if a target can go to deepsleep, false otherwise + */ +bool sleep_manager_can_deep_sleep_test_check(void); + +/** 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 + * + * @note + * If MBED_DEBUG is defined, only hal_sleep is allowed. This ensures the debugger + * to be active for debug modes. + * + */ +void sleep_manager_sleep_auto(void); + +/** Send the microcontroller to sleep + * + * @note This function can be a noop if not implemented by the platform. + * @note This function will be a noop in debug mode (debug build profile when MBED_DEBUG is defined). + * @note This function will be a noop if the following conditions are met: + * - The RTOS is present + * - The processor turn off the Systick clock during sleep + * - The target does not implement tickless mode + * + * The processor is setup ready for sleep, and sent to sleep using __WFI(). In this mode, the + * system clock to the core is stopped until a reset or an interrupt occurs. This eliminates + * dynamic power used by the processor, memory systems and buses. The processor, peripheral and + * memory state are maintained, and the peripherals continue to work and can generate interrupts. + * + * The processor can be woken up by any internal peripheral interrupt or external pin interrupt. + * + * @note + * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. + * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be + * able to access the LocalFileSystem + */ +static inline void sleep(void) +{ +#if DEVICE_SLEEP +#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_SYSTICK_CLK_OFF_DURING_SLEEP == 0) || defined(MBED_TICKLESS) */ +#endif /* DEVICE_SLEEP */ +} + +/** Provides the time spent in sleep mode since boot. + * + * @return Time spent in sleep + * @note Works only if platform supports LP ticker. + */ +us_timestamp_t mbed_time_sleep(void); + +/** Provides the time spent in deep sleep mode since boot. + * + * @return Time spent in deep sleep + * @note Works only if platform supports LP ticker. + */ +us_timestamp_t mbed_time_deepsleep(void); + +/** Provides the time spent in idle mode since boot. + * + * @return Idle thread time. + * @note Works only if platform supports LP ticker. + */ +us_timestamp_t mbed_time_idle(void); + +/** Provides the time since the system is up i.e. boot. + * + * @return System uptime. + * @note Works only if platform supports LP ticker. + */ +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 + +#endif + +/** @}*/ +/** @}*/ diff --git a/platform/include/platform/mbed_preprocessor.h b/platform/include/platform/mbed_preprocessor.h new file mode 100644 index 0000000..f7be2f1 --- /dev/null +++ b/platform/include/platform/mbed_preprocessor.h @@ -0,0 +1,87 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_PREPROCESSOR_H +#define MBED_PREPROCESSOR_H + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_preprocessor preprocessor macros + * @{ + */ + +/** MBED_CONCAT + * Concatenate tokens together + * + * @note + * Expands tokens before concatenation + * + * @code + * // Creates a unique label based on the line number + * int MBED_CONCAT(UNIQUE_LABEL_, __LINE__) = 1; + * @endcode + */ +#define MBED_CONCAT(a, b) MBED_CONCAT_(a, b) +#define MBED_CONCAT_(a, b) a##b + +/** MBED_STRINGIFY + * Converts tokens into strings + * + * @note + * Expands tokens before stringification + * + * @code + * // Creates a string based on the parameters + * const char *c = MBED_STRINGIFY(This is a ridiculous way to create a string) + * @endcode + */ +#define MBED_STRINGIFY(a) MBED_STRINGIFY_(a) +#define MBED_STRINGIFY_(a) #a + +/** MBED_STRLEN + * Reports string token length + * + * @note + * Expands tokens before calculating length + * + * @code + * // Get string length + * const int len = MBED_STRLEN("Get the length") + * @endcode + */ +#define MBED_STRLEN(a) MBED_STRLEN_(a) +#define MBED_STRLEN_(a) (sizeof(a) - 1) + +/** MBED_COUNT_VA_ARGS(...) + * Reports number of tokens passed + * + * @note + * Token limit is 16 + * + * @code + * // Get number of arguments + * const int count = MBED_COUNT_VA_ARGS("Address 0x%x, Data[0] = %d Data[1] = %d", 0x20001234, 10, 20) + * @endcode + */ +#define MBED_COUNT_VA_ARGS(...) GET_NTH_ARG_(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) +#define GET_NTH_ARG_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, N, ...) N + +#endif + +/** @}*/ +/** @}*/ diff --git a/platform/include/platform/mbed_retarget.h b/platform/include/platform/mbed_retarget.h new file mode 100644 index 0000000..380c8d2 --- /dev/null +++ b/platform/include/platform/mbed_retarget.h @@ -0,0 +1,670 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2006-2019 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 RETARGET_H +#define RETARGET_H + +#if __cplusplus +#include +#else +#include +#endif //__cplusplus +#include +#include + +/* Include logic for errno so we can get errno defined but not bring in error_t, + * including errno here prevents an include later, which would redefine our + * error codes + */ +#ifndef __error_t_defined +#define __error_t_defined 1 +#endif +#include + +#if defined __has_include +# if __has_include () +# include +# define HAVE_SYS_STAT_H +# endif +#endif + +/* We can get the following standard types from sys/types for gcc, but we + * need to define the types ourselves for the other compilers that normally + * target embedded systems */ +typedef signed int ssize_t; ///< Signed size type, usually encodes negative errors +typedef signed long off_t; ///< Offset in a data stream +typedef unsigned int nfds_t; ///< Number of file descriptors +typedef unsigned long long fsblkcnt_t; ///< Count of file system blocks +#if defined(__ARMCC_VERSION) || !defined(__GNUC__) +typedef unsigned int mode_t; ///< Mode for opening files +typedef unsigned int dev_t; ///< Device ID type +typedef unsigned long ino_t; ///< File serial number +typedef unsigned int nlink_t; ///< Number of links to a file +typedef unsigned int uid_t; ///< User ID +typedef unsigned int gid_t; ///< Group ID +#endif + +/* Flags for open() and fcntl(GETFL/SETFL) + * At present, fcntl only supports reading and writing O_NONBLOCK + */ +#define O_RDONLY 0 ///< Open for reading +#define O_WRONLY 1 ///< Open for writing +#define O_RDWR 2 ///< Open for reading and writing +#define O_NONBLOCK 0x0004 ///< Non-blocking mode +#define O_APPEND 0x0008 ///< Set file offset to end of file prior to each write +#define O_CREAT 0x0200 ///< Create file if it does not exist +#define O_TRUNC 0x0400 ///< Truncate file to zero length +#define O_EXCL 0x0800 ///< Fail if file exists +#define O_BINARY 0x8000 ///< Open file in binary mode + +#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) + +#define NAME_MAX 255 ///< Maximum size of a name in a file path + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#include + +/** \addtogroup platform-public-api */ +/** @{*/ + +#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY +/** + * \defgroup platform_retarget Retarget functions + * @{ + */ + +/* DIR declarations must also be here */ +#if __cplusplus +namespace mbed { +class FileHandle; +class DirHandle; + +/** Targets may implement this to change stdin, stdout, stderr. + * + * If the application hasn't provided mbed_override_console, this is called + * to give the target a chance to specify a FileHandle for the console. + * + * If this is not provided or returns NULL, the console will be: + * - BufferedSerial if configuration option "platform.stdio-buffered-serial" is + * true and the target has DEVICE_SERIAL; + * - Raw HAL serial via serial_getc and serial_putc if + * "platform.stdio-buffered-serial" is false and the target has DEVICE_SERIAL; + * - stdout/stderr will be a sink and stdin will input a stream of 0s if the + * target does not have DEVICE_SERIAL. + * + * @param fd file descriptor - STDIN_FILENO, STDOUT_FILENO or STDERR_FILENO + * @return pointer to FileHandle to override normal stream otherwise NULL + */ +FileHandle *mbed_target_override_console(int fd); + +/** Applications may implement this to change stdin, stdout, stderr. + * + * This hook gives the application a chance to specify a custom FileHandle + * for the console. + * + * If this is not provided or returns NULL, the console will be specified + * by mbed_target_override_console, else will default to serial - see + * mbed_target_override_console for more details. + * + * Example using BufferedSerial: + * @code + * FileHandle *mbed::mbed_override_console(int) { + * static BufferedSerial my_serial(D0, D1); + * return &my_serial; + * } + * @endcode + * + * Example using SingleWireOutput: + * @code + * FileHandle *mbed::mbed_override_console(int) { + * static SerialWireOutput swo; + * return &swo; + * } + * @endcode + * + * Example using arm semihosting: + * @code + * FileHandle *mbed::mbed_override_console(int fileno) { + * static LocalFileSystem fs("host"); + * if (fileno == STDIN_FILENO) { + * static FileHandle *in_terminal; + * static int in_open_result = fs.open(&in_terminal, ":tt", O_RDONLY); + * return in_terminal; + * } else { + * static FileHandle *out_terminal; + * static int out_open_result = fs.open(&out_terminal, ":tt", O_WRONLY); + * return out_terminal; + * } + * } + * @endcode + * + * @param fd file descriptor - STDIN_FILENO, STDOUT_FILENO or STDERR_FILENO + * @return pointer to FileHandle to override normal stream otherwise NULL + */ +FileHandle *mbed_override_console(int fd); + +/** Look up the Mbed file handle corresponding to a file descriptor + * + * This conversion function permits an application to find the underlying + * FileHandle object corresponding to a POSIX file descriptor. + * + * This allows access to specialized behavior only available via the + * FileHandle API. + * + * Example of saving power by disabling console input - for buffered serial, + * this would release the RX interrupt handler, which would release the + * deep sleep lock. + * @code + * mbed_file_handle(STDIN_FILENO)->enable_input(false); + * @endcode + * + * @param fd file descriptor + * @return FileHandle pointer + * NULL if descriptor does not correspond to a FileHandle (only + * possible if it's not open with current implementation). + */ +FileHandle *mbed_file_handle(int fd); +} + +typedef mbed::DirHandle DIR; +#else +typedef struct Dir DIR; +#endif +#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY + +/* The intent of this section is to unify the errno error values to match + * the POSIX definitions for the GCC_ARM, ARMCC and IAR compilers. This is + * necessary because the ARMCC/IAR errno.h, or sys/stat.h are missing some + * symbol definitions used by the POSIX filesystem API to return errno codes. + * Note also that ARMCC errno.h defines some symbol values differently from + * the GCC_ARM/IAR/standard POSIX definitions. The definitions guard against + * this and future changes by changing the symbol definition as shown below. + */ +#undef EPERM +#define EPERM 1 /* Operation not permitted */ +#undef ENOENT +#define ENOENT 2 /* No such file or directory */ +#undef ESRCH +#define ESRCH 3 /* No such process */ +#undef EINTR +#define EINTR 4 /* Interrupted system call */ +#undef EIO +#define EIO 5 /* I/O error */ +#undef ENXIO +#define ENXIO 6 /* No such device or address */ +#undef E2BIG +#define E2BIG 7 /* Argument list too long */ +#undef ENOEXEC +#define ENOEXEC 8 /* Exec format error */ +#undef EBADF +#define EBADF 9 /* Bad file number */ +#undef ECHILD +#define ECHILD 10 /* No child processes */ +#undef EAGAIN +#define EAGAIN 11 /* Try again */ +#undef ENOMEM +#define ENOMEM 12 /* Out of memory */ +#undef EACCES +#define EACCES 13 /* Permission denied */ +#undef EFAULT +#define EFAULT 14 /* Bad address */ +#undef ENOTBLK +#define ENOTBLK 15 /* Block device required */ +#undef EBUSY +#define EBUSY 16 /* Device or resource busy */ +#undef EEXIST +#define EEXIST 17 /* File exists */ +#undef EXDEV +#define EXDEV 18 /* Cross-device link */ +#undef ENODEV +#define ENODEV 19 /* No such device */ +#undef ENOTDIR +#define ENOTDIR 20 /* Not a directory */ +#undef EISDIR +#define EISDIR 21 /* Is a directory */ +#undef EINVAL +#define EINVAL 22 /* Invalid argument */ +#undef ENFILE +#define ENFILE 23 /* File table overflow */ +#undef EMFILE +#define EMFILE 24 /* Too many open files */ +#undef ENOTTY +#define ENOTTY 25 /* Not a typewriter */ +#undef ETXTBSY +#define ETXTBSY 26 /* Text file busy */ +#undef EFBIG +#define EFBIG 27 /* File too large */ +#undef ENOSPC +#define ENOSPC 28 /* No space left on device */ +#undef ESPIPE +#define ESPIPE 29 /* Illegal seek */ +#undef EROFS +#define EROFS 30 /* Read-only file system */ +#undef EMLINK +#define EMLINK 31 /* Too many links */ +#undef EPIPE +#define EPIPE 32 /* Broken pipe */ +#undef EDOM +#define EDOM 33 /* Math argument out of domain of func */ +#undef ERANGE +#define ERANGE 34 /* Math result not representable */ +#undef EDEADLK +#define EDEADLK 35 /* Resource deadlock would occur */ +#undef ENAMETOOLONG +#define ENAMETOOLONG 36 /* File name too long */ +#undef ENOLCK +#define ENOLCK 37 /* No record locks available */ +#undef ENOSYS +#define ENOSYS 38 /* Function not implemented */ +#undef ENOTEMPTY +#define ENOTEMPTY 39 /* Directory not empty */ +#undef ELOOP +#define ELOOP 40 /* Too many symbolic links encountered */ +#undef EWOULDBLOCK +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#undef ENOMSG +#define ENOMSG 42 /* No message of desired type */ +#undef EIDRM +#define EIDRM 43 /* Identifier removed */ +#undef ECHRNG +#define ECHRNG 44 /* Channel number out of range */ +#undef EL2NSYNC +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#undef EL3HLT +#define EL3HLT 46 /* Level 3 halted */ +#undef EL3RST +#define EL3RST 47 /* Level 3 reset */ +#undef ELNRNG +#define ELNRNG 48 /* Link number out of range */ +#undef EUNATCH +#define EUNATCH 49 /* Protocol driver not attached */ +#undef ENOCSI +#define ENOCSI 50 /* No CSI structure available */ +#undef EL2HLT +#define EL2HLT 51 /* Level 2 halted */ +#undef EBADE +#define EBADE 52 /* Invalid exchange */ +#undef EBADR +#define EBADR 53 /* Invalid request descriptor */ +#undef EXFULL +#define EXFULL 54 /* Exchange full */ +#undef ENOANO +#define ENOANO 55 /* No anode */ +#undef EBADRQC +#define EBADRQC 56 /* Invalid request code */ +#undef EBADSLT +#define EBADSLT 57 /* Invalid slot */ +#undef EDEADLOCK +#define EDEADLOCK EDEADLK /* Resource deadlock would occur */ +#undef EBFONT +#define EBFONT 59 /* Bad font file format */ +#undef ENOSTR +#define ENOSTR 60 /* Device not a stream */ +#undef ENODATA +#define ENODATA 61 /* No data available */ +#undef ETIME +#define ETIME 62 /* Timer expired */ +#undef ENOSR +#define ENOSR 63 /* Out of streams resources */ +#undef ENONET +#define ENONET 64 /* Machine is not on the network */ +#undef ENOPKG +#define ENOPKG 65 /* Package not installed */ +#undef EREMOTE +#define EREMOTE 66 /* Object is remote */ +#undef ENOLINK +#define ENOLINK 67 /* Link has been severed */ +#undef EADV +#define EADV 68 /* Advertise error */ +#undef ESRMNT +#define ESRMNT 69 /* Srmount error */ +#undef ECOMM +#define ECOMM 70 /* Communication error on send */ +#undef EPROTO +#define EPROTO 71 /* Protocol error */ +#undef EMULTIHOP +#define EMULTIHOP 72 /* Multihop attempted */ +#undef EDOTDOT +#define EDOTDOT 73 /* RFS specific error */ +#undef EBADMSG +#define EBADMSG 74 /* Not a data message */ +#undef EOVERFLOW +#define EOVERFLOW 75 /* Value too large for defined data type */ +#undef ENOTUNIQ +#define ENOTUNIQ 76 /* Name not unique on network */ +#undef EBADFD +#define EBADFD 77 /* File descriptor in bad state */ +#undef EREMCHG +#define EREMCHG 78 /* Remote address changed */ +#undef ELIBACC +#define ELIBACC 79 /* Can not access a needed shared library */ +#undef ELIBBAD +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#undef ELIBSCN +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#undef ELIBMAX +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#undef ELIBEXEC +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#undef EILSEQ +#define EILSEQ 84 /* Illegal byte sequence */ +#undef ERESTART +#define ERESTART 85 /* Interrupted system call should be restarted */ +#undef ESTRPIPE +#define ESTRPIPE 86 /* Streams pipe error */ +#undef EUSERS +#define EUSERS 87 /* Too many users */ +#undef ENOTSOCK +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#undef EDESTADDRREQ +#define EDESTADDRREQ 89 /* Destination address required */ +#undef EMSGSIZE +#define EMSGSIZE 90 /* Message too long */ +#undef EPROTOTYPE +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#undef ENOPROTOOPT +#define ENOPROTOOPT 92 /* Protocol not available */ +#undef EPROTONOSUPPORT +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#undef ESOCKTNOSUPPORT +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#undef EOPNOTSUPP +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#undef EPFNOSUPPORT +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#undef EAFNOSUPPORT +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#undef EADDRINUSE +#define EADDRINUSE 98 /* Address already in use */ +#undef EADDRNOTAVAIL +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#undef ENETDOWN +#define ENETDOWN 100 /* Network is down */ +#undef ENETUNREACH +#define ENETUNREACH 101 /* Network is unreachable */ +#undef ENETRESET +#define ENETRESET 102 /* Network dropped connection because of reset */ +#undef ECONNABORTED +#define ECONNABORTED 103 /* Software caused connection abort */ +#undef ECONNRESET +#define ECONNRESET 104 /* Connection reset by peer */ +#undef ENOBUFS +#define ENOBUFS 105 /* No buffer space available */ +#undef EISCONN +#define EISCONN 106 /* Transport endpoint is already connected */ +#undef ENOTCONN +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#undef ESHUTDOWN +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#undef ETOOMANYREFS +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#undef ETIMEDOUT +#define ETIMEDOUT 110 /* Connection timed out */ +#undef ECONNREFUSED +#define ECONNREFUSED 111 /* Connection refused */ +#undef EHOSTDOWN +#define EHOSTDOWN 112 /* Host is down */ +#undef EHOSTUNREACH +#define EHOSTUNREACH 113 /* No route to host */ +#undef EALREADY +#define EALREADY 114 /* Operation already in progress */ +#undef EINPROGRESS +#define EINPROGRESS 115 /* Operation now in progress */ +#undef ESTALE +#define ESTALE 116 /* Stale NFS file handle */ +#undef EUCLEAN +#define EUCLEAN 117 /* Structure needs cleaning */ +#undef ENOTNAM +#define ENOTNAM 118 /* Not a XENIX named type file */ +#undef ENAVAIL +#define ENAVAIL 119 /* No XENIX semaphores available */ +#undef EISNAM +#define EISNAM 120 /* Is a named type file */ +#undef EREMOTEIO +#define EREMOTEIO 121 /* Remote I/O error */ +#undef EDQUOT +#define EDQUOT 122 /* Quota exceeded */ +#undef ENOMEDIUM +#define ENOMEDIUM 123 /* No medium found */ +#undef EMEDIUMTYPE +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#undef ECANCELED +#define ECANCELED 125 /* Operation Canceled */ +#undef ENOKEY +#define ENOKEY 126 /* Required key not available */ +#undef EKEYEXPIRED +#define EKEYEXPIRED 127 /* Key has expired */ +#undef EKEYREVOKED +#define EKEYREVOKED 128 /* Key has been revoked */ +#undef EKEYREJECTED +#define EKEYREJECTED 129 /* Key was rejected by service */ +#undef EOWNERDEAD +#define EOWNERDEAD 130 /* Owner died */ +#undef ENOTRECOVERABLE +#define ENOTRECOVERABLE 131 /* State not recoverable */ + +/* Missing stat.h defines. + * The following are sys/stat.h definitions not currently present in the ARMCC + * errno.h. Note, ARMCC errno.h defines some symbol values differing from + * GCC_ARM/IAR/standard POSIX definitions. Guard against this and future + * changes by changing the symbol definition for filesystem use. + */ +#define _IFMT 0170000 //< type of file +#define _IFSOCK 0140000 //< socket +#define _IFLNK 0120000 //< symbolic link +#define _IFREG 0100000 //< regular +#define _IFBLK 0060000 //< block special +#define _IFDIR 0040000 //< directory +#define _IFCHR 0020000 //< character special +#define _IFIFO 0010000 //< fifo special + +#define S_IFMT _IFMT //< type of file +#define S_IFSOCK _IFSOCK //< socket +#define S_IFLNK _IFLNK //< symbolic link +#define S_IFREG _IFREG //< regular +#define S_IFBLK _IFBLK //< block special +#define S_IFDIR _IFDIR //< directory +#define S_IFCHR _IFCHR //< character special +#define S_IFIFO _IFIFO //< fifo special + +#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) +#define S_IRUSR 0000400 ///< read permission, owner +#define S_IWUSR 0000200 ///< write permission, owner +#define S_IXUSR 0000100 ///< execute/search permission, owner +#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) +#define S_IRGRP 0000040 ///< read permission, group +#define S_IWGRP 0000020 ///< write permission, group +#define S_IXGRP 0000010 ///< execute/search permission, group +#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) +#define S_IROTH 0000004 ///< read permission, other +#define S_IWOTH 0000002 ///< write permission, other +#define S_IXOTH 0000001 ///< execute/search permission, other + +#ifndef HAVE_SYS_STAT_H + +/* Refer to sys/stat standard + * Note: Not all fields may be supported by the underlying filesystem + */ +struct stat { + dev_t st_dev; ///< Device ID containing file + ino_t st_ino; ///< File serial number + mode_t st_mode; ///< Mode of file + nlink_t st_nlink; ///< Number of links to file + + uid_t st_uid; ///< User ID + gid_t st_gid; ///< Group ID + + off_t st_size; ///< Size of file in bytes + + time_t st_atime; ///< Time of last access + time_t st_mtime; ///< Time of last data modification + time_t st_ctime; ///< Time of last status change +}; + +#endif + +struct statvfs { + unsigned long f_bsize; ///< Filesystem block size + unsigned long f_frsize; ///< Fragment size (block size) + + fsblkcnt_t f_blocks; ///< Number of blocks + fsblkcnt_t f_bfree; ///< Number of free blocks + fsblkcnt_t f_bavail; ///< Number of free blocks for unprivileged users + + unsigned long f_fsid; ///< Filesystem ID + + unsigned long f_namemax; ///< Maximum filename length +}; + +/* The following are dirent.h definitions are declared here to guarantee + * consistency where structure may be different with different toolchains + */ +struct dirent { + char d_name[NAME_MAX + 1]; ///< Name of file + uint8_t d_type; ///< Type of file +}; + +enum { + DT_UNKNOWN, ///< The file type could not be determined. + DT_FIFO, ///< This is a named pipe (FIFO). + DT_CHR, ///< This is a character device. + DT_DIR, ///< This is a directory. + DT_BLK, ///< This is a block device. + DT_REG, ///< This is a regular file. + DT_LNK, ///< This is a symbolic link. + DT_SOCK, ///< This is a UNIX domain socket. +}; + +/* fcntl.h defines */ +#define F_GETFL 3 +#define F_SETFL 4 + +struct pollfd { + int fd; + short events; + short revents; +}; + +/* POSIX-compatible I/O functions */ +#if __cplusplus +extern "C" { +#endif +#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY + int open(const char *path, int oflag, ...); +#ifndef __IAR_SYSTEMS_ICC__ /* IAR provides fdopen itself */ +#if __cplusplus + std::FILE *fdopen(int fildes, const char *mode); +#else + FILE *fdopen(int fildes, const char *mode); +#endif +#endif +#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY + ssize_t write(int fildes, const void *buf, size_t nbyte); + ssize_t read(int fildes, void *buf, size_t nbyte); + int fsync(int fildes); + int isatty(int fildes); +#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY + off_t lseek(int fildes, off_t offset, int whence); + int ftruncate(int fildes, off_t length); + int fstat(int fildes, struct stat *st); + int fcntl(int fildes, int cmd, ...); + int poll(struct pollfd fds[], nfds_t nfds, int timeout); + int close(int fildes); + int stat(const char *path, struct stat *st); + int statvfs(const char *path, struct statvfs *buf); + DIR *opendir(const char *); + struct dirent *readdir(DIR *); + int closedir(DIR *); + void rewinddir(DIR *); + long telldir(DIR *); + void seekdir(DIR *, long); + int mkdir(const char *name, mode_t n); +#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY +#if __cplusplus +} // extern "C" + +namespace mbed { +#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY +/** This call is an analogue to POSIX fdopen(). + * + * It associates a C stream to an already-opened FileHandle, to allow you to + * use C printf/scanf/fwrite etc. The provided FileHandle must remain open - + * it will be closed by the C library when fclose(FILE) is called. + * + * The net effect is fdopen(bind_to_fd(fh), mode), with error handling. + * + * @param fh a pointer to an opened FileHandle + * @param mode operation upon the file descriptor, e.g., "w+" + * + * @returns a pointer to FILE + */ +std::FILE *fdopen(mbed::FileHandle *fh, const char *mode); + +/** Bind an mbed FileHandle to a POSIX file descriptor + * + * This is similar to fdopen, but only operating at the POSIX layer - it + * associates a POSIX integer file descriptor with a FileHandle, to allow you + * to use POSIX read/write calls etc. The provided FileHandle must remain open - + * it will be closed when close(int) is called. + * + * @param fh a pointer to an opened FileHandle + * + * @return an integer file descriptor, or negative if no descriptors available + */ +int bind_to_fd(mbed::FileHandle *fh); + +#else +/** Targets may implement this to override how to write to the console. + * + * If the target has provided minimal_console_putc, this is called + * to give the target a chance to specify an alternative minimal console. + * + * If this is not provided, serial_putc will be used if + * `target.console-uart` is `true`, else there will not be an output. + * + * @param c The char to write + * @return The written char + */ +int minimal_console_putc(int c); + +/** Targets may implement this to override how to read from the console. + * + * If the target has provided minimal_console_getc, this is called + * to give the target a chance to specify an alternative minimal console. + * + * If this is not provided, serial_getc will be used if + * `target.console-uart` is `true`, else no input would be captured. + * + * @return The char read from the serial port + */ +int minimal_console_getc(); +#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY + +} // namespace mbed + +#endif // __cplusplus + +/**@}*/ + +/**@}*/ + +#endif /* RETARGET_H */ diff --git a/platform/include/platform/mbed_rtc_time.h b/platform/include/platform/mbed_rtc_time.h new file mode 100644 index 0000000..f85796b --- /dev/null +++ b/platform/include/platform/mbed_rtc_time.h @@ -0,0 +1,136 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_RTC_TIME_H__ +#define __MBED_RTC_TIME_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_rtc_time rtc_time functions + * @{ + */ + +/* Timeval definition for non GCC_ARM toolchains */ +#if !defined(__GNUC__) || defined(__clang__) +struct timeval { + time_t tv_sec; + int32_t tv_usec; +}; +#endif + +/** Implementation of the C time.h functions + * + * Provides mechanisms to set and read the current time, based + * on the microcontroller Real-Time Clock (RTC), plus some + * standard C manipulation and formatting functions. + * + * Example: + * @code + * #include "mbed.h" + * + * int main() { + * set_time(1256729737); // Set RTC time to Wed, 28 Oct 2009 11:35:37 + * + * while (true) { + * time_t seconds = time(NULL); + * + * printf("Time as seconds since January 1, 1970 = %u\n", (unsigned int)seconds); + * + * printf("Time as a basic string = %s", ctime(&seconds)); + * + * char buffer[32]; + * strftime(buffer, 32, "%I:%M %p\n", localtime(&seconds)); + * printf("Time as a custom formatted string = %s", buffer); + * + * ThisThread::sleep_for(1000); + * } + * } + * @endcode + */ + +/** Set the current time + * + * 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). + * + * @param t Number of seconds since January 1, 1970 (the UNIX timestamp) + * + * @note Synchronization level: Thread safe + * + * Example: + * @code + * #include "mbed.h" + * + * int main() { + * set_time(1256729737); // Set time to Wed, 28 Oct 2009 11:35:37 + * } + * @endcode + */ +void set_time(time_t t); + +/** Attach an external RTC to be used for the C time functions + * + * @note Synchronization level: Thread safe + * + * @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 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)); + +/** Standard lib retarget, get time since Epoch + * + * @param tv Structure containing time_t seconds and useconds_t microseconds. Due to + * separate target specific RTC implementations only the seconds component is used. + * @param tz DEPRECATED IN THE STANDARD: This parameter is left in for legacy code. It is + * not used. + * @return 0 on success, -1 on a failure. + * @note Synchronization level: Thread safe + * + */ +int gettimeofday(struct timeval *tv, void *tz); + +/** Standard lib retarget, set time since Epoch + * + * @param tv Structure containing time_t seconds and useconds_t microseconds. Due to + * separate target specific RTC implementations only the seconds component is used. + * @param tz DEPRECATED IN THE STANDARD: This parameter is left in for legacy code. It is + * not used. + * @return Time in seconds on success, -1 on a failure. + * @note Synchronization level: Thread safe + * + */ +int settimeofday(const struct timeval *tv, const struct timezone *tz); + +#ifdef __cplusplus +} +#endif + +/** @}*/ +/** @}*/ + +#endif /* __MBED_RTC_TIME_H__ */ diff --git a/platform/include/platform/mbed_semihost_api.h b/platform/include/platform/mbed_semihost_api.h new file mode 100644 index 0000000..020e21a --- /dev/null +++ b/platform/include/platform/mbed_semihost_api.h @@ -0,0 +1,98 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_SEMIHOST_H +#define MBED_SEMIHOST_H + +#include "device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if DEVICE_SEMIHOST + +#if !defined(__ARMCC_VERSION) + +#if defined(__ICCARM__) +static inline int __semihost(int reason, const void *arg) +{ + return __semihosting(reason, (void *)arg); +} +#else + +#ifdef __thumb__ +# define AngelSWI 0xAB +# define AngelSWIInsn "bkpt" +# define AngelSWIAsm bkpt +#else +# define AngelSWI 0x123456 +# define AngelSWIInsn "swi" +# define AngelSWIAsm swi +#endif + +static inline int __semihost(int reason, const void *arg) +{ + int value; + + asm volatile( + "mov r0, %1" "\n\t" + "mov r1, %2" "\n\t" + AngelSWIInsn " %a3" "\n\t" + "mov %0, r0" + : "=r"(value) /* output operands */ + : "r"(reason), "r"(arg), "i"(AngelSWI) /* input operands */ + : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc" /* list of clobbered registers */ + ); + + return value; +} +#endif +#endif + +#if DEVICE_LOCALFILESYSTEM +FILEHANDLE semihost_open(const char *name, int openmode); +int semihost_close(FILEHANDLE fh); +int semihost_read(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode); +int semihost_write(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode); +int semihost_ensure(FILEHANDLE fh); +long semihost_flen(FILEHANDLE fh); +int semihost_seek(FILEHANDLE fh, long position); +int semihost_istty(FILEHANDLE fh); + +int semihost_remove(const char *name); +int semihost_rename(const char *old_name, const char *new_name); +#endif + +int semihost_uid(char *uid); +int semihost_reset(void); +int semihost_vbus(void); +int semihost_powerdown(void); +int semihost_exit(void); + +int semihost_connected(void); +int semihost_disabledebug(void); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/platform/include/platform/mbed_stats.h b/platform/include/platform/mbed_stats.h new file mode 100644 index 0000000..f331c65 --- /dev/null +++ b/platform/include/platform/mbed_stats.h @@ -0,0 +1,185 @@ +/* mbed Microcontroller Library + * Copyright (c) 2016-2019 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_STATS_H +#define MBED_STATS_H +#include +#include +#include "hal/ticker_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_stats stats functions + * @{ + */ + +#ifdef MBED_ALL_STATS_ENABLED + +#ifndef MBED_SYS_STATS_ENABLED +#define MBED_SYS_STATS_ENABLED 1 +#endif +#ifndef MBED_STACK_STATS_ENABLED +#define MBED_STACK_STATS_ENABLED 1 +#endif +#ifndef MBED_CPU_STATS_ENABLED +#define MBED_CPU_STATS_ENABLED 1 +#endif +#ifndef MBED_HEAP_STATS_ENABLED +#define MBED_HEAP_STATS_ENABLED 1 +#endif +#ifndef MBED_THREAD_STATS_ENABLED +#define MBED_THREAD_STATS_ENABLED 1 +#endif + +#endif // MBED_ALL_STATS_ENABLED + +/** Maximum memory regions reported by mbed-os memory statistics */ +#define MBED_MAX_MEM_REGIONS 4 + +/** + * struct mbed_stats_heap_t definition + */ +typedef struct { + 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 the heap statistics. + * + * @param stats A pointer to the mbed_stats_heap_t structure to fill + */ +void mbed_stats_heap_get(mbed_stats_heap_t *stats); + +/** + * struct mbed_stats_stack_t definition + */ +typedef struct { + 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 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 + */ +void mbed_stats_stack_get(mbed_stats_stack_t *stats); + +/** + * 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. + * 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); + +/** + * struct mbed_stats_cpu_t definition + */ +typedef struct { + 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; + +/** + * Fill the passed in CPU stat structure with CPU statistics. + * + * @param stats A pointer to the mbed_stats_cpu_t structure to fill + */ +void mbed_stats_cpu_get(mbed_stats_cpu_t *stats); + +/** + * struct mbed_stats_thread_t definition + */ +typedef struct { + 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 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. + * 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); + +/** + * enum mbed_compiler_id_t definition + */ +typedef enum { + ARM = 1, /**< ARM */ + GCC_ARM, /**< GNU ARM */ + IAR /**< IAR */ +} mbed_compiler_id_t; + +/** + * struct mbed_stats_sys_t definition + */ +typedef struct { + 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 */ + uint32_t ram_start[MBED_MAX_MEM_REGIONS]; /**< Start addresses of all internal RAM memories */ + uint32_t ram_size[MBED_MAX_MEM_REGIONS]; /**< Size of all internal RAM memories in target */ + uint32_t rom_start[MBED_MAX_MEM_REGIONS]; /**< Start addresses of all internal ROM memories */ + uint32_t rom_size[MBED_MAX_MEM_REGIONS]; /**< Size of all internal ROM memories in target */ +} mbed_stats_sys_t; + +/** + * Fill the passed in system stat structure with system statistics. + * + * @param stats A pointer to the mbed_stats_sys_t structure to fill + */ +void mbed_stats_sys_get(mbed_stats_sys_t *stats); + +#ifdef __cplusplus +} +#endif + +#endif + +/** @}*/ + +/** @}*/ diff --git a/platform/include/platform/mbed_thread.h b/platform/include/platform/mbed_thread.h new file mode 100644 index 0000000..8b9fff1 --- /dev/null +++ b/platform/include/platform/mbed_thread.h @@ -0,0 +1,75 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 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_THREAD_H +#define MBED_THREAD_H +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup mbed_thread Mbed Thread + * \ingroup platform-public-api + * @{ + */ + +/** Generic thread functions. + * + * These are C versions of functions provided in C++ via rtos::Thread and rtos::ThisThread + */ + +/** Read the current RTOS kernel millisecond tick count. + 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 In a non-RTOS build, this computes an equivalent time in milliseconds, + based on a HAL timer. The time may be referenced as 0 on first call. + @note You cannot call this function from ISR context. + @note The equivalent functionality is accessible in C++ via rtos::Kernel::get_ms_count. + */ +uint64_t get_ms_count(void); + +/** Sleep for a specified time period in millisec: + @param millisec time delay value + @note You cannot call this function from ISR context. + @note The equivalent functionality is accessible in C++ via rtos::ThisThread::sleep_for. +*/ +void thread_sleep_for(uint32_t millisec); + +/** Sleep until a specified time in millisec + The specified time is according to Kernel::get_ms_count(). + @param millisec absolute time in millisec + @note You cannot call this function from ISR context. + @note if millisec is equal to or lower than the current tick count, this + returns immediately. + @note The equivalent functionality is accessible in C++ via ThisThread::sleep_until. +*/ +void thread_sleep_until(uint64_t millisec); + +/** @}*/ + +#ifdef __cplusplus +} +#endif + + +#endif //MBED_THREAD_H diff --git a/platform/include/platform/mbed_toolchain.h b/platform/include/platform/mbed_toolchain.h new file mode 100644 index 0000000..2fa91d6 --- /dev/null +++ b/platform/include/platform/mbed_toolchain.h @@ -0,0 +1,562 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_TOOLCHAIN_H +#define MBED_TOOLCHAIN_H + +#include "platform/mbed_preprocessor.h" + +/* Workaround to prevent GCC library defining error_t, which can collide */ +#ifndef __error_t_defined +#define __error_t_defined 1 +#endif + +/* Work around ARM Compiler 6 bug - assert does not work in constexpr + * functions unless you stop it from using its __promise built-in. + */ +#ifdef __ARMCC_VERSION +#ifndef __DO_NOT_LINK_PROMISE_WITH_ASSERT +#define __DO_NOT_LINK_PROMISE_WITH_ASSERT +#endif +#endif + +// Warning for unsupported compilers +#if !defined(__GNUC__) /* GCC */ \ + && !defined(__clang__) /* LLVM/Clang */ \ + && !defined(__ICCARM__) /* IAR */ +#warning "This compiler is not yet supported." +#endif + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_toolchain Toolchain functions + * @{ + */ + +// Attributes + +/** MBED_PACKED + * Pack a structure, preventing any padding from being added between fields. + * + * @code + * #include "mbed_toolchain.h" + * + * MBED_PACKED(struct) foo { + * char x; + * int y; + * }; + * @endcode + */ +#ifndef MBED_PACKED +#if defined(__ICCARM__) +#define MBED_PACKED(struct) __packed struct +#else +#define MBED_PACKED(struct) struct __attribute__((packed)) +#endif +#endif + +/** MBED_ALIGN(N) + * Declare a variable to be aligned on an N-byte boundary. + * + * @note + * IAR does not support alignment greater than word size on the stack + * + * @code + * #include "mbed_toolchain.h" + * + * MBED_ALIGN(16) char a; + * @endcode + */ +#ifndef MBED_ALIGN +#if __cplusplus >= 201103 +#define MBED_ALIGN(N) alignas(N) +#elif __STDC_VERSION__ >= 201112 +#define MBED_ALIGN(N) _Alignas(N) +#elif defined(__ICCARM__) +#define MBED_ALIGN(N) _Pragma(MBED_STRINGIFY(data_alignment=N)) +#else +#define MBED_ALIGN(N) __attribute__((aligned(N))) +#endif +#endif + +/** MBED_UNUSED + * Declare a function argument to be unused, suppressing compiler warnings + * + * @code + * #include "mbed_toolchain.h" + * + * void foo(MBED_UNUSED int arg) { + * + * } + * @endcode + */ +#ifndef MBED_UNUSED +#if defined(__GNUC__) || defined(__clang__) +#define MBED_UNUSED __attribute__((__unused__)) +#else +#define MBED_UNUSED +#endif +#endif + +/** MBED_USED + * Inform the compiler that a static variable is to be retained in the object file, even if it is unreferenced. + * + * @code + * #include "mbed_toolchain.h" + * + * MBED_USED int foo; + * + * @endcode + */ +#ifndef MBED_USED +#if defined(__GNUC__) || defined(__clang__) +#define MBED_USED __attribute__((used)) +#elif defined(__ICCARM__) +#define MBED_USED __root +#else +#define MBED_USED +#endif +#endif + +/** MBED_WEAK + * Mark a function as being weak. + * + * @note + * Functions should only be marked as weak in the source file. The header file + * should contain a regular function declaration to insure the function is emitted. + * A function marked weak will not be emitted if an alternative non-weak + * implementation is defined. + * + * @note + * Weak functions are not friendly to making code re-usable, as they can only + * be overridden once (and if they are multiply overridden the linker will emit + * no warning). You should not normally use weak symbols as part of the API to + * re-usable modules. + * + * @code + * #include "mbed_toolchain.h" + * + * MBED_WEAK void foo() { + * // a weak implementation of foo that can be overriden by a definition + * // without __weak + * } + * @endcode + */ +#ifndef MBED_WEAK +#if defined(__ICCARM__) +#define MBED_WEAK __weak +#elif defined(__MINGW32__) +#define MBED_WEAK +#else +#define MBED_WEAK __attribute__((weak)) +#endif +#endif + +/** MBED_COMPILER_BARRIER + * Stop the compiler moving memory accesses. + * + * The barrier stops memory accesses from being moved from one side of the + * barrier to the other for safety against other threads and interrupts. + * + * This macro should only be used if we know only one CPU is accessing the data, + * or we are otherwise synchronising CPUs via acquire/release instructions. + * Otherwise, use MBED_BARRIER, which will act as a compiler barrier and also + * a CPU barrier if necessary. + * + * @internal + * This is not for use by normal code - it is a building block for the + * higher-level functions in mbed_critical.h. Higher-level lock/unlock or + * acquire/release APIs always provide ordering semantics, using this if + * necessary. + * + * @code + * #include "mbed_toolchain.h" + * + * void atomic_flag_clear_armv8(atomic_flag *flagPtr) + * { + * // ARMv8 LDA and STL instructions provide sequential consistency against + * // other CPUs, so no CPU barrier is needed. But we still need compiler + * // barriers to give us sequentially-consistent release semantics with + * // respect to compiler reordering - __STLB does not currently + * // include this. + * MBED_COMPILER_BARRIER(); + * __STLB(&flagPtr->_flag, false); + * MBED_COMPILER_BARRIER(); + * } + */ +#if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__) +#define MBED_COMPILER_BARRIER() asm volatile("" : : : "memory") +#else +#error "Missing MBED_COMPILER_BARRIER implementation" +#endif + +/** MBED_BARRIER + * Stop the compiler, and CPU if SMP, from moving memory accesses. + * + * The barrier stops memory accesses from being moved from one side of the + * barrier to the other for safety against other threads and interrupts, + * potentially on other CPUs. + * + * In a single-CPU system, this is just a compiler barrier. + * If we supported multiple CPUs, this would be a DMB (with implied compiler + * barrier). + * + * @internal + * This is not for use by normal code - it is a building block for the + * higher-level functions in mbed_critical.h. Higher-level lock/unlock or + * acquire/release APIs always provide ordering semantics, using this if + * necessary. + * @code + * #include "mbed_toolchain.h" + * + * void atomic_flag_clear_armv7(atomic_flag *flagPtr) + * { + * // ARMv7 LDR and STR instructions do not provide any ordering + * // consistency against other CPUs, so explicit barrier DMBs are needed + * // for a multi-CPU system, otherwise just compiler barriers for single-CPU. + * MBED_BARRIER(); + * flagPtr->_flag = false; + * MBED_BARRIER(); + * } + */ +#define MBED_BARRIER() MBED_COMPILER_BARRIER() + +/** MBED_PURE + * Hint to the compiler that a function depends only on parameters + * + * @code + * #include "mbed_toolchain.h" + * + * MBED_PURE int foo(int arg){ + * // no access to global variables + * } + * @endcode + */ +#ifndef MBED_PURE +#if defined(__GNUC__) || defined(__clang__) +#define MBED_PURE __attribute__((const)) +#else +#define MBED_PURE +#endif +#endif + +/** MBED_NOINLINE + * Declare a function that must not be inlined. + * + * @code + * #include "mbed_toolchain.h" + * + * MBED_NOINLINE void foo() { + * + * } + * @endcode + */ +#ifndef MBED_NOINLINE +#if defined(__GNUC__) || defined(__clang__) +#define MBED_NOINLINE __attribute__((noinline)) +#elif defined(__ICCARM__) +#define MBED_NOINLINE _Pragma("inline=never") +#else +#define MBED_NOINLINE +#endif +#endif + +/** MBED_FORCEINLINE + * Declare a function that must always be inlined. Failure to inline + * such a function will result in an error. + * + * @code + * #include "mbed_toolchain.h" + * + * MBED_FORCEINLINE void foo() { + * + * } + * @endcode + */ +#ifndef MBED_FORCEINLINE +#if defined(__GNUC__) || defined(__clang__) +#define MBED_FORCEINLINE inline __attribute__((always_inline)) +#elif defined(__ICCARM__) +#define MBED_FORCEINLINE _Pragma("inline=forced") +#else +#define MBED_FORCEINLINE inline +#endif +#endif + +/** MBED_NORETURN + * Declare a function that will never return. + * + * @code + * #include "mbed_toolchain.h" + * + * MBED_NORETURN void foo() { + * // must never return + * while (1) {} + * } + * @endcode + */ +#ifndef MBED_NORETURN +#if __cplusplus >= 201103 +#define MBED_NORETURN [[noreturn]] +#elif __STDC_VERSION__ >= 201112 +#define MBED_NORETURN _Noreturn +#elif defined(__GNUC__) || defined(__clang__) +#define MBED_NORETURN __attribute__((noreturn)) +#elif defined(__ICCARM__) +#define MBED_NORETURN __noreturn +#else +#define MBED_NORETURN +#endif +#endif + +/** MBED_UNREACHABLE + * An unreachable statement. If the statement is reached, + * behavior is undefined. Useful in situations where the compiler + * cannot deduce if the code is unreachable. + * + * @code + * #include "mbed_toolchain.h" + * + * void foo(int arg) { + * switch (arg) { + * case 1: return 1; + * case 2: return 2; + * ... + * } + * MBED_UNREACHABLE; + * } + * @endcode + */ +#ifndef MBED_UNREACHABLE +#if (defined(__GNUC__) || defined(__clang__)) +#define MBED_UNREACHABLE __builtin_unreachable() +#else +#define MBED_UNREACHABLE while (1) +#endif +#endif + +/** MBED_FALLTHROUGH + * Marks a point in a switch statement where fallthrough can occur. + * Should be placed as the last statement before a label. + * + * @code + * #include "mbed_toolchain.h" + * + * int foo(int arg) { + * switch (arg) { + * case 1: + * case 2: + * case 3: + * arg *= 2; + * MBED_FALLTHROUGH; + * default: + * return arg; + * } + * } + * @endcode + */ +#ifndef MBED_FALLTHROUGH +#if __cplusplus >= 201703 +#define MBED_FALLTHROUGH [[fallthrough]] +#elif defined(__clang__) +#if __cplusplus >= 201103 +#define MBED_FALLTHROUGH [[clang::fallthrough]] +#elif __has_attribute(fallthrough) +#define MBED_FALLTHROUGH __attribute__((fallthrough)) +#else +#define MBED_FALLTHROUGH +#endif +#elif defined (__GNUC__) +#define MBED_FALLTHROUGH __attribute__((fallthrough)) +#else +#define MBED_FALLTHROUGH +#endif +#endif + +/** MBED_DEPRECATED("message string") + * Mark a function declaration as deprecated, if it used then a warning will be + * issued by the compiler possibly including the provided message. Note that not + * all compilers are able to display the message. + * + * @code + * #include "mbed_toolchain.h" + * + * MBED_DEPRECATED("don't foo any more, bar instead") + * void foo(int arg); + * @endcode + */ +#ifndef MBED_DEPRECATED +#if defined(__GNUC__) || defined(__clang__) +#define MBED_DEPRECATED(M) __attribute__((deprecated(M))) +#else +#define MBED_DEPRECATED(M) +#endif +#endif + +/** MBED_DEPRECATED_SINCE("version", "message string") + * Mark a function declaration as deprecated, noting that the declaration was + * deprecated on the specified version. If the function is used then a warning + * will be issued by the compiler possibly including the provided message. + * Note that not all compilers are able to display this message. + * + * @code + * #include "mbed_toolchain.h" + * + * MBED_DEPRECATED_SINCE("mbed-os-5.1", "don't foo any more, bar instead") + * void foo(int arg); + * @endcode + */ +#define MBED_DEPRECATED_SINCE(D, M) MBED_DEPRECATED(M " [since " D "]") + +/** MBED_CALLER_ADDR() + * Returns the caller of the current function. + * + * @note + * This macro is only implemented for GCC and ARMCC. + * + * @code + * #include "mbed_toolchain.h" + * + * printf("This function was called from %p", MBED_CALLER_ADDR()); + * @endcode + * + * @return Address of the calling function + */ +#ifndef MBED_CALLER_ADDR +#if (defined(__GNUC__) || defined(__clang__)) +#define MBED_CALLER_ADDR() __builtin_extract_return_addr(__builtin_return_address(0)) +#else +#define MBED_CALLER_ADDR() (NULL) +#endif +#endif + +#ifndef MBED_SECTION +#if (defined(__GNUC__) || defined(__clang__)) +#define MBED_SECTION(name) __attribute__ ((section (name))) +#elif defined(__ICCARM__) +#define MBED_SECTION(name) _Pragma(MBED_STRINGIFY(location=name)) +#else +#error "Missing MBED_SECTION directive" +#endif +#endif + +/** + * Macro expanding to a string literal of the enclosing function name. + * + * The string returned takes into account language specificity and yield human + * readable content. + * + * As an example, if the macro is used within a C++ function then the string + * literal containing the function name will contain the complete signature of + * the function - including template parameters - and namespace qualifications. + */ +#ifndef MBED_PRETTY_FUNCTION +#define MBED_PRETTY_FUNCTION __PRETTY_FUNCTION__ +#endif + +#ifndef MBED_PRINTF +#if defined(__GNUC__) +#define MBED_PRINTF(format_idx, first_param_idx) __attribute__ ((__format__(__printf__, format_idx, first_param_idx))) +#else +#define MBED_PRINTF(format_idx, first_param_idx) +#endif +#endif + +#ifndef MBED_PRINTF_METHOD +#if defined(__GNUC__) +#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 +#endif + +#ifndef MBED_SCANF +#if defined(__GNUC__) +#define MBED_SCANF(format_idx, first_param_idx) __attribute__ ((__format__(__scanf__, format_idx, first_param_idx))) +#else +#define MBED_SCANF(format_idx, first_param_idx) +#endif +#endif + +#ifndef MBED_SCANF_METHOD +#if defined(__GNUC__) +#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 +#endif + +// Macro containing the filename part of the value of __FILE__. Defined as +// string literal. +#ifndef MBED_FILENAME +#if defined(__GNUC__) +#define MBED_FILENAME (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __builtin_strrchr(__FILE__, '\\') ? __builtin_strrchr(__FILE__, '\\') + 1 : __FILE__) +#elif defined(__ICCARM__) +#define MBED_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) +#else +#define MBED_FILENAME __FILE__ +#endif +#endif // #ifndef MBED_FILENAME + +// FILEHANDLE declaration +#if defined(TOOLCHAIN_ARM) +#include +#endif + +#ifndef FILEHANDLE +typedef int FILEHANDLE; +#endif + +// Backwards compatibility +#ifndef WEAK +#define WEAK MBED_WEAK +#endif + +#ifndef PACKED +#define PACKED MBED_PACKED() +#endif + +#ifndef EXTERN +#define EXTERN extern +#endif + +/** MBED_NONSECURE_ENTRY + * Declare a function that can be called from non-secure world or secure world + * + * @code + * #include "mbed_toolchain.h" + * + * MBED_NONSECURE_ENTRY void foo() { + * + * } + * @endcode + */ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3L) +#if defined (__ICCARM__) +#define MBED_NONSECURE_ENTRY __cmse_nonsecure_entry +#else +#define MBED_NONSECURE_ENTRY __attribute__((cmse_nonsecure_entry)) +#endif +#else +#define MBED_NONSECURE_ENTRY +#endif + +#endif + +/** @}*/ +/** @}*/ diff --git a/platform/include/platform/mbed_version.h b/platform/include/platform/mbed_version.h new file mode 100644 index 0000000..4eb8703 --- /dev/null +++ b/platform/include/platform/mbed_version.h @@ -0,0 +1,73 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2019 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_VERSION_H +#define MBED_VERSION_H + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_version Version macros + * @{ + */ + +/** MBED_MAJOR_VERSION + * Mbed OS major version + * + * @note 99 is default value for development version (master branch) + */ +#define MBED_MAJOR_VERSION 6 + +/** MBED_MINOR_VERSION + * Mbed OS minor version + * + * @note 99 is default value for development version (master branch) + */ +#define MBED_MINOR_VERSION 2 + +/** MBED_PATCH_VERSION + * Mbed OS patch version + * + * @note 99 is default value for development version (master branch) + */ +#define MBED_PATCH_VERSION 0 + +#define MBED_ENCODE_VERSION(major, minor, patch) ((major)*10000 + (minor)*100 + (patch)) + +/** MBED_VERSION + * Mbed OS 5 version (MMmmpp - M(Major); m(minor); p(patch)) + * + * @note 999999 is default value for development version (master branch) + */ +#define MBED_VERSION MBED_ENCODE_VERSION(MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION) + +/** MBED_VERSION_CHECK + * Macro can be used to check minimum Mbed OS version required for feature/library. If current version + * is less than required, it will assert. + * + * @note: Version of master branch will be 999999 as default, hence no assert/warning is provided for + * master branch code + */ +#define MBED_VERSION_CHECK(major, minor, patch) do { \ + MBED_STATIC_ASSERT((MBED_VERSION >= MBED_ENCODE_VERSION((major),(minor),(patch))), "Incompatible mbed-os version detected!!"); \ + } while(0) + +#endif + +/** @}*/ +/** @}*/ diff --git a/platform/include/platform/mbed_wait_api.h b/platform/include/platform/mbed_wait_api.h new file mode 100644 index 0000000..a6f85be --- /dev/null +++ b/platform/include/platform/mbed_wait_api.h @@ -0,0 +1,156 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 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_WAIT_API_H +#define MBED_WAIT_API_H + +#include "platform/mbed_toolchain.h" +#include "platform/mbed_atomic.h" +#include "device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup platform-public-api */ +/** @{*/ + +/** + * \defgroup platform_wait_api wait_api functions + * @{ + */ + +/** Generic wait functions. + * + * These provide simple NOP type wait capabilities. + * + * Example: + * @code + * #include "mbed.h" + * + * // Blinking rate in milliseconds + * #define BLINKING_RATE_MS 500 + * DigitalOut led(LED2); + * InterruptIn button(SW2); + * + * void blink_led() { + * led = 1; + * wait_us(BLINKING_RATE_MS * 1000); + * led = 0; + * } + * + * int main() { + * button.fall(&blink_led); + * while(1) { + * // Do nothing + * } + * } + * @endcode + */ + +/** Waits a number of microseconds. + * + * @param us the whole number of microseconds to wait + * + * @note + * This function always spins to get the exact number of microseconds. + * This will affect power and multithread performance. Therefore, spinning for + * millisecond wait is not recommended, and ThisThread::sleep_for should + * be used instead. + * + * @note You may call this function from ISR context, but large delays may + * impact system stability - interrupt handlers should take less than + * 50us. + */ +void wait_us(int us); + +/** Waits a number of nanoseconds. + * + * This function spins the CPU to produce a small delay. It should normally + * only be used for delays of 10us (10000ns) or less. As it is calculated + * based on the expected execution time of a software loop, it may well run + * slower than requested based on activity from other threads and interrupts. + * If greater precision is required, this can be called from inside a critical + * section. + * + * @param ns the number of nanoseconds to wait + * + * @note + * wait_us() will likely give more precise time than wait_ns for large-enough + * delays, as it is based on a timer, but its set-up time may be excessive + * for the smallest microsecond counts, at which point wait_ns() is better. + * + * @note + * Any delay larger than a millisecond (1000000ns) is liable to cause + * overflow in the internal loop calculation. You shouldn't normally be + * using this for such large delays anyway in real code, but be aware if + * calibrating. Make repeated calls for longer test runs. + * + * @note You may call this function from ISR context. + * + */ +void wait_ns(unsigned int ns); + +/* Optimize if we know the rate */ +#if DEVICE_USTICKER && defined US_TICKER_PERIOD_NUM +void _wait_us_ticks(uint32_t ticks); +void _wait_us_generic(unsigned int us); + +/* Further optimization if we know us_ticker is always running */ +#if MBED_CONF_TARGET_INIT_US_TICKER_AT_BOOT +#define _us_ticker_is_initialized true +#else +extern bool _us_ticker_initialized; +#define _us_ticker_is_initialized core_util_atomic_load_bool(&_us_ticker_initialized) +#endif + +#if US_TICKER_PERIOD_DEN == 1 && (US_TICKER_MASK * US_TICKER_PERIOD_NUM) >= 0xFFFFFFFF +/* Ticker is wide and slow enough to have full 32-bit range - can always use it directly */ +#define _us_is_small_enough(us) true +#else +/* Threshold is determined by specification of us_ticker_api.h - smallest possible + * time range for the us_ticker is 16-bit 8MHz, which gives 8192us. This also leaves + * headroom for the multiplication in 32 bits. + */ +#define _us_is_small_enough(us) ((us) < 8192) +#endif + +/* Speed optimisation for small wait_us. Care taken to preserve binary compatibility */ +inline void _wait_us_inline(unsigned int us) +{ + /* Threshold is determined by specification of us_ticker_api.h - smallest possible + * time range for the us_ticker is 16-bit 8MHz, which gives 8192us. This also leaves + * headroom for the multiplication in 32 bits. + */ + if (_us_is_small_enough(us) && _us_ticker_is_initialized) { + const uint32_t ticks = ((us * US_TICKER_PERIOD_DEN) + US_TICKER_PERIOD_NUM - 1) / US_TICKER_PERIOD_NUM; + _wait_us_ticks(ticks); + } else { + _wait_us_generic(us); + } +} + +#define wait_us(us) _wait_us_inline(us) +#endif // Known-rate, initialised timer + +#ifdef __cplusplus +} +#endif + +#endif + +/** @}*/ +/** @}*/ diff --git a/platform/include/platform/platform.h b/platform/include/platform/platform.h new file mode 100644 index 0000000..3268c7c --- /dev/null +++ b/platform/include/platform/platform.h @@ -0,0 +1,36 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 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_PLATFORM_H +#define MBED_PLATFORM_H + +#include +#include +#include +#include + +#include "platform/mbed_retarget.h" +#include "platform/mbed_toolchain.h" +#include "device.h" +#include "PinNames.h" +#include "PeripheralNames.h" + +/** \defgroup platform-public-api Platform + * \ingroup mbed-os-public + */ + +#endif diff --git a/platform/internal/CThunkBase.h b/platform/internal/CThunkBase.h deleted file mode 100644 index 212ff44..0000000 --- a/platform/internal/CThunkBase.h +++ /dev/null @@ -1,88 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018-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 __CTHUNK_BASE_H__ -#define __CTHUNK_BASE_H__ - -/** \defgroup platform-internal-api Platform - * \ingroup mbed-os-internal - */ - -/* IRQ/Exception compatible thunk entry function */ -typedef void (*CThunkEntry)(void); - -/** - * \defgroup platform_CThunkBase CThunkBase class - * \ingroup platform-internal-api - * @{ - */ -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/internal/mbed_atomic_impl.h b/platform/internal/mbed_atomic_impl.h deleted file mode 100644 index b29a0ae..0000000 --- a/platform/internal/mbed_atomic_impl.h +++ /dev/null @@ -1,1358 +0,0 @@ -/* - * Copyright (c) 2015-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 - * - * 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_ATOMIC_IMPL_H__ -#define __MBED_ATOMIC_IMPL_H__ - -#ifndef __MBED_UTIL_ATOMIC_H__ -#error "mbed_atomic_impl.h is designed to be included only by mbed_atomic.h" -#endif - -#include -#include "cmsis.h" -#include "platform/mbed_assert.h" -#include "platform/mbed_toolchain.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef MBED_DEBUG -/* Plain loads must not have "release" or "acquire+release" order */ -#define MBED_CHECK_LOAD_ORDER(order) MBED_ASSERT((order) != mbed_memory_order_release && (order) != mbed_memory_order_acq_rel) - -/* Plain stores must not have "consume", "acquire" or "acquire+release" order */ -#define MBED_CHECK_STORE_ORDER(order) MBED_ASSERT((order) != mbed_memory_order_consume && (order) != mbed_memory_order_acquire && (order) != mbed_memory_order_acq_rel) - -/* Compare exchange needs failure order no stronger than success, and failure can't be "release" or "acquire+release" */ -#define MBED_CHECK_CAS_ORDER(success, failure) \ - MBED_ASSERT((failure) <= (success) && (failure) != mbed_memory_order_release && (failure) != mbed_memory_order_acq_rel) -#else -#define MBED_CHECK_LOAD_ORDER(order) (void)0 -#define MBED_CHECK_STORE_ORDER(order) (void)0 -#define MBED_CHECK_CAS_ORDER(success, failure) (void)0 -#endif - -/* This is currently just to silence unit tests, so no better test required */ -#ifdef __MBED__ -#define MBED_ATOMIC_PTR_SIZE 32 -#else -#define MBED_ATOMIC_PTR_SIZE 64 -#endif - -/* Place barrier after a load or read-modify-write if a consume or acquire operation */ -#define MBED_ACQUIRE_BARRIER(order) do { \ - if ((order) & (mbed_memory_order_consume|mbed_memory_order_acquire)) { \ - MBED_BARRIER(); \ - } } while (0) - -/* Place barrier before a store or read-modify-write if a release operation */ -#define MBED_RELEASE_BARRIER(order) do { \ - if ((order) & mbed_memory_order_release) { \ - MBED_BARRIER(); \ - } } while (0) - -/* Place barrier after a plain store if a sequentially consistent */ -#define MBED_SEQ_CST_BARRIER(order) do { \ - if ((order) == mbed_memory_order_seq_cst) { \ - MBED_BARRIER(); \ - } } while (0) - - - -#if MBED_EXCLUSIVE_ACCESS - -/* This header file provides C inline definitions for atomic functions. */ -/* For C99 inline semantic compatibility, mbed_atomic_impl.c has out-of-line definitions. */ - -/****************************** ASSEMBLER **********************************/ - -// Fiddle about with constraints. These work for GCC and clang, but -// IAR appears to be restricted to having only a single constraint, -// so we can't do immediates. -#if MBED_EXCLUSIVE_ACCESS_THUMB1 -#define MBED_DOP_REG "l" // Need low register to get 16-bit 3-op ADD/SUB -#define MBED_CMP_IMM "I" // CMP 8-bit immediate -#define MBED_SUB3_IMM "L" // -7 to +7 -#else -#define MBED_DOP_REG "r" // Can use 32-bit 3-op ADD/SUB, so any registers -#define MBED_CMP_IMM "IL" // CMP or CMN, 12-bit immediate -#define MBED_SUB3_IMM "IL" // SUB or ADD, 12-bit immediate -#endif - -#if defined __clang__ || defined __GNUC__ -#define DO_MBED_LOCKFREE_EXCHG_ASM(M) \ - __asm volatile ( \ - ".syntax unified\n\t" \ - "LDREX"#M "\t%[oldValue], %[value]\n\t" \ - "STREX"#M "\t%[fail], %[newValue], %[value]\n\t" \ - : [oldValue] "=&r" (oldValue), \ - [fail] "=&r" (fail), \ - [value] "+Q" (*valuePtr) \ - : [newValue] "r" (newValue) \ - : \ - ) -#elif defined __ICCARM__ -/* In IAR "r" means low register if Thumbv1 (there's no way to specify any register...) */ -#define DO_MBED_LOCKFREE_EXCHG_ASM(M) \ - asm volatile ( \ - "LDREX"#M "\t%[oldValue], [%[valuePtr]]\n" \ - "STREX"#M "\t%[fail], %[newValue], [%[valuePtr]]\n" \ - : [oldValue] "=&r" (oldValue), \ - [fail] "=&r" (fail) \ - : [valuePtr] "r" (valuePtr), \ - [newValue] "r" (newValue) \ - : "memory" \ - ) -#endif - -#if defined __clang__ || defined __GNUC__ -#define DO_MBED_LOCKFREE_NEWVAL_2OP_ASM(OP, Constants, M) \ - __asm volatile ( \ - ".syntax unified\n\t" \ - "LDREX"#M "\t%[newValue], %[value]\n\t" \ - #OP "\t%[newValue], %[arg]\n\t" \ - "STREX"#M "\t%[fail], %[newValue], %[value]\n\t" \ - : [newValue] "=&" MBED_DOP_REG (newValue), \ - [fail] "=&r" (fail), \ - [value] "+Q" (*valuePtr) \ - : [arg] Constants MBED_DOP_REG (arg) \ - : "cc" \ - ) -#elif defined __ICCARM__ -/* In IAR "r" means low register if Thumbv1 (there's no way to specify any register...) */ -/* IAR does not support "ADDS reg, reg", so write as 3-operand */ -#define DO_MBED_LOCKFREE_NEWVAL_2OP_ASM(OP, Constants, M) \ - asm volatile ( \ - "LDREX"#M "\t%[newValue], [%[valuePtr]]\n" \ - #OP "\t%[newValue], %[newValue], %[arg]\n" \ - "STREX"#M "\t%[fail], %[newValue], [%[valuePtr]]\n" \ - : [newValue] "=&r" (newValue), \ - [fail] "=&r" (fail) \ - : [valuePtr] "r" (valuePtr), \ - [arg] "r" (arg) \ - : "memory", "cc" \ - ) -#endif - -#if defined __clang__ || defined __GNUC__ -#define DO_MBED_LOCKFREE_OLDVAL_3OP_ASM(OP, Constants, M) \ - __asm volatile ( \ - ".syntax unified\n\t" \ - "LDREX"#M "\t%[oldValue], %[value]\n\t" \ - #OP "\t%[newValue], %[oldValue], %[arg]\n\t" \ - "STREX"#M "\t%[fail], %[newValue], %[value]\n\t" \ - : [oldValue] "=&" MBED_DOP_REG (oldValue), \ - [newValue] "=&" MBED_DOP_REG (newValue), \ - [fail] "=&r" (fail), \ - [value] "+Q" (*valuePtr) \ - : [arg] Constants MBED_DOP_REG (arg) \ - : "cc" \ - ) -#elif defined __ICCARM__ -/* In IAR "r" means low register if Thumbv1 (there's no way to specify any register...) */ -#define DO_MBED_LOCKFREE_OLDVAL_3OP_ASM(OP, Constants, M) \ - asm volatile ( \ - "LDREX"#M "\t%[oldValue], [%[valuePtr]]\n" \ - #OP "\t%[newValue], %[oldValue], %[arg]\n" \ - "STREX"#M "\t%[fail], %[newValue], [%[valuePtr]]\n" \ - : [oldValue] "=&r" (oldValue), \ - [newValue] "=&r" (newValue), \ - [fail] "=&r" (fail) \ - : [valuePtr] "r" (valuePtr), \ - [arg] "r" (arg) \ - : "memory", "cc" \ - ) -#endif - -/* Bitwise operations are harder to do in ARMv8-M baseline - there - * are only 2-operand versions of the instructions. - */ -#if defined __clang__ || defined __GNUC__ -#define DO_MBED_LOCKFREE_OLDVAL_2OP_ASM(OP, Constants, M) \ - __asm volatile ( \ - ".syntax unified\n\t" \ - "LDREX"#M "\t%[oldValue], %[value]\n\t" \ - "MOV" "\t%[newValue], %[oldValue]\n\t" \ - #OP "\t%[newValue], %[arg]\n\t" \ - "STREX"#M "\t%[fail], %[newValue], %[value]\n\t" \ - : [oldValue] "=&r" (oldValue), \ - [newValue] "=&l" (newValue), \ - [fail] "=&r" (fail), \ - [value] "+Q" (*valuePtr) \ - : [arg] Constants "l" (arg) \ - : "cc" \ - ) -#elif defined __ICCARM__ -#define DO_MBED_LOCKFREE_OLDVAL_2OP_ASM(OP, Constants, M) \ - asm volatile ( \ - "LDREX"#M "\t%[oldValue], [%[valuePtr]]\n" \ - "MOV" "\t%[newValue], %[oldValue]\n" \ - #OP "\t%[newValue], %[arg]\n" \ - "STREX"#M "\t%[fail], %[newValue], [%[valuePtr]]\n" \ - : [oldValue] "=&r" (oldValue), \ - [newValue] "=&r" (newValue), \ - [fail] "=&r" (fail) \ - : [valuePtr] "r" (valuePtr), \ - [arg] "r" (arg) \ - : "memory", "cc" \ - ) -#endif - -/* Note that we split ARM and Thumb implementations for CAS, as - * the key distinction is the handling of conditions. Thumb-2 IT is - * partially deprecated, so avoid it, making Thumb-1 and Thumb-2 - * implementations the same. - */ -#if MBED_EXCLUSIVE_ACCESS_ARM -#if defined __clang__ || defined __GNUC__ -#define DO_MBED_LOCKFREE_CAS_WEAK_ASM(M) \ - __asm volatile ( \ - ".syntax unified\n\t" \ - "LDREX"#M "\t%[oldValue], %[value]\n\t" \ - "SUBS" "\t%[fail], %[oldValue], %[expectedValue]\n\t"\ - "STREX"#M"EQ\t%[fail], %[desiredValue], %[value]\n\t" \ - : [oldValue] "=&r" (oldValue), \ - [fail] "=&r" (fail), \ - [value] "+Q" (*ptr) \ - : [desiredValue] "r" (desiredValue), \ - [expectedValue] "ILr" (expectedValue) \ - : "cc" \ - ) -#elif defined __ICCARM__ -#define DO_MBED_LOCKFREE_CAS_WEAK_ASM(M) \ - asm volatile ( \ - "LDREX"#M "\t%[oldValue], [%[valuePtr]]\n" \ - "SUBS" "\t%[fail], %[oldValue], %[expectedValue]\n" \ - "STREX"#M"EQ\t%[fail], %[desiredValue], [%[valuePtr]]\n"\ - : [oldValue] "=&r" (oldValue), \ - [fail] "=&r" (fail) \ - : [desiredValue] "r" (desiredValue), \ - [expectedValue] "r" (expectedValue), \ - [valuePtr] "r" (ptr), \ - : "memory", "cc" \ - ) -#endif -#else // MBED_EXCLUSIVE_ACCESS_ARM -#if defined __clang__ || defined __GNUC__ -#define DO_MBED_LOCKFREE_CAS_WEAK_ASM(M) \ - __asm volatile ( \ - ".syntax unified\n\t" \ - "LDREX"#M "\t%[oldValue], %[value]\n\t" \ - "SUBS" "\t%[fail], %[oldValue], %[expectedValue]\n\t"\ - "BNE" "\t%=f\n\t" \ - "STREX"#M "\t%[fail], %[desiredValue], %[value]\n" \ - "%=:" \ - : [oldValue] "=&" MBED_DOP_REG (oldValue), \ - [fail] "=&" MBED_DOP_REG (fail), \ - [value] "+Q" (*ptr) \ - : [desiredValue] "r" (desiredValue), \ - [expectedValue] MBED_SUB3_IMM MBED_DOP_REG (expectedValue) \ - : "cc" \ - ) -#elif defined __ICCARM__ -#define DO_MBED_LOCKFREE_CAS_WEAK_ASM(M) \ - asm volatile ( \ - "LDREX"#M "\t%[oldValue], [%[valuePtr]]\n" \ - "SUBS" "\t%[fail], %[oldValue], %[expectedValue]\n" \ - "BNE" "\tdone\n\t" \ - "STREX"#M "\t%[fail], %[desiredValue], [%[valuePtr]]\n"\ - "done:" \ - : [oldValue] "=&r" (oldValue), \ - [fail] "=&r" (fail) \ - : [desiredValue] "r" (desiredValue), \ - [expectedValue] "r" (expectedValue), \ - [valuePtr] "r" (ptr) \ - : "memory", "cc" \ - ) -#endif -#endif // MBED_EXCLUSIVE_ACCESS_ARM - -/* For strong CAS, conditional execution is complex enough to - * not be worthwhile, so all implementations look like Thumb-1. - * (This is the operation for which STREX returning 0 for success - * is beneficial.) - */ -#if defined __clang__ || defined __GNUC__ -#define DO_MBED_LOCKFREE_CAS_STRONG_ASM(M) \ - __asm volatile ( \ - ".syntax unified\n\t" \ - "\n%=:\n\t" \ - "LDREX"#M "\t%[oldValue], %[value]\n\t" \ - "SUBS" "\t%[fail], %[oldValue], %[expectedValue]\n\t"\ - "BNE" "\t%=f\n" \ - "STREX"#M "\t%[fail], %[desiredValue], %[value]\n\t" \ - "CMP" "\t%[fail], #0\n\t" \ - "BNE" "\t%=b\n" \ - "%=:" \ - : [oldValue] "=&" MBED_DOP_REG (oldValue), \ - [fail] "=&" MBED_DOP_REG (fail), \ - [value] "+Q" (*ptr) \ - : [desiredValue] "r" (desiredValue), \ - [expectedValue] MBED_SUB3_IMM MBED_DOP_REG (expectedValue) \ - : "cc" \ - ) -#elif defined __ICCARM__ -#define DO_MBED_LOCKFREE_CAS_STRONG_ASM(M) \ - asm volatile ( \ - "retry:\n" \ - "LDREX"#M "\t%[oldValue], [%[valuePtr]]\n" \ - "SUBS" "\t%[fail], %[oldValue], %[expectedValue]\n" \ - "BNE" "\tdone\n" \ - "STREX"#M "\t%[fail], %[desiredValue], [%[valuePtr]]\n"\ - "CMP" "\t%[fail], #0\n" \ - "BNE" "\tretry\n" \ - "done:" \ - : [oldValue] "=&r" (oldValue), \ - [fail] "=&r" (fail) \ - : [desiredValue] "r" (desiredValue), \ - [expectedValue] "r" (expectedValue), \ - [valuePtr] "r" (ptr) \ - : "memory", "cc" \ - ) -#endif - -/********************* LOCK-FREE IMPLEMENTATION MACROS ****************/ - -/* Note care taken with types here. Values which the assembler outputs correctly - * narrowed, or inputs without caring about width, are marked as type T. Other - * values are uint32_t. It's not clear from documentation whether assembler - * assumes anything about widths, but try to signal correctly to get necessary - * narrowing, and avoid unnecessary. - * Tests show that GCC in particular will pass in unnarrowed values - eg passing - * "uint8_t arg = -1" to the assembler as 0xFFFFFFFF. This is fine for, eg, add_u8, - * but wouldn't be for compare_and_exchange_u8. - * On the other hand, it seems to be impossible to stop GCC inserting narrowing - * instructions for the output - it will always put in UXTB for the oldValue of - * an operation. - */ -#define DO_MBED_LOCKFREE_EXCHG_OP(T, fn_suffix, M) \ -inline T core_util_atomic_exchange_##fn_suffix(volatile T *valuePtr, T newValue) \ -{ \ - T oldValue; \ - uint32_t fail; \ - MBED_BARRIER(); \ - DO_MBED_LOCKFREE_EXCHG_ASM(M); \ - MBED_BARRIER(); \ - return oldValue; \ -} \ - \ -MBED_FORCEINLINE T core_util_atomic_exchange_explicit_##fn_suffix( \ - volatile T *valuePtr, T newValue, mbed_memory_order order) \ -{ \ - T oldValue; \ - uint32_t fail; \ - MBED_RELEASE_BARRIER(order); \ - DO_MBED_LOCKFREE_EXCHG_ASM(M); \ - MBED_ACQUIRE_BARRIER(order); \ - return oldValue; \ -} - -#define DO_MBED_LOCKFREE_CAS_WEAK_OP(T, fn_suffix, M) \ -inline bool core_util_atomic_compare_exchange_weak_##fn_suffix(volatile T *ptr, T *expectedCurrentValue, T desiredValue) \ -{ \ - MBED_BARRIER(); \ - T oldValue; \ - uint32_t fail, expectedValue = *expectedCurrentValue; \ - DO_MBED_LOCKFREE_CAS_WEAK_ASM(M); \ - if (fail) { \ - *expectedCurrentValue = oldValue; \ - } \ - MBED_BARRIER(); \ - return !fail; \ -} \ - \ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_##fn_suffix(volatile T *ptr, T *expectedCurrentValue, T desiredValue, mbed_memory_order success, mbed_memory_order failure) \ -{ \ - MBED_CHECK_CAS_ORDER(success, failure); \ - MBED_RELEASE_BARRIER(success); \ - T oldValue; \ - uint32_t fail, expectedValue = *expectedCurrentValue; \ - DO_MBED_LOCKFREE_CAS_WEAK_ASM(M); \ - if (fail) { \ - *expectedCurrentValue = oldValue; \ - } \ - MBED_ACQUIRE_BARRIER(fail ? failure : success); \ - return !fail; \ -} - -#define DO_MBED_LOCKFREE_CAS_STRONG_OP(T, fn_suffix, M) \ -inline bool core_util_atomic_cas_##fn_suffix(volatile T *ptr, T *expectedCurrentValue, T desiredValue) \ -{ \ - MBED_BARRIER(); \ - T oldValue; \ - uint32_t fail, expectedValue = *expectedCurrentValue; \ - DO_MBED_LOCKFREE_CAS_STRONG_ASM(M); \ - if (fail) { \ - *expectedCurrentValue = oldValue; \ - } \ - MBED_BARRIER(); \ - return !fail; \ -} \ - \ -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_##fn_suffix(volatile T *ptr, T *expectedCurrentValue, T desiredValue, mbed_memory_order success, mbed_memory_order failure) \ -{ \ - MBED_CHECK_CAS_ORDER(success, failure); \ - MBED_RELEASE_BARRIER(success); \ - T oldValue; \ - uint32_t fail, expectedValue = *expectedCurrentValue; \ - DO_MBED_LOCKFREE_CAS_STRONG_ASM(M); \ - if (fail) { \ - *expectedCurrentValue = oldValue; \ - } \ - MBED_ACQUIRE_BARRIER(fail ? failure : success); \ - return !fail; \ -} - - -#define DO_MBED_LOCKFREE_NEWVAL_2OP(name, OP, Constants, T, fn_suffix, M) \ -inline T core_util_atomic_##name##_##fn_suffix(volatile T *valuePtr, T arg) \ -{ \ - uint32_t fail, newValue; \ - MBED_BARRIER(); \ - do { \ - DO_MBED_LOCKFREE_NEWVAL_2OP_ASM(OP, Constants, M); \ - } while (fail); \ - MBED_BARRIER(); \ - return (T) newValue; \ -} \ - \ -MBED_FORCEINLINE T core_util_atomic_##name##_explicit_##fn_suffix( \ - volatile T *valuePtr, T arg, mbed_memory_order order) \ -{ \ - uint32_t fail, newValue; \ - MBED_RELEASE_BARRIER(order); \ - do { \ - DO_MBED_LOCKFREE_NEWVAL_2OP_ASM(OP, Constants, M); \ - } while (fail); \ - MBED_ACQUIRE_BARRIER(order); \ - return (T) newValue; \ -} \ - -#define DO_MBED_LOCKFREE_OLDVAL_2OP(name, OP, Constants, T, fn_suffix, M) \ -inline T core_util_atomic_##name##_##fn_suffix(volatile T *valuePtr, T arg) \ -{ \ - T oldValue; \ - uint32_t fail, newValue; \ - MBED_BARRIER(); \ - do { \ - DO_MBED_LOCKFREE_OLDVAL_2OP_ASM(OP, Constants, M); \ - } while (fail); \ - MBED_BARRIER(); \ - return oldValue; \ -} \ - \ -MBED_FORCEINLINE T core_util_atomic_##name##_explicit_##fn_suffix( \ - volatile T *valuePtr, T arg, mbed_memory_order order) \ -{ \ - T oldValue; \ - uint32_t fail, newValue; \ - MBED_RELEASE_BARRIER(order); \ - do { \ - DO_MBED_LOCKFREE_OLDVAL_2OP_ASM(OP, Constants, M); \ - } while (fail); \ - MBED_ACQUIRE_BARRIER(order); \ - return oldValue; \ -} \ - -#define DO_MBED_LOCKFREE_OLDVAL_3OP(name, OP, Constants, T, fn_suffix, M) \ -inline T core_util_atomic_##name##_##fn_suffix(volatile T *valuePtr, T arg) { \ - T oldValue; \ - uint32_t fail, newValue; \ - MBED_BARRIER(); \ - do { \ - DO_MBED_LOCKFREE_OLDVAL_3OP_ASM(OP, Constants, M); \ - } while (fail); \ - MBED_BARRIER(); \ - return oldValue; \ -} \ - \ -MBED_FORCEINLINE T core_util_atomic_##name##_explicit_##fn_suffix( \ - volatile T *valuePtr, T arg, mbed_memory_order order) \ -{ \ - T oldValue; \ - uint32_t fail, newValue; \ - MBED_RELEASE_BARRIER(order); \ - do { \ - DO_MBED_LOCKFREE_OLDVAL_3OP_ASM(OP, Constants, M); \ - } while (fail); \ - MBED_ACQUIRE_BARRIER(order); \ - return oldValue; \ -} \ - -inline bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *valuePtr) -{ - MBED_BARRIER(); - bool oldValue, newValue = true; - uint32_t fail; - do { - DO_MBED_LOCKFREE_EXCHG_ASM(B); - } while (fail); - MBED_BARRIER(); - return oldValue; -} - -MBED_FORCEINLINE bool core_util_atomic_flag_test_and_set_explicit(volatile core_util_atomic_flag *valuePtr, mbed_memory_order order) -{ - MBED_RELEASE_BARRIER(order); - bool oldValue, newValue = true; - uint32_t fail; - do { - DO_MBED_LOCKFREE_EXCHG_ASM(B); - } while (fail); - MBED_ACQUIRE_BARRIER(order); - return oldValue; -} - -/********************* LOCK-FREE IMPLEMENTATION DEFINITIONS ****************/ - -#define DO_MBED_LOCKFREE_EXCHG_OPS() \ - DO_MBED_LOCKFREE_EXCHG_OP(uint8_t, u8, B) \ - DO_MBED_LOCKFREE_EXCHG_OP(uint16_t, u16, H) \ - DO_MBED_LOCKFREE_EXCHG_OP(uint32_t, u32, ) - -#define DO_MBED_LOCKFREE_NEWVAL_2OPS(name, OP, Constants) \ - DO_MBED_LOCKFREE_NEWVAL_2OP(name, OP, Constants, uint8_t, u8, B) \ - DO_MBED_LOCKFREE_NEWVAL_2OP(name, OP, Constants, uint16_t, u16, H) \ - DO_MBED_LOCKFREE_NEWVAL_2OP(name, OP, Constants, uint32_t, u32, ) - -#define DO_MBED_LOCKFREE_OLDVAL_3OPS(name, OP, Constants) \ - DO_MBED_LOCKFREE_OLDVAL_3OP(name, OP, Constants, uint8_t, u8, B) \ - DO_MBED_LOCKFREE_OLDVAL_3OP(name, OP, Constants, uint16_t, u16, H) \ - DO_MBED_LOCKFREE_OLDVAL_3OP(name, OP, Constants, uint32_t, u32, ) - -#define DO_MBED_LOCKFREE_OLDVAL_2OPS(name, OP, Constants) \ - DO_MBED_LOCKFREE_OLDVAL_2OP(name, OP, Constants, uint8_t, u8, B) \ - DO_MBED_LOCKFREE_OLDVAL_2OP(name, OP, Constants, uint16_t, u16, H) \ - DO_MBED_LOCKFREE_OLDVAL_2OP(name, OP, Constants, uint32_t, u32, ) - -#define DO_MBED_LOCKFREE_CAS_STRONG_OPS() \ - DO_MBED_LOCKFREE_CAS_STRONG_OP(uint8_t, u8, B) \ - DO_MBED_LOCKFREE_CAS_STRONG_OP(uint16_t, u16, H) \ - DO_MBED_LOCKFREE_CAS_STRONG_OP(uint32_t, u32, ) - -#define DO_MBED_LOCKFREE_CAS_WEAK_OPS() \ - DO_MBED_LOCKFREE_CAS_WEAK_OP(uint8_t, u8, B) \ - DO_MBED_LOCKFREE_CAS_WEAK_OP(uint16_t, u16, H) \ - DO_MBED_LOCKFREE_CAS_WEAK_OP(uint32_t, u32, ) - -// Note that these macros define a number of functions that are -// not in mbed_atomic.h, like core_util_atomic_and_fetch_u16. -// These are not documented via the doxygen in mbed_atomic.h, so -// for now should be regarded as internal only. They are used by the -// Atomic template as an optimisation though. - -// We always use the "S" form of operations - avoids yet another -// possible unneeded distinction between Thumbv1 and Thumbv2, and -// may reduce code size by allowing 16-bit instructions. -#if !MBED_EXCLUSIVE_ACCESS_THUMB1 -// I constraint is 12-bit modified immediate constant -// L constraint is negated 12-bit modified immediate constant -// (relying on assembler to swap ADD/SUB) -// We could permit J (-4095 to +4095) if we used ADD/SUB -// instead of ADDS/SUBS, but then that would block generation -// of the 16-bit forms. Shame we can't specify "don't care" -// for the "S", or get the GNU multi-alternative to -// choose ADDS/ADD appropriately. - -DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_add, ADDS, "IL") -DO_MBED_LOCKFREE_NEWVAL_2OPS(incr, ADDS, "IL") -DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_sub, SUBS, "IL") -DO_MBED_LOCKFREE_NEWVAL_2OPS(decr, SUBS, "IL") -// K constraint is inverted 12-bit modified immediate constant -// (relying on assembler substituting BIC for AND) -DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_and, ANDS, "IK") -DO_MBED_LOCKFREE_NEWVAL_2OPS(and_fetch, ANDS, "IK") -#if MBED_EXCLUSIVE_ACCESS_ARM -// ARM does not have ORN instruction, so take plain immediates. -DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_or, ORRS, "I") -DO_MBED_LOCKFREE_NEWVAL_2OPS(or_fetch, ORRS, "I") -#else -// Thumb-2 has ORN instruction, and assembler substitutes ORN for ORR. -DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_or, ORRS, "IK") -DO_MBED_LOCKFREE_NEWVAL_2OPS(or_fetch, ORRS, "IK") -#endif -// I constraint is 12-bit modified immediate operand -DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_xor, EORS, "I") -DO_MBED_LOCKFREE_NEWVAL_2OPS(xor_fetch, EORS, "I") -#else // MBED_EXCLUSIVE_ACCESS_THUMB1 -// I constraint is 0-255; J is -255 to -1, suitable for -// 2-op ADD/SUB (relying on assembler to swap ADD/SUB) -// L constraint is -7 to +7, suitable for 3-op ADD/SUB -// (relying on assembler to swap ADD/SUB) -DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_add, ADDS, "L") -DO_MBED_LOCKFREE_NEWVAL_2OPS(incr, ADDS, "IJ") -DO_MBED_LOCKFREE_OLDVAL_3OPS(fetch_sub, SUBS, "L") -DO_MBED_LOCKFREE_NEWVAL_2OPS(decr, SUBS, "IJ") -DO_MBED_LOCKFREE_OLDVAL_2OPS(fetch_and, ANDS, "") -DO_MBED_LOCKFREE_NEWVAL_2OPS(and_fetch, ANDS, "") -DO_MBED_LOCKFREE_OLDVAL_2OPS(fetch_or, ORRS, "") -DO_MBED_LOCKFREE_NEWVAL_2OPS(or_fetch, ORRS, "") -DO_MBED_LOCKFREE_OLDVAL_2OPS(fetch_xor, EORS, "") -DO_MBED_LOCKFREE_NEWVAL_2OPS(xor_fetch, EORS, "") -#endif - -DO_MBED_LOCKFREE_EXCHG_OPS() -DO_MBED_LOCKFREE_CAS_STRONG_OPS() -DO_MBED_LOCKFREE_CAS_WEAK_OPS() - -#define DO_MBED_LOCKED_FETCH_OP_ORDERINGS(name) \ - DO_MBED_LOCKED_FETCH_OP_ORDERING(name, uint64_t, u64) -#define DO_MBED_LOCKED_CAS_ORDERINGS(name) \ - DO_MBED_LOCKED_CAS_ORDERING(name, uint64_t, u64) -#else // MBED_EXCLUSIVE_ACCESS -/* All the operations are locked, so need no ordering parameters */ -#define DO_MBED_LOCKED_FETCH_OP_ORDERINGS(name) \ - DO_MBED_LOCKED_FETCH_OP_ORDERING(name, uint8_t, u8) \ - DO_MBED_LOCKED_FETCH_OP_ORDERING(name, uint16_t, u16) \ - DO_MBED_LOCKED_FETCH_OP_ORDERING(name, uint32_t, u32) \ - DO_MBED_LOCKED_FETCH_OP_ORDERING(name, uint64_t, u64) -#define DO_MBED_LOCKED_CAS_ORDERINGS(name) \ - DO_MBED_LOCKED_CAS_ORDERING(name, uint8_t, u8) \ - DO_MBED_LOCKED_CAS_ORDERING(name, uint16_t, u16) \ - DO_MBED_LOCKED_CAS_ORDERING(name, uint32_t, u32) \ - DO_MBED_LOCKED_CAS_ORDERING(name, uint64_t, u64) - -MBED_FORCEINLINE bool core_util_atomic_flag_test_and_set_explicit(volatile core_util_atomic_flag *valuePtr, mbed_memory_order order) -{ - return core_util_atomic_flag_test_and_set(valuePtr); -} -#endif // MBED_EXCLUSIVE_ACCESS - -/********************* OPERATIONS THAT ARE ALWAYS LOCK-FREE ****************/ - -/* Lock-free loads and stores don't need assembler - just aligned accesses */ -/* Silly ordering of `T volatile` is because T can be `void *` */ -#define DO_MBED_LOCKFREE_LOADSTORE(T, V, fn_suffix) \ -MBED_FORCEINLINE T core_util_atomic_load_##fn_suffix(T const V *valuePtr) \ -{ \ - T value = *valuePtr; \ - MBED_BARRIER(); \ - return value; \ -} \ - \ -MBED_FORCEINLINE T core_util_atomic_load_explicit_##fn_suffix(T const V *valuePtr, mbed_memory_order order) \ -{ \ - MBED_CHECK_LOAD_ORDER(order); \ - T value = *valuePtr; \ - MBED_ACQUIRE_BARRIER(order); \ - return value; \ -} \ - \ -MBED_FORCEINLINE void core_util_atomic_store_##fn_suffix(T V *valuePtr, T value) \ -{ \ - MBED_BARRIER(); \ - *valuePtr = value; \ - MBED_BARRIER(); \ -} \ - \ -MBED_FORCEINLINE void core_util_atomic_store_explicit_##fn_suffix(T V *valuePtr, T value, mbed_memory_order order) \ -{ \ - MBED_CHECK_STORE_ORDER(order); \ - MBED_RELEASE_BARRIER(order); \ - *valuePtr = value; \ - MBED_SEQ_CST_BARRIER(order); \ -} - -MBED_FORCEINLINE void core_util_atomic_flag_clear(volatile core_util_atomic_flag *flagPtr) -{ - MBED_BARRIER(); - flagPtr->_flag = false; - MBED_BARRIER(); -} - -MBED_FORCEINLINE void core_util_atomic_flag_clear_explicit(volatile core_util_atomic_flag *flagPtr, mbed_memory_order order) -{ - MBED_CHECK_STORE_ORDER(order); - MBED_RELEASE_BARRIER(order); - flagPtr->_flag = false; - MBED_SEQ_CST_BARRIER(order); -} - -#ifdef __cplusplus -// Temporarily turn off extern "C", so we can provide non-volatile load/store -// overloads for efficiency. All these functions are static inline, so this has -// no linkage effect exactly, it just permits the overloads. -} // extern "C" - -// For efficiency it's worth having non-volatile overloads -MBED_FORCEINLINE void core_util_atomic_flag_clear(core_util_atomic_flag *flagPtr) -{ - MBED_BARRIER(); - flagPtr->_flag = false; - MBED_BARRIER(); -} - -MBED_FORCEINLINE void core_util_atomic_flag_clear_explicit(core_util_atomic_flag *flagPtr, mbed_memory_order order) -{ - MBED_RELEASE_BARRIER(order); - flagPtr->_flag = false; - MBED_SEQ_CST_BARRIER(order); -} - -DO_MBED_LOCKFREE_LOADSTORE(uint8_t,, u8) -DO_MBED_LOCKFREE_LOADSTORE(uint16_t,, u16) -DO_MBED_LOCKFREE_LOADSTORE(uint32_t,, u32) -DO_MBED_LOCKFREE_LOADSTORE(int8_t,, s8) -DO_MBED_LOCKFREE_LOADSTORE(int16_t,, s16) -DO_MBED_LOCKFREE_LOADSTORE(int32_t,, s32) -DO_MBED_LOCKFREE_LOADSTORE(bool,, bool) -DO_MBED_LOCKFREE_LOADSTORE(void *,, ptr) - -#endif - -DO_MBED_LOCKFREE_LOADSTORE(uint8_t, volatile, u8) -DO_MBED_LOCKFREE_LOADSTORE(uint16_t, volatile, u16) -DO_MBED_LOCKFREE_LOADSTORE(uint32_t, volatile, u32) -DO_MBED_LOCKFREE_LOADSTORE(int8_t, volatile, s8) -DO_MBED_LOCKFREE_LOADSTORE(int16_t, volatile, s16) -DO_MBED_LOCKFREE_LOADSTORE(int32_t, volatile, s32) -DO_MBED_LOCKFREE_LOADSTORE(bool, volatile, bool) -DO_MBED_LOCKFREE_LOADSTORE(void *, volatile, ptr) - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* GENERIC VARIANTS - SIGNED, BOOL, POINTERS ****************/ - -MBED_FORCEINLINE int64_t core_util_atomic_load_s64(const volatile int64_t *valuePtr) -{ - return (int64_t)core_util_atomic_load_u64((const volatile uint64_t *)valuePtr); -} - -MBED_FORCEINLINE void core_util_atomic_store_s64(volatile int64_t *valuePtr, int64_t desiredValue) -{ - core_util_atomic_store_u64((volatile uint64_t *)valuePtr, (uint64_t)desiredValue); -} - -#define DO_MBED_SIGNED_CAS_OP(name, T, fn_suffix) \ -MBED_FORCEINLINE bool core_util_atomic_##name##_s##fn_suffix(volatile T *ptr, \ - T *expectedCurrentValue, T desiredValue) \ -{ \ - return core_util_atomic_##name##_u##fn_suffix((volatile u##T *)ptr, \ - (u##T *)expectedCurrentValue, (u##T)desiredValue); \ -} \ - \ -MBED_FORCEINLINE bool core_util_atomic_##name##_explicit_s##fn_suffix(volatile T *ptr, \ - T *expectedCurrentValue, T desiredValue, \ - mbed_memory_order success, mbed_memory_order failure) \ -{ \ - return core_util_atomic_##name##_explicit_u##fn_suffix((volatile u##T *)ptr, \ - (u##T *)expectedCurrentValue, (u##T)desiredValue, success, failure); \ -} - -#define DO_MBED_SIGNED_CAS_OPS(name) \ - DO_MBED_SIGNED_CAS_OP(name, int8_t, 8) \ - DO_MBED_SIGNED_CAS_OP(name, int16_t, 16) \ - DO_MBED_SIGNED_CAS_OP(name, int32_t, 32) \ - DO_MBED_SIGNED_CAS_OP(name, int64_t, 64) - -DO_MBED_SIGNED_CAS_OPS(cas) -DO_MBED_SIGNED_CAS_OPS(compare_exchange_weak) - -MBED_FORCEINLINE bool core_util_atomic_cas_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue) -{ - return core_util_atomic_cas_u8((volatile uint8_t *)ptr, (uint8_t *)expectedCurrentValue, desiredValue); -} - -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue, mbed_memory_order success, mbed_memory_order failure) -{ - return core_util_atomic_cas_explicit_u8((volatile uint8_t *)ptr, (uint8_t *)expectedCurrentValue, desiredValue, success, failure); -} - -inline bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue) -{ -#if MBED_ATOMIC_PTR_SIZE == 32 - return core_util_atomic_cas_u32( - (volatile uint32_t *)ptr, - (uint32_t *)expectedCurrentValue, - (uint32_t)desiredValue); -#else - return core_util_atomic_cas_u64( - (volatile uint64_t *)ptr, - (uint64_t *)expectedCurrentValue, - (uint64_t)desiredValue); -#endif -} - -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue, mbed_memory_order success, mbed_memory_order failure) -{ -#if MBED_ATOMIC_PTR_SIZE == 32 - return core_util_atomic_cas_explicit_u32( - (volatile uint32_t *)ptr, - (uint32_t *)expectedCurrentValue, - (uint32_t)desiredValue, - success, failure); -#else - return core_util_atomic_cas_explicit_u64( - (volatile uint64_t *)ptr, - (uint64_t *)expectedCurrentValue, - (uint64_t)desiredValue, - success, failure); -#endif -} - -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue) -{ - return core_util_atomic_compare_exchange_weak_u8((volatile uint8_t *)ptr, (uint8_t *)expectedCurrentValue, desiredValue); -} - -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue, mbed_memory_order success, mbed_memory_order failure) -{ - return core_util_atomic_compare_exchange_weak_explicit_u8((volatile uint8_t *)ptr, (uint8_t *)expectedCurrentValue, desiredValue, success, failure); -} - -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue) -{ -#if MBED_ATOMIC_PTR_SIZE == 32 - return core_util_atomic_compare_exchange_weak_u32( - (volatile uint32_t *)ptr, - (uint32_t *)expectedCurrentValue, - (uint32_t)desiredValue); -#else - return core_util_atomic_compare_exchange_weak_u64( - (volatile uint64_t *)ptr, - (uint64_t *)expectedCurrentValue, - (uint64_t)desiredValue); -#endif -} - -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue, mbed_memory_order success, mbed_memory_order failure) -{ -#if MBED_ATOMIC_PTR_SIZE == 32 - return core_util_atomic_compare_exchange_weak_explicit_u32( - (volatile uint32_t *)ptr, - (uint32_t *)expectedCurrentValue, - (uint32_t)desiredValue, - success, failure); -#else - return core_util_atomic_compare_exchange_weak_explicit_u64( - (volatile uint64_t *)ptr, - (uint64_t *)expectedCurrentValue, - (uint64_t)desiredValue, - success, failure); -#endif -} - -#define DO_MBED_SIGNED_FETCH_OP(name, T, fn_suffix) \ -MBED_FORCEINLINE T core_util_atomic_##name##_s##fn_suffix(volatile T *valuePtr, T arg) \ -{ \ - return (T)core_util_atomic_##name##_u##fn_suffix((volatile u##T *)valuePtr, (u##T)arg); \ -} - -#define DO_MBED_SIGNED_EXPLICIT_FETCH_OP(name, T, fn_suffix) \ -MBED_FORCEINLINE T core_util_atomic_##name##_explicit_s##fn_suffix(volatile T *valuePtr, T arg, mbed_memory_order order) \ -{ \ - return (T)core_util_atomic_##name##_explicit_u##fn_suffix((volatile u##T *)valuePtr, (u##T)arg, order); \ -} - -#define DO_MBED_SIGNED_FETCH_OPS(name) \ - DO_MBED_SIGNED_FETCH_OP(name, int8_t, 8) \ - DO_MBED_SIGNED_FETCH_OP(name, int16_t, 16) \ - DO_MBED_SIGNED_FETCH_OP(name, int32_t, 32) \ - DO_MBED_SIGNED_FETCH_OP(name, int64_t, 64) - -#define DO_MBED_SIGNED_EXPLICIT_FETCH_OPS(name) \ - DO_MBED_SIGNED_EXPLICIT_FETCH_OP(name, int8_t, 8) \ - DO_MBED_SIGNED_EXPLICIT_FETCH_OP(name, int16_t, 16) \ - DO_MBED_SIGNED_EXPLICIT_FETCH_OP(name, int32_t, 32) \ - DO_MBED_SIGNED_EXPLICIT_FETCH_OP(name, int64_t, 64) - -DO_MBED_SIGNED_FETCH_OPS(exchange) -DO_MBED_SIGNED_FETCH_OPS(incr) -DO_MBED_SIGNED_FETCH_OPS(decr) -DO_MBED_SIGNED_FETCH_OPS(fetch_add) -DO_MBED_SIGNED_FETCH_OPS(fetch_sub) - -DO_MBED_SIGNED_EXPLICIT_FETCH_OPS(exchange) -DO_MBED_SIGNED_EXPLICIT_FETCH_OPS(fetch_add) -DO_MBED_SIGNED_EXPLICIT_FETCH_OPS(fetch_sub) - -MBED_FORCEINLINE bool core_util_atomic_exchange_bool(volatile bool *valuePtr, bool desiredValue) -{ - return (bool)core_util_atomic_exchange_u8((volatile uint8_t *)valuePtr, desiredValue); -} - -MBED_FORCEINLINE bool core_util_atomic_exchange_explicit_bool(volatile bool *valuePtr, bool desiredValue, mbed_memory_order order) -{ - return (bool)core_util_atomic_exchange_explicit_u8((volatile uint8_t *)valuePtr, desiredValue, order); -} - -inline void *core_util_atomic_exchange_ptr(void *volatile *valuePtr, void *desiredValue) -{ -#if MBED_ATOMIC_PTR_SIZE == 32 - return (void *)core_util_atomic_exchange_u32((volatile uint32_t *)valuePtr, (uint32_t)desiredValue); -#else - return (void *)core_util_atomic_exchange_u64((volatile uint64_t *)valuePtr, (uint64_t)desiredValue); -#endif -} - -MBED_FORCEINLINE void *core_util_atomic_exchange_explicit_ptr(void *volatile *valuePtr, void *desiredValue, mbed_memory_order order) -{ -#if MBED_ATOMIC_PTR_SIZE == 32 - return (void *)core_util_atomic_exchange_explicit_u32((volatile uint32_t *)valuePtr, (uint32_t)desiredValue, order); -#else - return (void *)core_util_atomic_exchange_explicit_u64((volatile uint64_t *)valuePtr, (uint64_t)desiredValue, order); -#endif -} - -inline void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta) -{ -#if MBED_ATOMIC_PTR_SIZE == 32 - return (void *)core_util_atomic_incr_u32((volatile uint32_t *)valuePtr, (uint32_t)delta); -#else - return (void *)core_util_atomic_incr_u64((volatile uint64_t *)valuePtr, (uint64_t)delta); -#endif -} - -inline void *core_util_atomic_decr_ptr(void *volatile *valuePtr, ptrdiff_t delta) -{ -#if MBED_ATOMIC_PTR_SIZE == 32 - return (void *)core_util_atomic_decr_u32((volatile uint32_t *)valuePtr, (uint32_t)delta); -#else - return (void *)core_util_atomic_decr_u64((volatile uint64_t *)valuePtr, (uint64_t)delta); -#endif -} - -MBED_FORCEINLINE void *core_util_atomic_fetch_add_ptr(void *volatile *valuePtr, ptrdiff_t arg) -{ -#if MBED_ATOMIC_PTR_SIZE == 32 - return (void *)core_util_atomic_fetch_add_u32((volatile uint32_t *)valuePtr, (uint32_t)arg); -#else - return (void *)core_util_atomic_fetch_add_u64((volatile uint64_t *)valuePtr, (uint64_t)arg); -#endif -} - -MBED_FORCEINLINE void *core_util_atomic_fetch_add_explicit_ptr(void *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) -{ -#if MBED_ATOMIC_PTR_SIZE == 32 - return (void *)core_util_atomic_fetch_add_explicit_u32((volatile uint32_t *)valuePtr, (uint32_t)arg, order); -#else - return (void *)core_util_atomic_fetch_add_explicit_u64((volatile uint64_t *)valuePtr, (uint64_t)arg, order); -#endif -} - -MBED_FORCEINLINE void *core_util_atomic_fetch_sub_ptr(void *volatile *valuePtr, ptrdiff_t arg) -{ -#if MBED_ATOMIC_PTR_SIZE == 32 - return (void *)core_util_atomic_fetch_sub_u32((volatile uint32_t *)valuePtr, (uint32_t)arg); -#else - return (void *)core_util_atomic_fetch_sub_u64((volatile uint64_t *)valuePtr, (uint64_t)arg); -#endif -} - -MBED_FORCEINLINE void *core_util_atomic_fetch_sub_explicit_ptr(void *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) -{ -#if MBED_ATOMIC_PTR_SIZE == 32 - return (void *)core_util_atomic_fetch_sub_explicit_u32((volatile uint32_t *)valuePtr, (uint32_t)arg, order); -#else - return (void *)core_util_atomic_fetch_sub_explicit_u64((volatile uint64_t *)valuePtr, (uint64_t)arg, order); -#endif -} - -/***************** DUMMY EXPLICIT ORDERING FOR LOCKED OPS *****************/ - -/* Need to throw away the ordering information for all locked operations */ -MBED_FORCEINLINE uint64_t core_util_atomic_load_explicit_u64(const volatile uint64_t *valuePtr, MBED_UNUSED mbed_memory_order order) -{ - MBED_CHECK_LOAD_ORDER(order); - return core_util_atomic_load_u64(valuePtr); -} - -MBED_FORCEINLINE int64_t core_util_atomic_load_explicit_s64(const volatile int64_t *valuePtr, MBED_UNUSED mbed_memory_order order) -{ - MBED_CHECK_LOAD_ORDER(order); - return core_util_atomic_load_s64(valuePtr); -} - -MBED_FORCEINLINE void core_util_atomic_store_explicit_u64(volatile uint64_t *valuePtr, uint64_t desiredValue, MBED_UNUSED mbed_memory_order order) -{ - MBED_CHECK_STORE_ORDER(order); - core_util_atomic_store_u64(valuePtr, desiredValue); -} - -MBED_FORCEINLINE void core_util_atomic_store_explicit_s64(volatile int64_t *valuePtr, int64_t desiredValue, MBED_UNUSED mbed_memory_order order) -{ - MBED_CHECK_STORE_ORDER(order); - core_util_atomic_store_s64(valuePtr, desiredValue); -} - -#define DO_MBED_LOCKED_FETCH_OP_ORDERING(name, T, fn_suffix) \ -MBED_FORCEINLINE T core_util_atomic_##name##_explicit_##fn_suffix( \ - volatile T *valuePtr, T arg, MBED_UNUSED mbed_memory_order order) \ -{ \ - return core_util_atomic_##name##_##fn_suffix(valuePtr, arg); \ -} - -#define DO_MBED_LOCKED_CAS_ORDERING(name, T, fn_suffix) \ -MBED_FORCEINLINE bool core_util_atomic_##name##_explicit_##fn_suffix( \ - volatile T *ptr, T *expectedCurrentValue, T desiredValue, \ - MBED_UNUSED mbed_memory_order success, \ - MBED_UNUSED mbed_memory_order failure) \ -{ \ - MBED_CHECK_CAS_ORDER(success, failure); \ - return core_util_atomic_##name##_##fn_suffix(ptr, expectedCurrentValue, desiredValue); \ -} - -DO_MBED_LOCKED_FETCH_OP_ORDERINGS(exchange) -DO_MBED_LOCKED_FETCH_OP_ORDERINGS(fetch_add) -DO_MBED_LOCKED_FETCH_OP_ORDERINGS(fetch_sub) -DO_MBED_LOCKED_FETCH_OP_ORDERINGS(fetch_and) -DO_MBED_LOCKED_FETCH_OP_ORDERINGS(fetch_or) -DO_MBED_LOCKED_FETCH_OP_ORDERINGS(fetch_xor) -DO_MBED_LOCKED_CAS_ORDERINGS(cas) -DO_MBED_LOCKED_CAS_ORDERINGS(compare_exchange_weak) - -#ifdef __cplusplus -} // extern "C" - -/***************** TEMPLATE IMPLEMENTATIONS *****************/ - -/* Each of these groups provides specialisations for the T template for each of - * the small types (there is no base implementation), and the base implementation - * of the T * template. - */ -#define DO_MBED_ATOMIC_LOAD_TEMPLATE(T, fn_suffix) \ -template<> \ -inline T core_util_atomic_load(const volatile T *valuePtr) noexcept \ -{ \ - return core_util_atomic_load_##fn_suffix(valuePtr); \ -} \ - \ -template<> \ -inline T core_util_atomic_load(const T *valuePtr) noexcept \ -{ \ - return core_util_atomic_load_##fn_suffix(valuePtr); \ -} \ - \ -template<> \ -inline T core_util_atomic_load_explicit(const volatile T *valuePtr, mbed_memory_order order) noexcept \ -{ \ - return core_util_atomic_load_explicit_##fn_suffix(valuePtr, order); \ -} \ - \ -template<> \ -inline T core_util_atomic_load_explicit(const T *valuePtr, mbed_memory_order order) noexcept \ -{ \ - return core_util_atomic_load_explicit_##fn_suffix(valuePtr, order); \ -} - -template -inline T *core_util_atomic_load(T *const volatile *valuePtr) noexcept -{ - return (T *) core_util_atomic_load_ptr((void *const volatile *) valuePtr); -} - -template -inline T *core_util_atomic_load(T *const *valuePtr) noexcept -{ - return (T *) core_util_atomic_load_ptr((void *const *) valuePtr); -} - -template -inline T *core_util_atomic_load_explicit(T *const volatile *valuePtr, mbed_memory_order order) noexcept -{ - return (T *) core_util_atomic_load_explicit_ptr((void *const volatile *) valuePtr, order); -} - -template -inline T *core_util_atomic_load_explicit(T *const *valuePtr, mbed_memory_order order) noexcept -{ - return (T *) core_util_atomic_load_explicit_ptr((void *const *) valuePtr, order); -} - -DO_MBED_ATOMIC_LOAD_TEMPLATE(uint8_t, u8) -DO_MBED_ATOMIC_LOAD_TEMPLATE(uint16_t, u16) -DO_MBED_ATOMIC_LOAD_TEMPLATE(uint32_t, u32) -DO_MBED_ATOMIC_LOAD_TEMPLATE(uint64_t, u64) -DO_MBED_ATOMIC_LOAD_TEMPLATE(int8_t, s8) -DO_MBED_ATOMIC_LOAD_TEMPLATE(int16_t, s16) -DO_MBED_ATOMIC_LOAD_TEMPLATE(int32_t, s32) -DO_MBED_ATOMIC_LOAD_TEMPLATE(int64_t, s64) -DO_MBED_ATOMIC_LOAD_TEMPLATE(bool, bool) - -#define DO_MBED_ATOMIC_STORE_TEMPLATE(T, fn_suffix) \ -template<> \ -inline void core_util_atomic_store(volatile T *valuePtr, T val) noexcept \ -{ \ - core_util_atomic_store_##fn_suffix(valuePtr, val); \ -} \ - \ -template<> \ -inline void core_util_atomic_store(T *valuePtr, T val) noexcept \ -{ \ - core_util_atomic_store_##fn_suffix(valuePtr, val); \ -} \ - \ -template<> \ -inline void core_util_atomic_store_explicit(volatile T *valuePtr, T val, mbed_memory_order order) noexcept \ -{ \ - core_util_atomic_store_explicit_##fn_suffix(valuePtr, val, order); \ -} \ - \ -template<> \ -inline void core_util_atomic_store_explicit(T *valuePtr, T val, mbed_memory_order order) noexcept \ -{ \ - core_util_atomic_store_explicit_##fn_suffix(valuePtr, val, order); \ -} - -template -inline void core_util_atomic_store(T *volatile *valuePtr, T *val) noexcept -{ - core_util_atomic_store_ptr((void *volatile *) valuePtr, val); -} - -template -inline void core_util_atomic_store(T **valuePtr, T *val) noexcept -{ - core_util_atomic_store_ptr((void **) valuePtr, val); -} - -template -inline void core_util_atomic_store_explicit(T *volatile *valuePtr, T *val, mbed_memory_order order) noexcept -{ - core_util_atomic_store_ptr((void *volatile *) valuePtr, val, order); -} - -template -inline void core_util_atomic_store_explicit(T **valuePtr, T *val, mbed_memory_order order) noexcept -{ - core_util_atomic_store_ptr((void **) valuePtr, val, order); -} - -DO_MBED_ATOMIC_STORE_TEMPLATE(uint8_t, u8) -DO_MBED_ATOMIC_STORE_TEMPLATE(uint16_t, u16) -DO_MBED_ATOMIC_STORE_TEMPLATE(uint32_t, u32) -DO_MBED_ATOMIC_STORE_TEMPLATE(uint64_t, u64) -DO_MBED_ATOMIC_STORE_TEMPLATE(int8_t, s8) -DO_MBED_ATOMIC_STORE_TEMPLATE(int16_t, s16) -DO_MBED_ATOMIC_STORE_TEMPLATE(int32_t, s32) -DO_MBED_ATOMIC_STORE_TEMPLATE(int64_t, s64) -DO_MBED_ATOMIC_STORE_TEMPLATE(bool, bool) - -#define DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, T, fn_suffix) \ -template<> inline \ -bool core_util_atomic_##tname(volatile T *ptr, T *expectedCurrentValue, T desiredValue) noexcept \ -{ \ - return core_util_atomic_##fname##_##fn_suffix(ptr, expectedCurrentValue, desiredValue); \ -} - -template -inline bool core_util_atomic_compare_exchange_strong(T *volatile *ptr, T **expectedCurrentValue, T *desiredValue) noexcept -{ - return core_util_atomic_cas_ptr((void *volatile *) ptr, (void **) expectedCurrentValue, desiredValue); -} - -template -inline bool core_util_atomic_compare_exchange_weak(T *volatile *ptr, T **expectedCurrentValue, T *desiredValue) noexcept -{ - return core_util_atomic_compare_exchange_weak_ptr((void *volatile *) ptr, (void **) expectedCurrentValue, desiredValue); -} - -#define DO_MBED_ATOMIC_CAS_TEMPLATES(tname, fname) \ - DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, uint8_t, u8) \ - DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, uint16_t, u16) \ - DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, uint32_t, u32) \ - DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, uint64_t, u64) \ - DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, int8_t, s8) \ - DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, int16_t, s16) \ - DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, int32_t, s32) \ - DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, int64_t, s64) \ - DO_MBED_ATOMIC_CAS_TEMPLATE(tname, fname, bool, bool) - -DO_MBED_ATOMIC_CAS_TEMPLATES(compare_exchange_strong, cas) -DO_MBED_ATOMIC_CAS_TEMPLATES(compare_exchange_weak, compare_exchange_weak) - -#define DO_MBED_ATOMIC_OP_TEMPLATE(name, T, fn_suffix) \ -template<> \ -inline T core_util_atomic_##name(volatile T *valuePtr, T arg) noexcept \ -{ \ - return core_util_atomic_##name##_##fn_suffix(valuePtr, arg); \ -} \ - \ -template<> \ -inline T core_util_atomic_##name##_explicit(volatile T *valuePtr, T arg, \ - mbed_memory_order order) noexcept \ -{ \ - return core_util_atomic_##name##_explicit_##fn_suffix(valuePtr, arg, order); \ -} - - -template<> -inline bool core_util_atomic_exchange(volatile bool *valuePtr, bool arg) noexcept -{ - return core_util_atomic_exchange_bool(valuePtr, arg); -} - -template<> -inline bool core_util_atomic_exchange_explicit(volatile bool *valuePtr, bool arg, mbed_memory_order order) noexcept -{ - return core_util_atomic_exchange_explicit_bool(valuePtr, arg, order); -} - -template -inline T *core_util_atomic_exchange(T *volatile *valuePtr, T *arg) noexcept -{ - return (T *) core_util_atomic_exchange_ptr((void *volatile *) valuePtr, arg); -} - -template -inline T *core_util_atomic_exchange_explicit(T *volatile *valuePtr, T *arg, mbed_memory_order order) noexcept -{ - return (T *) core_util_atomic_fetch_add_explicit_ptr((void *volatile *) valuePtr, arg, order); -} - -template -inline T *core_util_atomic_fetch_add(T *volatile *valuePtr, ptrdiff_t arg) noexcept -{ - return (T *) core_util_atomic_fetch_add_ptr((void *volatile *) valuePtr, arg * sizeof(T)); -} - -template -inline T *core_util_atomic_fetch_add_explicit(T *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) noexcept -{ - return (T *) core_util_atomic_fetch_add_explicit_ptr((void *volatile *) valuePtr, arg * sizeof(T), order); -} - -template -inline T *core_util_atomic_fetch_sub(T *volatile *valuePtr, ptrdiff_t arg) noexcept -{ - return (T *) core_util_atomic_fetch_sub_ptr((void *volatile *) valuePtr, arg * sizeof(T)); -} - -template -inline T *core_util_atomic_fetch_sub_explicit(T *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) noexcept -{ - return (T *) core_util_atomic_fetch_sub_explicit_ptr((void *volatile *) valuePtr, arg * sizeof(T), order); -} - - -#define DO_MBED_ATOMIC_OP_U_TEMPLATES(name) \ - DO_MBED_ATOMIC_OP_TEMPLATE(name, uint8_t, u8) \ - DO_MBED_ATOMIC_OP_TEMPLATE(name, uint16_t, u16) \ - DO_MBED_ATOMIC_OP_TEMPLATE(name, uint32_t, u32) \ - DO_MBED_ATOMIC_OP_TEMPLATE(name, uint64_t, u64) - -#define DO_MBED_ATOMIC_OP_S_TEMPLATES(name) \ - DO_MBED_ATOMIC_OP_TEMPLATE(name, int8_t, s8) \ - DO_MBED_ATOMIC_OP_TEMPLATE(name, int16_t, s16) \ - DO_MBED_ATOMIC_OP_TEMPLATE(name, int32_t, s32) \ - DO_MBED_ATOMIC_OP_TEMPLATE(name, int64_t, s64) - -#define DO_MBED_ATOMIC_MANUAL_PRE_OP_TEMPLATE(name, T, fn_suffix, postname, OP) \ -template<> \ -inline T core_util_atomic_##name(volatile T *valuePtr, T arg) noexcept \ -{ \ - return core_util_atomic_##postname##_##fn_suffix(valuePtr, arg) OP; \ -} \ - \ -template<> \ -inline T core_util_atomic_##name##_explicit(volatile T *valuePtr, T arg, \ - mbed_memory_order order) noexcept \ -{ \ - return core_util_atomic_##postname##_explicit_##fn_suffix(valuePtr, arg, order) OP; \ -} - -DO_MBED_ATOMIC_OP_U_TEMPLATES(exchange) -DO_MBED_ATOMIC_OP_S_TEMPLATES(exchange) -DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_add) -DO_MBED_ATOMIC_OP_S_TEMPLATES(fetch_add) -DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_sub) -DO_MBED_ATOMIC_OP_S_TEMPLATES(fetch_sub) -DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_and) -DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_or) -DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_xor) - -namespace mstd { -namespace impl { - -// Use custom assembler forms for pre-ops where available, else construct from post-ops -#if MBED_EXCLUSIVE_ACCESS -#define DO_MBED_ATOMIC_PRE_OP_TEMPLATES(name, postname, OP) \ - template T core_util_atomic_##name(volatile T *valuePtr, T arg) noexcept; \ - template T core_util_atomic_##name##_explicit(volatile T *valuePtr, T arg, mbed_memory_order order) noexcept; \ - DO_MBED_ATOMIC_OP_TEMPLATE(name, uint8_t, u8) \ - DO_MBED_ATOMIC_OP_TEMPLATE(name, uint16_t, u16) \ - DO_MBED_ATOMIC_OP_TEMPLATE(name, uint32_t, u32) \ - DO_MBED_ATOMIC_MANUAL_PRE_OP_TEMPLATE(name, uint64_t, u64, postname, OP) -#else -#define DO_MBED_ATOMIC_PRE_OP_TEMPLATES(name, postname, OP) \ - template T core_util_atomic_##name(volatile T *valuePtr, T arg) noexcept; \ - template T core_util_atomic_##name##_explicit(volatile T *valuePtr, T arg, mbed_memory_order order) noexcept; \ - DO_MBED_ATOMIC_MANUAL_PRE_OP_TEMPLATE(name, uint8_t, u8, postname, OP) \ - DO_MBED_ATOMIC_MANUAL_PRE_OP_TEMPLATE(name, uint16_t, u16, postname, OP) \ - DO_MBED_ATOMIC_MANUAL_PRE_OP_TEMPLATE(name, uint32_t, u32, postname, OP) \ - DO_MBED_ATOMIC_MANUAL_PRE_OP_TEMPLATE(name, uint64_t, u64, postname, OP) -#endif - -// *INDENT-OFF* -DO_MBED_ATOMIC_PRE_OP_TEMPLATES(incr, fetch_add, + arg) -DO_MBED_ATOMIC_PRE_OP_TEMPLATES(decr, fetch_sub, - arg) -DO_MBED_ATOMIC_PRE_OP_TEMPLATES(and_fetch, fetch_and, & arg) -DO_MBED_ATOMIC_PRE_OP_TEMPLATES(or_fetch, fetch_or, | arg) -DO_MBED_ATOMIC_PRE_OP_TEMPLATES(xor_fetch, fetch_xor, ^ arg) -// *INDENT-ON* - -} -} - -#endif // __cplusplus - -#undef MBED_DOP_REG -#undef MBED_CMP_IMM -#undef MBED_SUB3_IMM -#undef DO_MBED_LOCKFREE_EXCHG_ASM -#undef DO_MBED_LOCKFREE_NEWVAL_2OP_ASM -#undef DO_MBED_LOCKFREE_OLDVAL_3OP_ASM -#undef DO_MBED_LOCKFREE_OLDVAL_2OP_ASM -#undef DO_MBED_LOCKFREE_CAS_WEAK_ASM -#undef DO_MBED_LOCKFREE_CAS_STRONG_ASM -#undef DO_MBED_LOCKFREE_LOADSTORE -#undef DO_MBED_LOCKFREE_EXCHG_OP -#undef DO_MBED_LOCKFREE_CAS_WEAK_OP -#undef DO_MBED_LOCKFREE_CAS_STRONG_OP -#undef DO_MBED_LOCKFREE_NEWVAL_2OP -#undef DO_MBED_LOCKFREE_OLDVAL_2OP -#undef DO_MBED_LOCKFREE_OLDVAL_3OP -#undef DO_MBED_LOCKFREE_EXCHG_OPS -#undef DO_MBED_LOCKFREE_NEWVAL_2OPS -#undef DO_MBED_LOCKFREE_OLDVAL_2OPS -#undef DO_MBED_LOCKFREE_OLDVAL_3OPS -#undef DO_MBED_LOCKFREE_CAS_WEAK_OPS -#undef DO_MBED_LOCKFREE_CAS_STRONG_OPS -#undef DO_MBED_SIGNED_CAS_OP -#undef DO_MBED_SIGNED_CAS_OPS -#undef DO_MBED_SIGNED_FETCH_OP -#undef DO_MBED_SIGNED_EXPLICIT_FETCH_OP -#undef DO_MBED_SIGNED_FETCH_OPS -#undef DO_MBED_SIGNED_EXPLICIT_FETCH_OPS -#undef DO_MBED_LOCKED_FETCH_OP_ORDERINGS -#undef DO_MBED_LOCKED_CAS_ORDERINGS -#undef MBED_ACQUIRE_BARRIER -#undef MBED_RELEASE_BARRIER -#undef MBED_SEQ_CST_BARRIER -#undef DO_MBED_ATOMIC_LOAD_TEMPLATE -#undef DO_MBED_ATOMIC_STORE_TEMPLATE -#undef DO_MBED_ATOMIC_EXCHANGE_TEMPLATE -#undef DO_MBED_ATOMIC_CAS_TEMPLATE -#undef DO_MBED_ATOMIC_CAS_TEMPLATES -#undef DO_MBED_ATOMIC_FETCH_TEMPLATE -#undef DO_MBED_ATOMIC_FETCH_U_TEMPLATES -#undef DO_MBED_ATOMIC_FETCH_S_TEMPLATES - -#endif diff --git a/platform/internal/mbed_fault_handler.h b/platform/internal/mbed_fault_handler.h deleted file mode 100644 index 53813a4..0000000 --- a/platform/internal/mbed_fault_handler.h +++ /dev/null @@ -1,112 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-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_FAULT_HANDLER_H -#define MBED_FAULT_HANDLER_H - -#include "mbed_toolchain.h" -#include "mbed_error.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//Fault context struct -#ifdef TARGET_CORTEX_M -//WARNING: DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES in except.S files. -//Offset of these registers are used by fault handler in except.S -typedef struct { - uint32_t R0_reg; - uint32_t R1_reg; - uint32_t R2_reg; - uint32_t R3_reg; - uint32_t R4_reg; - uint32_t R5_reg; - uint32_t R6_reg; - uint32_t R7_reg; - uint32_t R8_reg; - uint32_t R9_reg; - uint32_t R10_reg; - uint32_t R11_reg; - uint32_t R12_reg; - uint32_t SP_reg; - uint32_t LR_reg; - uint32_t PC_reg; - uint32_t xPSR; - uint32_t PSP; - uint32_t MSP; - uint32_t EXC_RETURN; - uint32_t CONTROL; -} mbed_fault_context_t; -#elif defined TARGET_CORTEX_A -// This is not currently used, but would be a plausible implementation -typedef struct { - uint32_t R0_reg; - uint32_t R1_reg; - uint32_t R2_reg; - uint32_t R3_reg; - uint32_t R4_reg; - uint32_t R5_reg; - uint32_t R6_reg; - uint32_t R7_reg; - uint32_t R8_reg; - uint32_t R9_reg; - uint32_t R10_reg; - uint32_t R11_reg; - uint32_t R12_reg; - uint32_t SP_reg; - uint32_t LR_reg; - uint32_t PC_reg; - uint32_t CPSR; - uint32_t SP_usr; - uint32_t LR_usr; -} mbed_fault_context_t; -#else -// Dummy for mbed_crash_data_t -typedef struct { -} mbed_fault_context_t; -#endif - - -//Fault type definitions -#ifdef TARGET_CORTEX_M -//WARNING: DO NOT CHANGE THESE VALUES WITHOUT MAKING CORRESPONDING CHANGES in except.S files. -#define HARD_FAULT_EXCEPTION (0x10) //Keep some gap between values for any future insertion/expansion -#define MEMMANAGE_FAULT_EXCEPTION (0x20) -#define BUS_FAULT_EXCEPTION (0x30) -#define USAGE_FAULT_EXCEPTION (0x40) -#endif - -//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_fault_handler.c) to print the information without using C-lib support. -MBED_NORETURN void mbed_fault_handler(uint32_t fault_type, const mbed_fault_context_t *mbed_fault_context_in); - -/** - * Call this function to retrieve the fault context after a fatal exception which triggered a system reboot. The function retrieves the fault context stored in crash-report ram area which is preserved over reboot. - * @param fault_context Pointer to mbed_fault_context_t struct allocated by the caller. This is the mbed_fault_context_t info captured as part of the fatal exception which triggered the reboot. - * @return 0 or MBED_SUCCESS on success. - * MBED_ERROR_INVALID_ARGUMENT in case of invalid error_info pointer - * MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system - * - */ -mbed_error_status_t mbed_get_reboot_fault_context(mbed_fault_context_t *fault_context); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/platform/mbed_application.h b/platform/mbed_application.h deleted file mode 100644 index 37619e2..0000000 --- a/platform/mbed_application.h +++ /dev/null @@ -1,54 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017-2017 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_APPLICATION_H -#define MBED_APPLICATION_H - -#include - -#if defined(__CORTEX_M0PLUS) || defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__CORTEX_M7)\ - || defined(__CORTEX_M23) || defined(__CORTEX_A9) || defined(__CORTEX_M33) -#define MBED_APPLICATION_SUPPORT 1 -#else -#define MBED_APPLICATION_SUPPORT 0 -#endif - -#if MBED_APPLICATION_SUPPORT -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Start the application at the given address. This function does - * not return. It is the applications responsibility for flushing to - * or powering down external components such as filesystems or - * socket connections before calling this function. For Cortex-M - * devices this function powers down generic system components such as - * the NVIC and set the vector table to that of the new image followed - * by jumping to the reset handler of the new image. - * - * @param address Starting address of next application to run - */ -void mbed_start_application(uintptr_t address); - -#ifdef __cplusplus -} -#endif -#endif - -#endif - diff --git a/platform/mbed_assert.h b/platform/mbed_assert.h deleted file mode 100644 index 7df16b8..0000000 --- a/platform/mbed_assert.h +++ /dev/null @@ -1,127 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_ASSERT_H -#define MBED_ASSERT_H - -#include "platform/mbed_toolchain.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_Assert Assert macros - * @{ - */ - -/** 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 Expression to be checked. - * @param file File where assertation failed. - * @param line Failing assertation line number. - */ -MBED_NORETURN void mbed_assert_internal(const char *expr, const char *file, int line); - -#ifdef __cplusplus -} -#endif - -/** MBED_ASSERT - * Declare runtime assertions: results in runtime error if condition is false - * - * @note - * Use of MBED_ASSERT is limited to Debug and Develop builds. - * - * @code - * - * int Configure(serial_t *obj) { - * MBED_ASSERT(obj); - * } - * @endcode - */ -#ifdef NDEBUG -#define MBED_ASSERT(expr) ((void)0) - -#else -#define MBED_ASSERT(expr) \ -do { \ - if (!(expr)) { \ - mbed_assert_internal(#expr, __FILE__, __LINE__); \ - } \ -} while (0) -#endif - - -/** MBED_STATIC_ASSERT - * Declare compile-time assertions, results in compile-time error if condition is false - * - * The assertion acts as a declaration that can be placed at file scope, in a - * code block (except after a label), or as a member of a C++ class/struct/union. - * - * @code - * MBED_STATIC_ASSERT(MBED_MAJOR_VERSION >= 6, - * "The mbed-os library must be at least version 6.0.0"); - * - * int main() { - * MBED_STATIC_ASSERT(sizeof(int) >= sizeof(char), - * "An int must be larger than a char"); - * } - * @endcode - * - * @deprecated This feature is now no longer necessary with the minimum - * supported language versions. It will be removed in a forthcoming release. - * Use `static_assert` instead. For C this is provided by ``, and - * for C++ it is a built-in keyword. - */ -#if defined(__cplusplus) -#define MBED_STATIC_ASSERT(expr, msg) static_assert(expr, msg) -#else -#define MBED_STATIC_ASSERT(expr, msg) _Static_assert(expr, msg) -#endif - -/** MBED_STRUCT_STATIC_ASSERT - * Declare compile-time assertions, results in compile-time error if condition is false - * - * Previous supported compiler languages would not allow static_assert to be - * used within a struct or a class. This is no longer the case. This macro - * exists for backwards compatibility. - * - * @code - * struct thing { - * MBED_STRUCT_STATIC_ASSERT(2 + 2 == 4, - * "Hopefully the universe is mathematically consistent"); - * }; - * @endcode - * - * @deprecated This feature is now no longer necessary with the minimum - * supported language versions. It will be removed in a forthcoming release. - * Use `static_assert` instead. For C this is provided by ``, and - * for C++ it is a built-in keyword. - */ -#define MBED_STRUCT_STATIC_ASSERT(expr, message) MBED_STATIC_ASSERT(expr, message) - -#endif - -/**@}*/ - -/**@}*/ - diff --git a/platform/mbed_atomic.h b/platform/mbed_atomic.h deleted file mode 100644 index 28e2cb2..0000000 --- a/platform/mbed_atomic.h +++ /dev/null @@ -1,998 +0,0 @@ - -/* - * Copyright (c) 2015-2019, 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 __MBED_UTIL_ATOMIC_H__ -#define __MBED_UTIL_ATOMIC_H__ - -#include "cmsis.h" - -#include -#include -#include -#include "platform/mbed_toolchain.h" - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_atomic atomic functions - * - * Atomic functions function analogously to C11 and C++11 - loads have - * acquire semantics, stores have release semantics, and atomic operations - * are sequentially consistent. Atomicity is enforced both between threads and - * interrupt handlers. - * - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Memory order constraints for atomic operations. Intended semantics - * are as per C++11. - */ -typedef enum mbed_memory_order { - /* Bits 0 = consume - * 1 = acquire (explicitly requested, or implied by seq.cst) - * 2 = release (explicitly requested, or implied by seq.cst) - * 4 = sequentially consistent - */ - mbed_memory_order_relaxed = 0x00, - mbed_memory_order_consume = 0x01, - mbed_memory_order_acquire = 0x02, - mbed_memory_order_release = 0x04, - mbed_memory_order_acq_rel = 0x06, - mbed_memory_order_seq_cst = 0x16 -} mbed_memory_order; - -// if __EXCLUSIVE_ACCESS rtx macro not defined, we need to get this via own-set architecture macros -#ifndef MBED_EXCLUSIVE_ACCESS -#ifndef __EXCLUSIVE_ACCESS -#if defined __arm__ || defined __ICC_ARM__ || defined __ARM_ARCH -#if ((__ARM_ARCH_7M__ == 1U) || \ - (__ARM_ARCH_7EM__ == 1U) || \ - (__ARM_ARCH_8M_BASE__ == 1U) || \ - (__ARM_ARCH_8M_MAIN__ == 1U)) || \ - (__ARM_ARCH_7A__ == 1U) -#define MBED_EXCLUSIVE_ACCESS 1U -#define MBED_EXCLUSIVE_ACCESS_THUMB1 (__ARM_ARCH_8M_BASE__ == 1U) -#ifdef __ICCARM__ -#if __CPU_MODE__ == 2 -#define MBED_EXCLUSIVE_ACCESS_ARM 1U -#else -#define MBED_EXCLUSIVE_ACCESS_ARM 0U -#endif -#else -#if !defined (__thumb__) -#define MBED_EXCLUSIVE_ACCESS_ARM 1U -#else -#define MBED_EXCLUSIVE_ACCESS_ARM 0U -#endif -#endif -#elif (__ARM_ARCH_6M__ == 1U) -#define MBED_EXCLUSIVE_ACCESS 0U -#else -#error "Unknown ARM architecture for exclusive access" -#endif // __ARM_ARCH_xxx -#else // __arm__ || defined __ICC_ARM__ || defined __ARM_ARCH -// Seem to be compiling for non-ARM, so stick with critical section implementations -#define MBED_EXCLUSIVE_ACCESS 0U -#endif -#else -#define MBED_EXCLUSIVE_ACCESS __EXCLUSIVE_ACCESS -#endif -#endif - -#if MBED_EXCLUSIVE_ACCESS -#define MBED_INLINE_IF_EX inline -#else -#define MBED_INLINE_IF_EX -#endif - -/** - * A lock-free, primitive atomic flag. - * - * Emulate C11's atomic_flag. The flag is initially in an indeterminate state - * unless explicitly initialized with CORE_UTIL_ATOMIC_FLAG_INIT. - */ -typedef struct core_util_atomic_flag { - uint8_t _flag; -} core_util_atomic_flag; - -/** - * Initializer 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. - */ -MBED_INLINE_IF_EX bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr); - -/** \ copydoc core_util_atomic_flag_test_and_set - * @param order memory ordering constraint - */ -MBED_FORCEINLINE bool core_util_atomic_flag_test_and_set_explicit(volatile core_util_atomic_flag *valuePtr, mbed_memory_order order); - -/** - * Atomic clear. - * - * @param flagPtr Target flag being cleared. - */ -MBED_FORCEINLINE void core_util_atomic_flag_clear(volatile core_util_atomic_flag *flagPtr); - -/** \ copydoc core_util_atomic_flag_clear - * @param order memory ordering constraint - */ -MBED_FORCEINLINE void core_util_atomic_flag_clear_explicit(volatile core_util_atomic_flag *flagPtr, mbed_memory_order order); - - -/** - * 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 - * memory location to a given new value. This is done as a single atomic - * operation. The atomicity guarantees that the new value is calculated based on - * up-to-date information; if the value had been updated by another thread in - * the meantime, the write would fail due to a mismatched expectedCurrentValue. - * - * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect - * you to the article on compare-and swap]. - * - * @param ptr The target memory location. - * @param[in,out] expectedCurrentValue A pointer to some location holding the - * expected current value of the data being set atomically. - * The computed 'desiredValue' should be a function of this current value. - * @note: This is an in-out parameter. In the - * failure case of atomic_cas (where the - * destination isn't set), the pointee of expectedCurrentValue is - * updated with the current value. - * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. - * - * @return true if the memory location was atomically - * updated with the desired value (after verifying - * that it contained the expectedCurrentValue), - * false otherwise. In the failure case, - * exepctedCurrentValue is updated with the new - * value of the target memory location. - * - * pseudocode: - * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { - * if *p != *old { - * *old = *p - * return false - * } - * *p = new - * return true - * } - * - * @note: In the failure case (where the destination isn't set), the value - * pointed to by expectedCurrentValue is instead updated with the current value. - * This property helps writing concise code for the following incr: - * - * function incr(p : pointer to int, a : int) returns int { - * done = false - * value = atomic_load(p) - * while not done { - * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success - * } - * return value + a - * } - * - * However, if the call is made in a loop like this, the atomic_compare_exchange_weak - * functions are to be preferred. - * - * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it - * always succeeds if the current value is expected, as per the pseudocode - * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. - * This call would normally be used when a fail return does not retry. - */ -MBED_INLINE_IF_EX bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue); - -/** \copydoc core_util_atomic_cas_u8 - * @param success memory ordering constraint for successful exchange - * @param failure memory ordering constraint for failure - */ -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_cas_u8 */ -MBED_INLINE_IF_EX bool core_util_atomic_cas_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue); - -/** \copydoc core_util_atomic_cas_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_cas_u8 */ -MBED_INLINE_IF_EX bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue); - -/** \copydoc core_util_atomic_cas_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_cas_u8 */ -bool core_util_atomic_cas_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue); - -/** \copydoc core_util_atomic_cas_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_cas_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_s8(volatile int8_t *ptr, int8_t *expectedCurrentValue, int8_t desiredValue); - -/** \copydoc core_util_atomic_cas_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_s8(volatile int8_t *ptr, int8_t *expectedCurrentValue, int8_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_cas_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_s16(volatile int16_t *ptr, int16_t *expectedCurrentValue, int16_t desiredValue); - -/** \copydoc core_util_atomic_cas_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_s16(volatile int16_t *ptr, int16_t *expectedCurrentValue, int16_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_cas_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_s32(volatile int32_t *ptr, int32_t *expectedCurrentValue, int32_t desiredValue); - -/** \copydoc core_util_atomic_cas_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_s32(volatile int32_t *ptr, int32_t *expectedCurrentValue, int32_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_cas_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_s64(volatile int64_t *ptr, int64_t *expectedCurrentValue, int64_t desiredValue); - -/** \copydoc core_util_atomic_cas_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_s64(volatile int64_t *ptr, int64_t *expectedCurrentValue, int64_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_cas_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue); - -/** \copydoc core_util_atomic_cas_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_cas_u8 */ -inline bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue); - -/** \copydoc core_util_atomic_cas_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_cas_explicit_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue, mbed_memory_order success, mbed_memory_order failure); - - - -/** - * 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 - * memory location to a given new value. This is done as a single atomic - * operation. The atomicity guarantees that the new value is calculated based on - * up-to-date information; if the value had been updated by another thread in - * the meantime, the write would fail due to a mismatched expectedCurrentValue. - * - * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect - * you to the article on compare-and swap]. - * - * @param ptr The target memory location. - * @param[in,out] expectedCurrentValue A pointer to some location holding the - * expected current value of the data being set atomically. - * The computed 'desiredValue' should be a function of this current value. - * @note: This is an in-out parameter. In the - * failure case of atomic_cas (where the - * destination isn't set), the pointee of expectedCurrentValue is - * updated with the current value. - * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. - * - * @return true if the memory location was atomically - * updated with the desired value (after verifying - * that it contained the expectedCurrentValue), - * false otherwise. In the failure case, - * exepctedCurrentValue is updated with the new - * value of the target memory location. - * - * pseudocode: - * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { - * if *p != *old or spurious failure { - * *old = *p - * return false - * } - * *p = new - * return true - * } - * - * @note: In the failure case (where the destination isn't set), the value - * pointed to by expectedCurrentValue is instead updated with the current value. - * This property helps writing concise code for the following incr: - * - * function incr(p : pointer to int, a : int) returns int { - * done = false - * value = *p // This fetch operation need not be atomic. - * while not done { - * done = atomic_compare_exchange_weak(p, &value, value + a) // *value gets updated automatically until success - * } - * return value + a - * } - * - * @note: This corresponds to the C11 "atomic_compare_exchange_weak" - it - * may spuriously fail if the current value is expected, as per the pseudocode - * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. - * This call would normally be used when a fail return will cause a retry anyway, - * saving the need for an extra loop inside the cas operation. - */ -MBED_INLINE_IF_EX bool core_util_atomic_compare_exchange_weak_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue); - -/** \copydoc core_util_atomic_compare_exchange_weak_u8 - * @param success memory ordering constraint for successful exchange - * @param failure memory ordering constraint for failure - */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ -MBED_INLINE_IF_EX bool core_util_atomic_compare_exchange_weak_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue); - -/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ -MBED_INLINE_IF_EX bool core_util_atomic_compare_exchange_weak_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue); - -/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ -bool core_util_atomic_compare_exchange_weak_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue); - -/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_s8(volatile int8_t *ptr, int8_t *expectedCurrentValue, int8_t desiredValue); - -/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_s8(volatile int8_t *ptr, int8_t *expectedCurrentValue, int8_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_s16(volatile int16_t *ptr, int16_t *expectedCurrentValue, int16_t desiredValue); - -/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_s16(volatile int16_t *ptr, int16_t *expectedCurrentValue, int16_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_s32(volatile int32_t *ptr, int32_t *expectedCurrentValue, int32_t desiredValue); - -/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_s32(volatile int32_t *ptr, int32_t *expectedCurrentValue, int32_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_s64(volatile int64_t *ptr, int64_t *expectedCurrentValue, int64_t desiredValue); - -/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_s64(volatile int64_t *ptr, int64_t *expectedCurrentValue, int64_t desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue); - -/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_bool(volatile bool *ptr, bool *expectedCurrentValue, bool desiredValue, mbed_memory_order success, mbed_memory_order failure); - -/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue); - -/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_compare_exchange_weak_explicit_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue, mbed_memory_order success, mbed_memory_order failure); - - -/** - * Atomic load. - * @param valuePtr Target memory location. - * @return The loaded value. - */ -MBED_FORCEINLINE uint8_t core_util_atomic_load_u8(const volatile uint8_t *valuePtr); - -/** - * \copydoc core_util_atomic_load_u8 - * @param order memory ordering constraint - */ -MBED_FORCEINLINE uint8_t core_util_atomic_load_explicit_u8(const volatile uint8_t *valuePtr, mbed_memory_order order); - -/** \copydoc core_util_atomic_load_u8 */ -MBED_FORCEINLINE uint16_t core_util_atomic_load_u16(const volatile uint16_t *valuePtr); - -/** \copydoc core_util_atomic_load_explicit_u8 */ -MBED_FORCEINLINE uint16_t core_util_atomic_load_explicit_u16(const volatile uint16_t *valuePtr, mbed_memory_order order); - -/** \copydoc core_util_atomic_load_u8 */ -MBED_FORCEINLINE uint32_t core_util_atomic_load_u32(const volatile uint32_t *valuePtr); - -/** \copydoc core_util_atomic_load_explicit_u8 */ -MBED_FORCEINLINE uint32_t core_util_atomic_load_explicit_u32(const volatile uint32_t *valuePtr, mbed_memory_order order); - -/** \copydoc core_util_atomic_load_u8 */ -uint64_t core_util_atomic_load_u64(const volatile uint64_t *valuePtr); - -/** \copydoc core_util_atomic_load_explicit_u8 */ -MBED_FORCEINLINE uint64_t core_util_atomic_load_explicit_u64(const volatile uint64_t *valuePtr, mbed_memory_order order); - -/** \copydoc core_util_atomic_load_u8 */ -MBED_FORCEINLINE int8_t core_util_atomic_load_s8(const volatile int8_t *valuePtr); - -/** \copydoc core_util_atomic_load_explicit_u8 */ -MBED_FORCEINLINE int8_t core_util_atomic_load_explicit_s8(const volatile int8_t *valuePtr, mbed_memory_order order); - -/** \copydoc core_util_atomic_load_u8 */ -MBED_FORCEINLINE int16_t core_util_atomic_load_s16(const volatile int16_t *valuePtr); - -/** \copydoc core_util_atomic_load_explicit_u8 */ -MBED_FORCEINLINE int16_t core_util_atomic_load_explicit_s16(const volatile int16_t *valuePtr, mbed_memory_order order); - -/** \copydoc core_util_atomic_load_u8 */ -MBED_FORCEINLINE int32_t core_util_atomic_load_s32(const volatile int32_t *valuePtr); - -/** \copydoc core_util_atomic_load_explicit_u8 */ -MBED_FORCEINLINE int32_t core_util_atomic_load_explicit_s32(const volatile int32_t *valuePtr, mbed_memory_order order); - -/** \copydoc core_util_atomic_load_u8 */ -MBED_FORCEINLINE int64_t core_util_atomic_load_s64(const volatile int64_t *valuePtr); - -/** \copydoc core_util_atomic_load_u8 */ -MBED_FORCEINLINE int64_t core_util_atomic_load_explicit_s64(const volatile int64_t *valuePtr, MBED_UNUSED mbed_memory_order order); - -/** \copydoc core_util_atomic_load_u8 */ -MBED_FORCEINLINE bool core_util_atomic_load_bool(const volatile bool *valuePtr); - -/** \copydoc core_util_atomic_load_u8 */ -MBED_FORCEINLINE bool core_util_atomic_load_explicit_bool(const volatile bool *valuePtr, mbed_memory_order order); - -/** \copydoc core_util_atomic_load_u8 */ -MBED_FORCEINLINE void *core_util_atomic_load_ptr(void *const volatile *valuePtr); - -/** \copydoc core_util_atomic_load_u8 */ -MBED_FORCEINLINE void *core_util_atomic_load_explicit_ptr(void *const volatile *valuePtr, mbed_memory_order order); - -/** - * Atomic store. - * @param valuePtr Target memory location. - * @param desiredValue The value to store. - */ -MBED_FORCEINLINE void core_util_atomic_store_u8(volatile uint8_t *valuePtr, uint8_t desiredValue); - -/** - * \copydoc core_util_atomic_store_u8 - * @param order memory ordering constraint - */ -MBED_FORCEINLINE void core_util_atomic_store_explicit_u8(volatile uint8_t *valuePtr, uint8_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_store_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_u16(volatile uint16_t *valuePtr, uint16_t desiredValue); - -/** \copydoc core_util_atomic_store_explicit_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_explicit_u16(volatile uint16_t *valuePtr, uint16_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_store_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_u32(volatile uint32_t *valuePtr, uint32_t desiredValue); - -/** \copydoc core_util_atomic_store_explicit_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_explicit_u32(volatile uint32_t *valuePtr, uint32_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_store_u8 */ -void core_util_atomic_store_u64(volatile uint64_t *valuePtr, uint64_t desiredValue); - -/** \copydoc core_util_atomic_store_explicit_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_explicit_u64(volatile uint64_t *valuePtr, uint64_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_store_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_s8(volatile int8_t *valuePtr, int8_t desiredValue); - -/** \copydoc core_util_atomic_store_explicit_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_explicit_s8(volatile int8_t *valuePtr, int8_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_store_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_s16(volatile int16_t *valuePtr, int16_t desiredValue); - -/** \copydoc core_util_atomic_store_explicit_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_explicit_s16(volatile int16_t *valuePtr, int16_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_store_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_s32(volatile int32_t *valuePtr, int32_t desiredValue); - -/** \copydoc core_util_atomic_store_explicit_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_explicit_s32(volatile int32_t *valuePtr, int32_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_store_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_s64(volatile int64_t *valuePtr, int64_t desiredValue); - -/** \copydoc core_util_atomic_store_explicit_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_explicit_s64(volatile int64_t *valuePtr, int64_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_store_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_bool(volatile bool *valuePtr, bool desiredValue); - -/** \copydoc core_util_atomic_store_explicit_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_explicit_bool(volatile bool *valuePtr, bool desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_store_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_ptr(void *volatile *valuePtr, void *desiredValue); - -/** \copydoc core_util_atomic_store_explicit_u8 */ -MBED_FORCEINLINE void core_util_atomic_store_explicit_ptr(void *volatile *valuePtr, void *desiredValue, mbed_memory_order order); - -/** - * Atomic exchange. - * @param valuePtr Target memory location. - * @param desiredValue The value to store. - * @return The previous value. - */ -MBED_INLINE_IF_EX uint8_t core_util_atomic_exchange_u8(volatile uint8_t *valuePtr, uint8_t desiredValue); - -/** \copydoc core_util_atomic_exchange_u8 - * @param order memory ordering constraint - */ -MBED_FORCEINLINE uint8_t core_util_atomic_exchange_explicit_u8(volatile uint8_t *valuePtr, uint8_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_exchange_u8 */ -MBED_INLINE_IF_EX uint16_t core_util_atomic_exchange_u16(volatile uint16_t *valuePtr, uint16_t desiredValue); - -/** \copydoc core_util_atomic_exchange_explicit_u8 */ -MBED_FORCEINLINE uint16_t core_util_atomic_exchange_explicit_u16(volatile uint16_t *valuePtr, uint16_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_exchange_u8 */ -MBED_INLINE_IF_EX uint32_t core_util_atomic_exchange_u32(volatile uint32_t *valuePtr, uint32_t desiredValue); - -/** \copydoc core_util_atomic_exchange_explicit_u8 */ -MBED_FORCEINLINE uint32_t core_util_atomic_exchange_explicit_u32(volatile uint32_t *valuePtr, uint32_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_exchange_u8 */ -uint64_t core_util_atomic_exchange_u64(volatile uint64_t *valuePtr, uint64_t desiredValue); - -/** \copydoc core_util_atomic_exchange_explicit_u8 */ -MBED_FORCEINLINE uint64_t core_util_atomic_exchange_explicit_u64(volatile uint64_t *valuePtr, uint64_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_exchange_u8 */ -MBED_FORCEINLINE int8_t core_util_atomic_exchange_s8(volatile int8_t *valuePtr, int8_t desiredValue); - -/** \copydoc core_util_atomic_exchange_explicit_u8 */ -MBED_FORCEINLINE int8_t core_util_atomic_exchange_explicit_s8(volatile int8_t *valuePtr, int8_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_exchange_u8 */ -MBED_FORCEINLINE int16_t core_util_atomic_exchange_s16(volatile int16_t *valuePtr, int16_t desiredValue); - -/** \copydoc core_util_atomic_exchange_explicit_u8 */ -MBED_FORCEINLINE int16_t core_util_atomic_exchange_explicit_s16(volatile int16_t *valuePtr, int16_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_exchange_u8 */ -MBED_FORCEINLINE int32_t core_util_atomic_exchange_s32(volatile int32_t *valuePtr, int32_t desiredValue); - -/** \copydoc core_util_atomic_exchange_explicit_u8 */ -MBED_FORCEINLINE int32_t core_util_atomic_exchange_explicit_s32(volatile int32_t *valuePtr, int32_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_exchange_u8 */ -MBED_FORCEINLINE int64_t core_util_atomic_exchange_s64(volatile int64_t *valuePtr, int64_t desiredValue); - -/** \copydoc core_util_atomic_exchange_explicit_u8 */ -MBED_FORCEINLINE int64_t core_util_atomic_exchange_explicit_s64(volatile int64_t *valuePtr, int64_t desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_exchange_u8 */ -MBED_FORCEINLINE bool core_util_atomic_exchange_bool(volatile bool *valuePtr, bool desiredValue); - -/** \copydoc core_util_atomic_exchange_explicit_u8 */ -MBED_FORCEINLINE bool core_util_atomic_exchange_explicit_bool(volatile bool *valuePtr, bool desiredValue, mbed_memory_order order); - -/** \copydoc core_util_atomic_exchange_u8 */ -inline void *core_util_atomic_exchange_ptr(void *volatile *valuePtr, void *desiredValue); - -/** \copydoc core_util_atomic_exchange_explicit_u8 */ -MBED_FORCEINLINE void *core_util_atomic_exchange_explicit_ptr(void *volatile *valuePtr, void *desiredValue, mbed_memory_order order); - -/** - * Atomic increment. - * @param valuePtr Target memory location being incremented. - * @param delta The amount being incremented. - * @return The new incremented value. - */ -MBED_INLINE_IF_EX uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta); - -/** \copydoc core_util_atomic_incr_u8 */ -MBED_INLINE_IF_EX uint16_t core_util_atomic_incr_u16(volatile uint16_t *valuePtr, uint16_t delta); - -/** \copydoc core_util_atomic_incr_u8 */ -MBED_INLINE_IF_EX uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta); - -/** \copydoc core_util_atomic_incr_u8 */ -uint64_t core_util_atomic_incr_u64(volatile uint64_t *valuePtr, uint64_t delta); - -/** \copydoc core_util_atomic_incr_u8 */ -MBED_FORCEINLINE int8_t core_util_atomic_incr_s8(volatile int8_t *valuePtr, int8_t delta); - -/** \copydoc core_util_atomic_incr_u8 */ -MBED_FORCEINLINE int16_t core_util_atomic_incr_s16(volatile int16_t *valuePtr, int16_t delta); - -/** \copydoc core_util_atomic_incr_u8 */ -MBED_FORCEINLINE int32_t core_util_atomic_incr_s32(volatile int32_t *valuePtr, int32_t delta); - -/** \copydoc core_util_atomic_incr_u8 */ -MBED_FORCEINLINE int64_t core_util_atomic_incr_s64(volatile int64_t *valuePtr, int64_t delta); - -/** \copydoc core_util_atomic_incr_u8 */ -inline void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta); - -/** - * Atomic decrement. - * @param valuePtr Target memory location being decremented. - * @param delta The amount being decremented. - * @return The new decremented value. - */ -MBED_INLINE_IF_EX uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t delta); - -/** \copydoc core_util_atomic_decr_u8 */ -MBED_INLINE_IF_EX uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t delta); - -/** \copydoc core_util_atomic_decr_u8 */ -MBED_INLINE_IF_EX uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta); - -/** \copydoc core_util_atomic_decr_u8 */ -uint64_t core_util_atomic_decr_u64(volatile uint64_t *valuePtr, uint64_t delta); - -/** \copydoc core_util_atomic_decr_u8 */ -MBED_FORCEINLINE int8_t core_util_atomic_decr_s8(volatile int8_t *valuePtr, int8_t delta); - -/** \copydoc core_util_atomic_decr_u8 */ -MBED_FORCEINLINE int16_t core_util_atomic_decr_s16(volatile int16_t *valuePtr, int16_t delta); - -/** \copydoc core_util_atomic_decr_u8 */ -MBED_FORCEINLINE int32_t core_util_atomic_decr_s32(volatile int32_t *valuePtr, int32_t delta); - -/** \copydoc core_util_atomic_decr_u8 */ -MBED_FORCEINLINE int64_t core_util_atomic_decr_s64(volatile int64_t *valuePtr, int64_t delta); - -/** \copydoc core_util_atomic_decr_u8 */ -inline void *core_util_atomic_decr_ptr(void *volatile *valuePtr, ptrdiff_t delta); - -/** - * Atomic add. - * @param valuePtr Target memory location being modified. - * @param arg The argument for the addition. - * @return The original value. - */ -MBED_INLINE_IF_EX uint8_t core_util_atomic_fetch_add_u8(volatile uint8_t *valuePtr, uint8_t arg); - -/** \copydoc core_util_atomic_fetch_add_u8 - * @param order memory ordering constraint - */ -MBED_FORCEINLINE uint8_t core_util_atomic_fetch_add_explicit_u8(volatile uint8_t *valuePtr, uint8_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_add_u8 */ -MBED_INLINE_IF_EX uint16_t core_util_atomic_fetch_add_u16(volatile uint16_t *valuePtr, uint16_t arg); - -/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ -MBED_FORCEINLINE uint16_t core_util_atomic_fetch_add_explicit_u16(volatile uint16_t *valuePtr, uint16_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_add_u8 */ -MBED_INLINE_IF_EX uint32_t core_util_atomic_fetch_add_u32(volatile uint32_t *valuePtr, uint32_t arg); - -/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ -MBED_FORCEINLINE uint32_t core_util_atomic_fetch_add_explicit_u32(volatile uint32_t *valuePtr, uint32_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_add_u8 */ -uint64_t core_util_atomic_fetch_add_u64(volatile uint64_t *valuePtr, uint64_t arg); - -/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ -MBED_FORCEINLINE uint64_t core_util_atomic_fetch_add_explicit_u64(volatile uint64_t *valuePtr, uint64_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_add_u8 */ -MBED_FORCEINLINE int8_t core_util_atomic_fetch_add_s8(volatile int8_t *valuePtr, int8_t arg); - -/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ -MBED_FORCEINLINE int8_t core_util_atomic_fetch_add_explicit_s8(volatile int8_t *valuePtr, int8_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_add_u8 */ -MBED_FORCEINLINE int16_t core_util_atomic_fetch_add_s16(volatile int16_t *valuePtr, int16_t arg); - -/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ -MBED_FORCEINLINE int16_t core_util_atomic_fetch_add_explicit_s16(volatile int16_t *valuePtr, int16_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_add_u8 */ -MBED_FORCEINLINE int32_t core_util_atomic_fetch_add_s32(volatile int32_t *valuePtr, int32_t arg); - -/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ -MBED_FORCEINLINE int32_t core_util_atomic_fetch_add_explicit_s32(volatile int32_t *valuePtr, int32_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_add_u8 */ -MBED_FORCEINLINE int64_t core_util_atomic_fetch_add_s64(volatile int64_t *valuePtr, int64_t arg); - -/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ -MBED_FORCEINLINE int64_t core_util_atomic_fetch_add_explicit_s64(volatile int64_t *valuePtr, int64_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_add_u8 */ -MBED_FORCEINLINE void *core_util_atomic_fetch_add_ptr(void *volatile *valuePtr, ptrdiff_t arg); - -/** \copydoc core_util_atomic_fetch_add_explicit_u8 */ -MBED_FORCEINLINE void *core_util_atomic_fetch_add_explicit_ptr(void *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order); - -/** - * Atomic subtract. - * @param valuePtr Target memory location being modified. - * @param arg The argument for the subtraction. - * @return The original value. - */ -MBED_INLINE_IF_EX uint8_t core_util_atomic_fetch_sub_u8(volatile uint8_t *valuePtr, uint8_t arg); - -/** \copydoc core_util_atomic_fetch_sub_u8 - * @param order memory ordering constraint - */ -MBED_FORCEINLINE uint8_t core_util_atomic_fetch_sub_explicit_u8(volatile uint8_t *valuePtr, uint8_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_sub_u8 */ -MBED_INLINE_IF_EX uint16_t core_util_atomic_fetch_sub_u16(volatile uint16_t *valuePtr, uint16_t arg); - -/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ -MBED_FORCEINLINE uint16_t core_util_atomic_fetch_sub_explicit_u16(volatile uint16_t *valuePtr, uint16_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_sub_u8 */ -MBED_INLINE_IF_EX uint32_t core_util_atomic_fetch_sub_u32(volatile uint32_t *valuePtr, uint32_t arg); - -/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ -MBED_FORCEINLINE uint32_t core_util_atomic_fetch_sub_explicit_u32(volatile uint32_t *valuePtr, uint32_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_sub_u8 */ -uint64_t core_util_atomic_fetch_sub_u64(volatile uint64_t *valuePtr, uint64_t arg); - -/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ -MBED_FORCEINLINE uint64_t core_util_atomic_fetch_sub_explicit_u64(volatile uint64_t *valuePtr, uint64_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_sub_u8 */ -MBED_FORCEINLINE int8_t core_util_atomic_fetch_sub_s8(volatile int8_t *valuePtr, int8_t arg); - -/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ -MBED_FORCEINLINE int8_t core_util_atomic_fetch_sub_explicit_s8(volatile int8_t *valuePtr, int8_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_sub_u8 */ -MBED_FORCEINLINE int16_t core_util_atomic_fetch_sub_s16(volatile int16_t *valuePtr, int16_t arg); - -/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ -MBED_FORCEINLINE int16_t core_util_atomic_fetch_sub_explicit_s16(volatile int16_t *valuePtr, int16_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_sub_u8 */ -MBED_FORCEINLINE int32_t core_util_atomic_fetch_sub_s32(volatile int32_t *valuePtr, int32_t arg); - -/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ -MBED_FORCEINLINE int32_t core_util_atomic_fetch_sub_explicit_s32(volatile int32_t *valuePtr, int32_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_sub_u8 */ -MBED_FORCEINLINE int64_t core_util_atomic_fetch_sub_s64(volatile int64_t *valuePtr, int64_t arg); - -/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ -MBED_FORCEINLINE int64_t core_util_atomic_fetch_sub_explicit_s64(volatile int64_t *valuePtr, int64_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_sub_u8 */ -MBED_FORCEINLINE void *core_util_atomic_fetch_sub_ptr(void *volatile *valuePtr, ptrdiff_t arg); - -/** \copydoc core_util_atomic_fetch_sub_explicit_u8 */ -MBED_FORCEINLINE void *core_util_atomic_fetch_sub_explicit_ptr(void *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order); - -/** - * Atomic bitwise and. - * @param valuePtr Target memory location being modified. - * @param arg The argument for the bitwise operation. - * @return The original value. - */ -MBED_INLINE_IF_EX uint8_t core_util_atomic_fetch_and_u8(volatile uint8_t *valuePtr, uint8_t arg); - -/** \copydoc core_util_atomic_fetch_and_u8 - * @param order memory ordering constraint - */ -MBED_FORCEINLINE uint8_t core_util_atomic_fetch_and_explicit_u8(volatile uint8_t *valuePtr, uint8_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_and_u8 */ -MBED_INLINE_IF_EX uint16_t core_util_atomic_fetch_and_u16(volatile uint16_t *valuePtr, uint16_t arg); - -/** \copydoc core_util_atomic_fetch_and_explicit_u8 */ -MBED_FORCEINLINE uint16_t core_util_atomic_fetch_and_explicit_u16(volatile uint16_t *valuePtr, uint16_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_and_u8 */ -MBED_INLINE_IF_EX uint32_t core_util_atomic_fetch_and_u32(volatile uint32_t *valuePtr, uint32_t arg); - -/** \copydoc core_util_atomic_fetch_and_explicit_u8 */ -MBED_FORCEINLINE uint32_t core_util_atomic_fetch_and_explicit_u32(volatile uint32_t *valuePtr, uint32_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_and_u8 */ -uint64_t core_util_atomic_fetch_and_u64(volatile uint64_t *valuePtr, uint64_t arg); - -/** \copydoc core_util_atomic_fetch_and_explicit_u8 */ -MBED_FORCEINLINE uint64_t core_util_atomic_fetch_and_explicit_u64(volatile uint64_t *valuePtr, uint64_t arg, mbed_memory_order order); - -/** - * Atomic bitwise inclusive or. - * @param valuePtr Target memory location being modified. - * @param arg The argument for the bitwise operation. - * @return The original value. - */ -MBED_INLINE_IF_EX uint8_t core_util_atomic_fetch_or_u8(volatile uint8_t *valuePtr, uint8_t arg); - -/** \copydoc core_util_atomic_fetch_or_u8 - * @param order memory ordering constraint - */ -MBED_FORCEINLINE uint8_t core_util_atomic_fetch_or_explicit_u8(volatile uint8_t *valuePtr, uint8_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_or_u8 */ -MBED_INLINE_IF_EX uint16_t core_util_atomic_fetch_or_u16(volatile uint16_t *valuePtr, uint16_t arg); - -/** \copydoc core_util_atomic_fetch_or_explicit_u8 */ -MBED_FORCEINLINE uint16_t core_util_atomic_fetch_or_explicit_u16(volatile uint16_t *valuePtr, uint16_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_or_u8 */ -MBED_INLINE_IF_EX uint32_t core_util_atomic_fetch_or_u32(volatile uint32_t *valuePtr, uint32_t arg); - -/** \copydoc core_util_atomic_fetch_or_explicit_u8 */ -MBED_FORCEINLINE uint32_t core_util_atomic_fetch_or_explicit_u32(volatile uint32_t *valuePtr, uint32_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_or_u8 */ -uint64_t core_util_atomic_fetch_or_u64(volatile uint64_t *valuePtr, uint64_t arg); - -/** \copydoc core_util_atomic_fetch_or_explicit_u8 */ -MBED_FORCEINLINE uint64_t core_util_atomic_fetch_or_explicit_u64(volatile uint64_t *valuePtr, uint64_t arg, mbed_memory_order order); - -/** - * Atomic bitwise exclusive or. - * @param valuePtr Target memory location being modified. - * @param arg The argument for the bitwise operation. - * @return The original value. - */ -MBED_INLINE_IF_EX uint8_t core_util_atomic_fetch_xor_u8(volatile uint8_t *valuePtr, uint8_t arg); - -/** \copydoc core_util_atomic_fetch_xor_u8 - * @param order memory ordering constraint - */ -MBED_FORCEINLINE uint8_t core_util_atomic_fetch_xor_explicit_u8(volatile uint8_t *valuePtr, uint8_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_xor_u8 */ -MBED_INLINE_IF_EX uint16_t core_util_atomic_fetch_xor_u16(volatile uint16_t *valuePtr, uint16_t arg); - -/** \copydoc core_util_atomic_fetch_xor_explicit_u8 */ -MBED_FORCEINLINE uint16_t core_util_atomic_fetch_xor_explicit_u16(volatile uint16_t *valuePtr, uint16_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_xor_u8 */ -MBED_INLINE_IF_EX uint32_t core_util_atomic_fetch_xor_u32(volatile uint32_t *valuePtr, uint32_t arg); - -/** \copydoc core_util_atomic_fetch_xor_explicit_u8 */ -MBED_FORCEINLINE uint32_t core_util_atomic_fetch_xor_explicit_u32(volatile uint32_t *valuePtr, uint32_t arg, mbed_memory_order order); - -/** \copydoc core_util_atomic_fetch_xor_u8 */ -uint64_t core_util_atomic_fetch_xor_u64(volatile uint64_t *valuePtr, uint64_t arg); - -/** \copydoc core_util_atomic_fetch_xor_explicit_u8 */ -MBED_FORCEINLINE uint64_t core_util_atomic_fetch_xor_explicit_u64(volatile uint64_t *valuePtr, uint64_t arg, mbed_memory_order order); - -#ifdef __cplusplus -} // extern "C" - -#include - -// For each operation, two overloaded templates: -// * one for non-pointer types, which has implementations based on the -// u8/u16/u32/u64/s8/s16/s32/s64/bool functions above. No base implementation. -// * one for any pointer type, generically implemented based on ptr function above. -// -// Templates use standard C/C++ naming - old incr/decr/cas forms are not provided. -// -// The `type_identity_t` used here means "same type as T", blocking template -// argument deduction. It forces type selection based on the type of the actual pointer -// to the atomic. If just `T` was used, the following would be ambiguous: -// core_util_atomic_store(&my_uint8_t, 1) - it wouldn't be able to select between T -// being uint8_t and int. - -/** \copydoc core_util_atomic_load_u8 */ -template T core_util_atomic_load(const volatile T *valuePtr) noexcept; -/** \copydoc core_util_atomic_load_u8 */ -template T core_util_atomic_load(const T *valuePtr) noexcept; -/** \copydoc core_util_atomic_store_u8 */ -template void core_util_atomic_store(volatile T *valuePtr, mstd::type_identity_t desiredValue) noexcept; -/** \copydoc core_util_atomic_store_u8 */ -template void core_util_atomic_store(T *valuePtr, mstd::type_identity_t desiredValue) noexcept; -/** \copydoc core_util_atomic_exchange_u8 */ -template T core_util_atomic_exchange(volatile T *ptr, mstd::type_identity_t desiredValue) noexcept; -/** \copydoc core_util_atomic_cas_u8 */ -template bool core_util_atomic_compare_exchange_strong(volatile T *ptr, mstd::type_identity_t *expectedCurrentValue, mstd::type_identity_t desiredValue) noexcept; -/** \copydoc core_util_atomic_compare_exchange_weak_u8 */ -template bool core_util_atomic_compare_exchange_weak(volatile T *ptr, mstd::type_identity_t *expectedCurrentValue, mstd::type_identity_t desiredValue) noexcept; -/** \copydoc core_util_fetch_add_u8 */ -template T core_util_atomic_fetch_add(volatile T *valuePtr, mstd::type_identity_t arg) noexcept; -/** \copydoc core_util_fetch_sub_u8 */ -template T core_util_atomic_fetch_sub(volatile T *valuePtr, mstd::type_identity_t arg) noexcept; -/** \copydoc core_util_fetch_and_u8 */ -template T core_util_atomic_fetch_and(volatile T *valuePtr, mstd::type_identity_t arg) noexcept; -/** \copydoc core_util_fetch_or_u8 */ -template T core_util_atomic_fetch_or(volatile T *valuePtr, mstd::type_identity_t arg) noexcept; -/** \copydoc core_util_fetch_xor_u8 */ -template T core_util_atomic_fetch_xor(volatile T *valuePtr, mstd::type_identity_t arg) noexcept; - -/** \copydoc core_util_atomic_load_explicit_u8 */ -template T core_util_atomic_load_explicit(const volatile T *valuePtr, mbed_memory_order order) noexcept; -/** \copydoc core_util_atomic_load_explicit_u8 */ -template T core_util_atomic_load_explicit(const T *valuePtr, mbed_memory_order order) noexcept; -/** \copydoc core_util_atomic_store_explicit_u8 */ -template void core_util_atomic_store_explicit(volatile T *valuePtr, mstd::type_identity_t desiredValue, mbed_memory_order order) noexcept; -/** \copydoc core_util_atomic_store_explicit_u8 */ -template void core_util_atomic_store_explicit(T *valuePtr, mstd::type_identity_t desiredValue, mbed_memory_order order) noexcept; -/** \copydoc core_util_atomic_exchange_explicit_u8 */ -template T core_util_atomic_exchange_explicit(volatile T *ptr, mstd::type_identity_t desiredValue, mbed_memory_order order) noexcept; -/** \copydoc core_util_atomic_cas_explicit_u8 */ -template bool core_util_atomic_compare_exchange_strong_explicit(volatile T *ptr, mstd::type_identity_t *expectedCurrentValue, mstd::type_identity_t desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept; -/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */ -template bool core_util_atomic_compare_exchange_weak_explicit(volatile T *ptr, mstd::type_identity_t *expectedCurrentValue, mstd::type_identity_t desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept; -/** \copydoc core_util_fetch_add_explicit_u8 */ -template T core_util_atomic_fetch_add_explicit(volatile T *valuePtr, mstd::type_identity_t arg, mbed_memory_order order) noexcept; -/** \copydoc core_util_fetch_sub_explicit_u8 */ -template T core_util_atomic_fetch_sub_explicit(volatile T *valuePtr, mstd::type_identity_t arg, mbed_memory_order order) noexcept; -/** \copydoc core_util_fetch_and_explicit_u8 */ -template T core_util_atomic_fetch_and_explicit(volatile T *valuePtr, mstd::type_identity_t arg, mbed_memory_order order) noexcept; -/** \copydoc core_util_fetch_or_explicit_u8 */ -template T core_util_atomic_fetch_or_explicit(volatile T *valuePtr, mstd::type_identity_t arg, mbed_memory_order order) noexcept; -/** \copydoc core_util_fetch_xor_explicit_u8 */ -template T core_util_atomic_fetch_xor_explicit(volatile T *valuePtr, mstd::type_identity_t arg, mbed_memory_order order) noexcept; - -/** \copydoc core_util_atomic_load_ptr */ -template inline T *core_util_atomic_load(T *const volatile *valuePtr) noexcept; -/** \copydoc core_util_atomic_load_ptr */ -template inline T *core_util_atomic_load(T *const *valuePtr) noexcept; -/** \copydoc core_util_atomic_store_ptr */ -template inline void core_util_atomic_store(T *volatile *valuePtr, mstd::type_identity_t *desiredValue) noexcept; -/** \copydoc core_util_atomic_store_ptr */ -template inline void core_util_atomic_store(T **valuePtr, mstd::type_identity_t *desiredValue) noexcept; -/** \copydoc core_util_atomic_exchange_ptr */ -template inline T *core_util_atomic_exchange(T *volatile *valuePtr, mstd::type_identity_t *desiredValue) noexcept; -/** \copydoc core_util_atomic_cas_ptr */ -template inline bool core_util_atomic_compare_exchange_strong(T *volatile *ptr, mstd::type_identity_t **expectedCurrentValue, mstd::type_identity_t *desiredValue) noexcept; -/** \copydoc core_util_atomic_compare_exchange_weak_ptr */ -template inline bool core_util_atomic_compare_exchange_weak(T *volatile *ptr, mstd::type_identity_t **expectedCurrentValue, mstd::type_identity_t *desiredValue) noexcept; -/** \copydoc core_util_fetch_add_ptr */ -template inline T *core_util_atomic_fetch_add(T *volatile *valuePtr, ptrdiff_t arg) noexcept; -/** \copydoc core_util_fetch_sub_ptr */ -template inline T *core_util_atomic_fetch_sub(T *volatile *valuePtr, ptrdiff_t arg) noexcept; - -/** \copydoc core_util_atomic_load_explicit_ptr */ -template inline T *core_util_atomic_load_explicit(T *const volatile *valuePtr, mbed_memory_order order) noexcept; -/** \copydoc core_util_atomic_load_explicit_ptr */ -template inline T *core_util_atomic_load_explicit(T *const *valuePtr, mbed_memory_order order) noexcept; -/** \copydoc core_util_atomic_store_explicit_ptr */ -template inline void core_util_atomic_store_explicit(T *volatile *valuePtr, mstd::type_identity_t *desiredValue, mbed_memory_order order) noexcept; -/** \copydoc core_util_atomic_store_explicit_ptr */ -template inline void core_util_atomic_store_explicit(T **valuePtr, mstd::type_identity_t *desiredValue, mbed_memory_order order) noexcept; -/** \copydoc core_util_atomic_exchange_explicit_ptr */ -template inline T *core_util_atomic_exchange_explicit(T *volatile *valuePtr, mstd::type_identity_t *desiredValue, mbed_memory_order order) noexcept; -/** \copydoc core_util_atomic_cas_explicit_ptr */ -template inline bool core_util_atomic_compare_exchange_strong_explicit(T *volatile *ptr, mstd::type_identity_t **expectedCurrentValue, mstd::type_identity_t *desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept; -/** \copydoc core_util_atomic_compare_exchange_weak_explicit_ptr */ -template inline bool core_util_atomic_compare_exchange_weak_explicit(T *volatile *ptr, mstd::type_identity_t **expectedCurrentValue, mstd::type_identity_t *desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept; -/** \copydoc core_util_fetch_add_explicit_ptr */ -template inline T *core_util_atomic_fetch_add_explicit(T *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) noexcept; -/** \copydoc core_util_fetch_sub_explicit_ptr */ -template inline T *core_util_atomic_fetch_sub_explicit(T *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) noexcept; - -#endif // __cplusplus - -/**@}*/ - -/**@}*/ - -/* Hide the implementation away */ -#include "platform/internal/mbed_atomic_impl.h" - -#endif // __MBED_UTIL_ATOMICL_H__ - - - diff --git a/platform/mbed_chrono.h b/platform/mbed_chrono.h deleted file mode 100644 index 210d64b..0000000 --- a/platform/mbed_chrono.h +++ /dev/null @@ -1,128 +0,0 @@ - -/* - * Copyright (c) 2015-2019, 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 __MBED_CHRONO_H__ -#define __MBED_CHRONO_H__ - -#include "mbed_toolchain.h" -#include -#include -#include -#include - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_chrono chrono utilities - * - * Additions and variations of std::chrono - * - * - unsigned 32-bit variants of standard signed 64-bit duration types - * - centiseconds and deciseconds - * @{ - */ -namespace mbed { - -/* Extensions declared in mbed::chrono, following pattern of std::chrono */ -namespace chrono { - -/* Add deciseconds and centiseconds - may be - * useful to use lower precision when not messing with templating. - */ -using deciseconds = std::chrono::duration; -using centiseconds = std::chrono::duration; - -/** 32-bit microsecond duration type - * - * Standard std::chrono::microseconds is signed 64-bit. For some purposes - * it's more efficient to process small times as 32-bit. And when doing so, - * as we likely need to worry about wrapping, use of an unsigned - * value to process modulo 2**32 is appropriate. - */ -using microseconds_u32 = std::chrono::duration; - -/** 32-bit millisecond duration type - * - * Standard std::chrono::milliseconds is signed 64-bit. For some purposes - * it's more efficient to process times as 32-bit. And when doing so, - * as we likely need to worry about wrapping, use of an unsigned - * value to process modulo 2**32 is appropriate. - */ -using milliseconds_u32 = std::chrono::duration; - -} // namespace chrono - -inline namespace literals { - -inline namespace chrono_literals { - -/** User-defined literal for deciseconds (1/10 of a second) - * - * Useful in case we might change kernel tick frequency to be slower - with tick frequency 1000Hz, it is - * possible to assign 500ms to a KernelClock::duration, but that would fail at slower rates. - * - * Example use: - * - * using namespace mbed::chrono_literals; - * - * ThisThread::sleep_for(5_ds); - */ -constexpr chrono::deciseconds operator "" _ds(unsigned long long x) -{ - chrono::deciseconds::rep val = static_cast(x); - assert(val >= 0 && static_cast(val) == x); - return chrono::deciseconds(val); -} - -/** User-defined literal for centiseconds (1/100 of a second) - * - * Useful in case we might change kernel tick frequency to be slower - with tick frequency 1000Hz, it is - * possible to assign 500ms to a KernelClock::duration, but that would fail at slower rates. - * - * Example use: - * - * using namespace mbed::chrono_literals; - * - * ThisThread::sleep_for(1_cs); - */ -constexpr chrono::centiseconds operator "" _cs(unsigned long long x) -{ - chrono::centiseconds::rep val = static_cast(x); - assert(val >= 0 && static_cast(val) == x); - return chrono::centiseconds(val); -} - -} // inline namespace chrono_literals - -} // inline namespace literals - -namespace chrono { - -using namespace chrono_literals; - -} // namespace chrono - -} // namespace mbed - -/**@}*/ - -/**@}*/ - -#endif // __MBED_CHRONO_H__ - diff --git a/platform/mbed_critical.h b/platform/mbed_critical.h deleted file mode 100644 index 9213794..0000000 --- a/platform/mbed_critical.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2015-2019, 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 __MBED_UTIL_CRITICAL_H__ -#define __MBED_UTIL_CRITICAL_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup platform-public-api */ -/** @{*/ -/** - * \defgroup platform_critical critical section function - * @{ - */ - -/** Determine the current interrupts enabled state - * - * 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 underlying implementation - * differs. - * @return true if interrupts are enabled, false otherwise - */ -bool core_util_are_interrupts_enabled(void); - -/** Determine if this code is executing from an interrupt - * - * 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 underlying implementation - * differs. - * @return true if in an isr, false otherwise - */ -bool core_util_is_isr_active(void); - -/** Mark the start of a critical section - * - * This function should be called to mark the start of a critical section of code. - * @note - * NOTES: - * 1) The use of this style of critical section is targetted at C based implementations. - * 2) These critical sections can be nested. - * 3) The interrupt enable state on entry to the first critical section (of a nested set, or single - * section) will be preserved on exit from the section. - * 4) This implementation will currently only work on code running in privileged mode. - */ -void core_util_critical_section_enter(void); - -/** Mark the end of a critical section - * - * This function should be called to mark the end of a critical section of code. - * @note - * NOTES: - * 1) The use of this style of critical section is targetted at C based implementations. - * 2) These critical sections can be nested. - * 3) The interrupt enable state on entry to the first critical section (of a nested set, or single - * section) will be preserved on exit from the section. - * 4) This implementation will currently only work on code running in privileged mode. - */ -void core_util_critical_section_exit(void); - -/** - * Determine if we are currently in a critical section - * - * @return true if in a critical section, false otherwise. - */ -bool core_util_in_critical_section(void); - -/**@}*/ - -/**@}*/ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // __MBED_UTIL_CRITICAL_H__ diff --git a/platform/mbed_debug.h b/platform/mbed_debug.h deleted file mode 100644 index ed5e60d..0000000 --- a/platform/mbed_debug.h +++ /dev/null @@ -1,85 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_DEBUG_H -#define MBED_DEBUG_H -#if DEVICE_STDIO_MESSAGES -#include -#include -#endif -#include "platform/mbed_toolchain.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_debug Debug functions - * @{ - */ - -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 - * - * @param format printf-style format string, followed by variables - */ -static inline void debug(const char *format, ...) -{ -#if DEVICE_STDIO_MESSAGES && !defined(NDEBUG) - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); -#endif -} - - -/** Conditionally output a debug message - * - * NOTE: If the condition is constant false (== 0) and the compiler optimization - * level is greater than 0, then the whole function will be compiled away. - * - * @param condition output only if condition is true (!= 0) - * @param format printf-style format string, followed by variables - */ -static inline void debug_if(int condition, const char *format, ...) -{ -#if DEVICE_STDIO_MESSAGES && !defined(NDEBUG) - if (condition) { - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); - } -#endif -} - - -#ifdef __cplusplus -} -#endif - -#endif - -/**@}*/ - -/**@}*/ - diff --git a/platform/mbed_enum_flags.h b/platform/mbed_enum_flags.h deleted file mode 100644 index edeee31..0000000 --- a/platform/mbed_enum_flags.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2020 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 MBED_SCOPED_ENUM_FLAGS_H -#define MBED_SCOPED_ENUM_FLAGS_H - -#include - -#define ENUM_FLAG_BITWISE_OPERATOR(T, OP) \ -inline constexpr T operator OP(T lhs, T rhs) \ -{ \ - return T (static_cast>(lhs) OP \ - static_cast>(rhs)); \ -} - - -#define ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, OP) \ -inline constexpr T &operator OP(T &lhs, T rhs) \ -{ \ - return lhs = lhs OP rhs; \ -} - - -/** - * @brief Applies bitwise operators to a enum class defined elsewhere. - * - * @param T The enum class typename - * - * This macro applies the bitwise negate, AND, OR, XOR operators and the - * corresponding assignment operators to an existing enum class. The macro - * uses underlying type traits to convert back and forth. - * - * Usage: - * @code - * external_enum.h: - * - * enum class SpokenLanguages : uint8_t { - * Sindarin = (1 << 0), - * Westron = (1 << 1), - * Rohirric = (1 << 2), - * BlackSpeech = (1 << 3) - * }; - * - * my_code.cpp: - * - * #include "mbed_enum_flags.h" - * #include "external_enum.h" - * - * MBED_ENUM_FLAG_APPLY_OPERATORS(SpokenLanguages); - * - * SpokenLanguages gandalf = SpokenLanguages::Sindarin | SpokenLanguages::Westron | - * SpokenLanguages::Rohirric | SpokenLanguages::BlackSpeech; - * @endcode - * - */ -#define MBED_ENUM_FLAG_APPLY_OPERATORS(T) \ - inline constexpr T operator ~(T lhs) \ - { \ - return T(~static_cast>(lhs)); \ - } \ - ENUM_FLAG_BITWISE_OPERATOR(T, |) \ - ENUM_FLAG_BITWISE_OPERATOR(T, ^) \ - ENUM_FLAG_BITWISE_OPERATOR(T, &) \ - ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, |=) \ - ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, ^=) \ - ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, &=) \ - static_assert(true, "This assert true is to require a semicolon to terminate the macro.") \ - - -/** @private - * - * @brief Bitwise definition macro with underlying type. - * - * Not part of public API. Do not use directly. Use MBED_SCOPED_ENUM_FLAGS instead. - */ -#define SCOPED_ENUM_FLAGS_TYPED(T, UNDERLYING_T) \ - enum class T : UNDERLYING_T; \ - MBED_ENUM_FLAG_APPLY_OPERATORS(T); \ - enum class T : UNDERLYING_T - -/** @private - * - * @brief Bitwise definition macro with default underlying type. - * - * Not part of public API. Do not use directly. Use MBED_SCOPED_ENUM_FLAGS instead. - */ -#define SCOPED_ENUM_FLAGS_UNTYPED(T) \ - enum class T; \ - MBED_ENUM_FLAG_APPLY_OPERATORS(T); \ - enum class T - -#define MBED_SCOPED_ENUM_FLAGS_CHOOSER(_1, _2, NAME, ...) NAME - -/** - * @brief Creates an enum class with bitwise operator overloads. - * - * @param T The enum class typename - * @param UNDERLYING_T Optional: specify the underlying integral type. If - * omitted, the enum class underlying type will be the - * compiler default. - * - * This macro creates both the enum class type and defines NOT, AND, OR, and - * XOR operators. It also defines as three bitwise assignment operators, AND, - * OR, and XOR. It allows for the scoped nature of the enum class, but adds back - * the bitwise operators that were missing. - * - * This macro uses type traits to convert between the underlying type and back - * again for the bitwise operations. - * - * Usage: - * @code - * my_nice_enum_class_with_flags.h: - * - * MBED_SCOPED_ENUM_FLAGS(MyFlagName) { - * HasEars = (1 << 0), - * HasFur = (1 << 1), - * LaysEggs = (1 << 2), - * Meows = (1 << 3), - * Polydactyl = (1 << 30) - * }; - * - * MBED_SCOPED_ENUM_FLAGS(SpokenLanguages, uint8_t) { - * Sindarin = (1 << 0), - * Westron = (1 << 1), - * Rohirric = (1 << 2), - * BlackSpeech = (1 << 3) - * }; - * - * my_enum_class_flag_consumer.h: - * - * class EnumEater { - * public: - * EnumEater(MyFlagName flags) : _flags(flags) {} - * - * static MyFlagName DefaultFlags = MyFlagName::HasEars | MyFlagName::Meows; - * - * bool is_cat() const { - * return ((_flags & DefaultFlags) == DefaultFlags) && - * ((_flags & MyFlagName::LaysEggs) == MyFlagName()); - * } - * private: - * MyFlagName _flags; - * }; - * - * bool is_Gandalf(SpokenLanguages flags) { - * return flags == (SpokenLanguages::Sindarin | SpokenLanguages::Westron | - * SpokenLanguages::SpeaksRohirric | SpokenLanguages::BlackSpeech); - * } - * @endcode - * - */ -#define MBED_SCOPED_ENUM_FLAGS(...) MBED_SCOPED_ENUM_FLAGS_CHOOSER(__VA_ARGS__, SCOPED_ENUM_FLAGS_TYPED, SCOPED_ENUM_FLAGS_UNTYPED)(__VA_ARGS__) - -#endif //MBED_SCOPED_ENUM_FLAGS_H diff --git a/platform/mbed_error.h b/platform/mbed_error.h deleted file mode 100644 index 5c01bda..0000000 --- a/platform/mbed_error.h +++ /dev/null @@ -1,1183 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_ERROR_H -#define MBED_ERROR_H - -#include -#include "platform/mbed_retarget.h" -#include "platform/mbed_toolchain.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_error Error functions - * @{ - */ - -/** Define this macro to include filenames in error context. For release builds, do not include filename to save memory. - * MBED_PLATFORM_CONF_ERROR_FILENAME_CAPTURE_ENABLED - */ - -/** Define this macro to enable error history - * MBED_PLATFORM_CONF_ERROR_HIST_ENABLED - */ - -#ifndef MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN -#define MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN 16 -#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_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 -#endif - -#define MBED_ERROR_STATUS_CODE_MASK (0x0000FFFF) -#define MBED_ERROR_STATUS_CODE_UNSHIFTED_MASK (0x0000FFFF) -#define MBED_ERROR_STATUS_CODE_POS (0) -#define MBED_ERROR_STATUS_CODE_FIELD_SIZE (16) - -#define MBED_ERROR_STATUS_MODULE_MASK (0x00FF0000) -#define MBED_ERROR_STATUS_MODULE_UNSHIFTED_MASK (0x000000FF) -#define MBED_ERROR_STATUS_MODULE_POS (16) -#define MBED_ERROR_STATUS_MODULE_FIELD_SIZE (8) - -#define MBED_ERROR_STATUS_TYPE_MASK (0x60000000) -#define MBED_ERROR_STATUS_TYPE_UNSHIFTED_MASK (0x00000003) -#define MBED_ERROR_STATUS_TYPE_POS (29) -#define MBED_ERROR_STATUS_TYPE_FIELD_SIZE (2) - -/* mbed_error_status_t Status Encoding */ -//|31(1 bit) Always Negative|30-29(2 bits) |28-24 | 23-16(8 bits) | 15-0(16 bits) | -//|-1 |TYPE |(unused/reserved) | MODULE TYPE | ERROR CODE | - -#define MAKE_MBED_ERROR(type, module, error_code) (mbed_error_status_t) \ - ((0x80000000) | \ - ((mbed_error_status_t) (error_code & MBED_ERROR_STATUS_CODE_UNSHIFTED_MASK) << MBED_ERROR_STATUS_CODE_POS) | \ - ((mbed_error_status_t) (module & MBED_ERROR_STATUS_MODULE_UNSHIFTED_MASK) << MBED_ERROR_STATUS_MODULE_POS) | \ - ((mbed_error_status_t) (type & MBED_ERROR_STATUS_TYPE_UNSHIFTED_MASK) << MBED_ERROR_STATUS_TYPE_POS)) - -#define MBED_GET_ERROR_TYPE( error_status ) ((error_status & MBED_ERROR_STATUS_TYPE_MASK) >> MBED_ERROR_STATUS_TYPE_POS) -#define MBED_GET_ERROR_MODULE( error_status ) ((error_status & MBED_ERROR_STATUS_MODULE_MASK) >> MBED_ERROR_STATUS_MODULE_POS) -#define MBED_GET_ERROR_CODE( error_status ) (int)((MBED_GET_ERROR_TYPE( error_status ) == MBED_ERROR_TYPE_POSIX)?(-error_status):((error_status & MBED_ERROR_STATUS_CODE_MASK) >> MBED_ERROR_STATUS_CODE_POS)) - -/** mbed_error_status_t description - * - * mbed_error_status_t type represents the error status values under MbedOS. mbed_error_status_t values are signed integers and always be negative.\n - * Internally its encoded as below with bit-fields representing error type, module and error code:\n\n - * mbed_error_status_t Status Encoding:\n - * - \verbatim - | 31 Always Negative | 30-29(2 bits) | 28-24 | 23-16(8 bits) | 15-0(16 bits) | - | -1 | TYPE | (unused/reserved) | MODULE TYPE | ERROR CODE | - \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 - * 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 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. - */ -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. - * @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). - * - */ -#define MBED_DEFINE_POSIX_ERROR( error_name, error_code ) \ - MBED_ERROR_CODE_##error_name = error_code, \ - MBED_ERROR_##error_name = -(MBED_POSIX_ERROR_BASE + error_code) - -/** - * Macro for defining a System error status. This macro is used to define System 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 256 and 4096(inclusive). - * - */ -#define MBED_DEFINE_SYSTEM_ERROR( error_name, error_code ) \ - MBED_ERROR_CODE_##error_name = MBED_SYSTEM_ERROR_BASE + error_code, \ - MBED_ERROR_##error_name = MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, MBED_MODULE_UNKNOWN, MBED_ERROR_CODE_##error_name) - -/** - * Macro for defining a Custom error status. This macro is used to define custom 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 4097 and 65535(inclusive). - * - */ -#define MBED_DEFINE_CUSTOM_ERROR( error_name, error_code ) \ - MBED_ERROR_CODE_##error_name = MBED_CUSTOM_ERROR_BASE + error_code, \ - MBED_ERROR_##error_name = MAKE_MBED_ERROR(MBED_ERROR_TYPE_CUSTOM, MBED_MODULE_UNKNOWN, MBED_ERROR_CODE_##error_name) - - -/** - * Macros for setting a system warning. These macros will log the error, Its a wrapper for calling mbed_warning API. - * There are 2 versions of this macro. MBED_WARNING takes status and message. MBED_WARNING1 takes an additional context specific argument - * @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. - * - * @code - * - * MBED_WARNING( ERROR_INVALID_SIZE, "MyDriver: Invalid size in read" ) - * MBED_WARNING1( ERROR_INVALID_SIZE, "MyDriver: Invalid size in read", size_val ) - * - * @endcode - * @note The macro calls mbed_warning API with filename and line number info without caller explicitly passing them. - * Since this macro is a wrapper for mbed_warning API callers should process the return value from this macro which is the return value from calling mbed_error API. - * - */ -#ifdef NDEBUG -#define MBED_WARNING1( error_status, error_msg, error_value ) mbed_warning( error_status, (const char *)NULL, (uint32_t)error_value, NULL, 0 ) -#define MBED_WARNING( error_status, error_msg ) mbed_warning( error_status, (const char *)NULL, (uint32_t)0, NULL, 0 ) -#else //NDEBUG -#if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED -#define MBED_WARNING1( error_status, error_msg, error_value ) mbed_warning( error_status, (const char *)error_msg, (uint32_t)error_value, (const char *)MBED_FILENAME, __LINE__ ) -#define MBED_WARNING( error_status, error_msg ) mbed_warning( error_status, (const char *)error_msg, (uint32_t)0 , (const char *)MBED_FILENAME, __LINE__ ) -#else //MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED -#define MBED_WARNING1( error_status, error_msg, error_value ) mbed_warning( error_status, (const char *)error_msg, (uint32_t)error_value, NULL, 0 ) -#define MBED_WARNING( error_status, error_msg ) mbed_warning( error_status, (const char *)error_msg, (uint32_t)0, NULL, 0 ) -#endif -#endif - -/** - * Macros for setting a fatal system error. These macros will log the error, prints the error report and halts the system. Its a wrapper for calling mbed_error API. - * There are 2 versions of this macro. MBED_ERROR takes status and message. MBED_ERROR1 takes an additional context specific argument - * @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 Does not return - * - * @code - * - * MBED_ERROR( MBED_ERROR_MUTEX_LOCK_FAILED, "MyDriver: Can't lock driver Mutex" ) - * MBED_ERROR1( MBED_ERROR_MUTEX_LOCK_FAILED, "MyDriver: Can't lock driver Mutex", &my_mutex ) - * - * @endcode - * @note The macro calls mbed_error API with filename and line number info without caller explicitly passing them. - * Since this macro is a wrapper for mbed_error API callers should process the return value from this macro which is the return value from calling mbed_error API. - * - */ -#ifdef NDEBUG -#define MBED_ERROR1( error_status, error_msg, error_value ) mbed_error( error_status, (const char *)NULL, (uint32_t)error_value, NULL, 0 ) -#define MBED_ERROR( error_status, error_msg ) mbed_error( error_status, (const char *)NULL, (uint32_t)0 , NULL, 0 ) -#else //NDEBUG -#if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED -#define MBED_ERROR1( error_status, error_msg, error_value ) mbed_error( error_status, (const char *)error_msg, (uint32_t)error_value, (const char *)MBED_FILENAME, __LINE__ ) -#define MBED_ERROR( error_status, error_msg ) mbed_error( error_status, (const char *)error_msg, (uint32_t)0 , (const char *)MBED_FILENAME, __LINE__ ) -#else //MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED -#define MBED_ERROR1( error_status, error_msg, error_value ) mbed_error( error_status, (const char *)error_msg, (uint32_t)error_value, NULL, 0 ) -#define MBED_ERROR( error_status, error_msg ) mbed_error( error_status, (const char *)error_msg, (uint32_t)0 , NULL, 0 ) -#endif -#endif - -//Error Type definition -/** mbed_error_type_t definition - * @note - * This enumeration defines the Error types supported. The value of these enum values will be encoded into mbed_error_status_t TYPE field.\n - * 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 - * - */ -typedef enum _mbed_error_type_t { - MBED_ERROR_TYPE_SYSTEM = 0, - MBED_ERROR_TYPE_CUSTOM = 1, - //2 is reserved - //Use 3 for POSIX because we are mapping -1 to -255 to POSIX error codes - //and thus we must use 3 to match the type bits in error status representation which are from 0xFFFFFFFF to 0xFFFFFF00 - MBED_ERROR_TYPE_POSIX = 3 -} mbed_error_type_t; - -//Module type/id definitions -/** mbed_module_type_t definition - * @note - * This enumeration defines the module types. The value of these enum values will be encoded into mbed_error_status_t MODULE field.\n\n - * See mbed_error_status_t description for more info.\n - * MBED_MODULE_UNKNOWN - This module type can be used if caller of the mbed_error/mbed_warning doesn't know who is the actual originator of the error.\n - * Other module values can be used to provide more info on who/where the error originated from.\n\n - * For example, if I2C driver is the component originating the error you can use MBED_MODULE_DRIVER_I2C to provide more info.\n - * Its used in call to MBED_MAKE_ERROR/MBED_MAKE_SYSTEM_ERROR/MBED_MAKE_CUSTOM_ERROR macros.\n - * - * @code - * Example: mbed_error_status_t i2c_driver_error = MBED_MAKE_ERROR( MBED_MODULE_DRIVER_I2C, MBED_ERROR_CONFIG_UNSUPPORTED ); - * @endcode - * - * @note - * \n Below are the module code mappings:\n - \verbatim - 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_NETWORK_STATS 24 Network Statistics - - MBED_MODULE_UNKNOWN 255 Unknown module - \endverbatim - * - */ -typedef enum _mbed_module_type { - MBED_MODULE_APPLICATION = 0, - MBED_MODULE_PLATFORM, - MBED_MODULE_KERNEL, - MBED_MODULE_NETWORK_STACK, - MBED_MODULE_HAL, - MBED_MODULE_MEMORY_SUBSYSTEM, - MBED_MODULE_FILESYSTEM, - MBED_MODULE_BLOCK_DEVICE, - MBED_MODULE_DRIVER, - MBED_MODULE_DRIVER_SERIAL, - MBED_MODULE_DRIVER_RTC, - MBED_MODULE_DRIVER_I2C, - MBED_MODULE_DRIVER_SPI, - MBED_MODULE_DRIVER_GPIO, - MBED_MODULE_DRIVER_ANALOG, - MBED_MODULE_DRIVER_DIGITAL, - MBED_MODULE_DRIVER_CAN, - MBED_MODULE_DRIVER_ETHERNET, - MBED_MODULE_DRIVER_CRC, - MBED_MODULE_DRIVER_PWM, - MBED_MODULE_DRIVER_QSPI, - MBED_MODULE_DRIVER_USB, - MBED_MODULE_DRIVER_WATCHDOG, - MBED_MODULE_TARGET_SDK, - MBED_MODULE_BLE, - MBED_MODULE_NETWORK_STATS, - /* Add More entities here as required */ - - MBED_MODULE_UNKNOWN = 255, - MBED_MODULE_MAX = MBED_MODULE_UNKNOWN -} mbed_module_type_t; - -//Use MBED_SUCCESS(=0) or any positive number for successful returns -#define MBED_SUCCESS 0 - -#define MBED_POSIX_ERROR_BASE 0 -#define MBED_SYSTEM_ERROR_BASE 256 -#define MBED_CUSTOM_ERROR_BASE 4096 - -//Error Code definitions -/** 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 - * - * @note - * 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 - * 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 POSIX error codes and the description:\n - * \verbatim - EPERM 1 Operation not permitted - ENOENT 2 No such file or directory - ESRCH 3 No such process - EINTR 4 Interrupted system call - EIO 5 I/O error - ENXIO 6 No such device or address - E2BIG 7 Argument list too long - ENOEXEC 8 Exec format error - EBADF 9 Bad file number - ECHILD 10 No child processes - EAGAIN 11 Try again - ENOMEM 12 Out of memory - EACCES 13 Permission denied - EFAULT 14 Bad address - ENOTBLK 15 Block device required - EBUSY 16 Device or resource busy - EEXIST 17 File exists - EXDEV 18 Cross-device link - ENODEV 19 No such device - ENOTDIR 20 Not a directory - EISDIR 21 Is a directory - EINVAL 22 Invalid argument - ENFILE 23 File table overflow - EMFILE 24 Too many open files - ENOTTY 25 Not a typewriter - ETXTBSY 26 Text file busy - EFBIG 27 File too large - ENOSPC 28 No space left on device - ESPIPE 29 Illegal seek - EROFS 30 Read-only file system - EMLINK 31 Too many links - EPIPE 32 Broken pipe - EDOM 33 Math argument out of domain of func - ERANGE 34 Math result not representable - EDEADLK 35 Resource deadlock would occur - ENAMETOOLONG 36 File name too long - ENOLCK 37 No record locks available - ENOSYS 38 Function not implemented - ENOTEMPTY 39 Directory not empty - ELOOP 40 Too many symbolic links encountered - EWOULDBLOCK EAGAIN Operation would block - ENOMSG 42 No message of desired type - EIDRM 43 Identifier removed - ECHRNG 44 Channel number out of range - EL2NSYNC 45 Level 2 not synchronized - EL3HLT 46 Level 3 halted - EL3RST 47 Level 3 reset - ELNRNG 48 Link number out of range - EUNATCH 49 Protocol driver not attached - ENOCSI 50 No CSI structure available - EL2HLT 51 Level 2 halted - EBADE 52 Invalid exchange - EBADR 53 Invalid request descriptor - EXFULL 54 Exchange full - ENOANO 55 No anode - EBADRQC 56 Invalid request code - EBADSLT 57 Invalid slot - EDEADLOCK EDEADLK Resource deadlock would occur - EBFONT 59 Bad font file format - ENOSTR 60 Device not a stream - ENODATA 61 No data available - ETIME 62 Timer expired - ENOSR 63 Out of streams resources - ENONET 64 Machine is not on the network - ENOPKG 65 Package not installed - EREMOTE 66 Object is remote - ENOLINK 67 Link has been severed - EADV 68 Advertise error - ESRMNT 69 Srmount error - ECOMM 70 Communication error on send - EPROTO 71 Protocol error - EMULTIHOP 72 Multihop attempted - EDOTDOT 73 RFS specific error - EBADMSG 74 Not a data message - EOVERFLOW 75 Value too large for defined data type - ENOTUNIQ 76 Name not unique on network - EBADFD 77 File descriptor in bad state - EREMCHG 78 Remote address changed - ELIBACC 79 Can not access a needed shared library - ELIBBAD 80 Accessing a corrupted shared library - ELIBSCN 81 .lib section in a.out corrupted - ELIBMAX 82 Attempting to link in too many shared libraries - ELIBEXEC 83 Cannot exec a shared library directly - EILSEQ 84 Illegal byte sequence - ERESTART 85 Interrupted system call should be restarted - ESTRPIPE 86 Streams pipe error - EUSERS 87 Too many users - ENOTSOCK 88 Socket operation on non-socket - EDESTADDRREQ 89 Destination address required - EMSGSIZE 90 Message too long - EPROTOTYPE 91 Protocol wrong type for socket - ENOPROTOOPT 92 Protocol not available - EPROTONOSUPPORT 93 Protocol not supported - ESOCKTNOSUPPORT 94 Socket type not supported - EOPNOTSUPP 95 Operation not supported on transport endpoint - EPFNOSUPPORT 96 Protocol family not supported - EAFNOSUPPORT 97 Address family not supported by protocol - EADDRINUSE 98 Address already in use - EADDRNOTAVAIL 99 Cannot assign requested address - ENETDOWN 100 Network is down - ENETUNREACH 101 Network is unreachable - ENETRESET 102 Network dropped connection because of reset - ECONNABORTED 103 Software caused connection abort - ECONNRESET 104 Connection reset by peer - ENOBUFS 105 No buffer space available - EISCONN 106 Transport endpoint is already connected - ENOTCONN 107 Transport endpoint is not connected - ESHUTDOWN 108 Cannot send after transport endpoint shutdown - ETOOMANYREFS 109 Too many references: cannot splice - ETIMEDOUT 110 Connection timed out - ECONNREFUSED 111 Connection refused - EHOSTDOWN 112 Host is down - EHOSTUNREACH 113 No route to host - EALREADY 114 Operation already in progress - EINPROGRESS 115 Operation now in progress - ESTALE 116 Stale NFS file handle - EUCLEAN 117 Structure needs cleaning - ENOTNAM 118 Not a XENIX named type file - ENAVAIL 119 No XENIX semaphores available - EISNAM 120 Is a named type file - EREMOTEIO 121 Remote I/O error - EDQUOT 122 Quota exceeded - ENOMEDIUM 123 No medium found - EMEDIUMTYPE 124 Wrong medium type - ECANCELED 125 Operation Canceled - ENOKEY 126 Required key not available - EKEYEXPIRED 127 Key has expired - EKEYREVOKED 128 Key has been revoked - EKEYREJECTED 129 Key was rejected by service - EOWNERDEAD 130 Owner died - ENOTRECOVERABLE 131 State not recoverable - \endverbatim - * - * @note - * MbedOS System Error codes are defined using the macro MBED_DEFINE_SYSTEM_ERROR\n - * For example MBED_DEFINE_SYSTEM_ERROR( INVALID_ARGUMENT ,1 ) macro defines the following values:\n - * ERROR_CODE_INVALID_ARGUMENT = MBED_SYSTEM_ERROR_BASE+1\n - * ERROR_INVALID_ARGUMENT = MAKE_MBED_ERROR(ERROR_TYPE_SYSTEM, MBED_MODULE_UNKNOWN, ERROR_CODE_INVALID_ARGUMENT)\n - * Its effectively equivalent to:\n - * ERROR_CODE_INVALID_ARGUMENT = 1\n - * ERROR_INVALID_ARGUMENT = 0x80FF0001\n (Note that MODULE field is set to MBED_MODULE_UNKNOWN) - * New System Error codes should be defined using MBED_DEFINE_SYSTEM_ERROR macro and must have an unique error code value\n - * passed as the second argument in the MBED_DEFINE_SYSTEM_ERROR macro.\n\n - * Below are the Mbed System error codes and the description: - * \verbatim - UNKNOWN 256 Unknown error - INVALID_ARGUMENT 257 Invalid Argument - INVALID_DATA 258 Invalid data - INVALID_FORMAT 259 Invalid format - INVALID_INDEX 260 Invalid Index - INVALID_SIZE 261 Invalid Size - INVALID_OPERATION 262 Invalid Operation - NOT_FOUND 263 Not Found - ACCESS_DENIED 264 Access Denied - NOT_SUPPORTED 265 Not supported - BUFFER_FULL 266 Buffer Full - MEDIA_FULL 267 Media/Disk Full - ALREADY_IN_USE 268 Already in use - TIMEOUT 269 Timeout error - NOT_READY 270 Not Ready - FAILED_OPERATION 271 Requested Operation failed - OPERATION_PROHIBITED 272 Operation prohibited - OPERATION_ABORTED 273 Operation failed - WRITE_PROTECTED 274 Attempt to write to write-protected resource - NO_RESPONSE 275 No response - SEMAPHORE_LOCK_FAILED 276 Semaphore lock failed - MUTEX_LOCK_FAILED 277 Mutex lock 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 - CLOSE_FAILED 282 Close failed - READ_FAILED 283 Read failed - WRITE_FAILED 284 Write failed - INITIALIZATION_FAILED 285 Initialization failed - BOOT_FAILURE 286 Boot failure - OUT_OF_MEMORY 287 Out of memory - OUT_OF_RESOURCES 288 Out of resources - ALLOC_FAILED 289 Alloc failed - FREE_FAILED 290 Free failed - OVERFLOW 291 Overflow error - UNDERFLOW 292 Underflow error - STACK_OVERFLOW 293 Stack overflow error - ISR_QUEUE_OVERFLOW 294 ISR queue overflow - TIMER_QUEUE_OVERFLOW 295 Timer Queue overflow - CLIB_SPACE_UNAVAILABLE 296 Standard library error - Space unavailable - CLIB_EXCEPTION 297 Standard library error - Exception - CLIB_MUTEX_INIT_FAILURE 298 Standard library error - Mutex Init failure - CREATE_FAILED 299 Create failed - DELETE_FAILED 300 Delete failed - THREAD_CREATE_FAILED 301 Thread Create failed - THREAD_DELETE_FAILED 302 Thread Delete failed - PROHIBITED_IN_ISR_CONTEXT 303 Operation Prohibited in ISR context - PINMAP_INVALID 304 Pinmap Invalid - RTOS_EVENT 305 Unknown Rtos Error - RTOS_THREAD_EVENT 306 Rtos Thread Error - RTOS_MUTEX_EVENT 307 Rtos Mutex Error - RTOS_SEMAPHORE_EVENT 308 Rtos Semaphore Error - RTOS_MEMORY_POOL_EVENT 309 Rtos Memory Pool Error - RTOS_TIMER_EVENT 310 Rtos Timer Error - RTOS_EVENT_FLAGS_EVENT 311 Rtos Event flags Error - RTOS_MESSAGE_QUEUE_EVENT 312 Rtos Message queue Error - DEVICE_BUSY 313 Device Busy - CONFIG_UNSUPPORTED 314 Configuration not supported - CONFIG_MISMATCH 315 Configuration mismatch - 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 - ASSERTION_FAILED 324 Assertion Failed - AUTHENTICATION_FAILED 325 Authentication Failed - RBP_AUTHENTICATION_FAILED 326 Rollback Protect Authentication Failed - \endverbatim - * - * @note - * Custom Error codes can be defined using the macro DEFINE_CUSTOM_ERROR\n - * This is mainly meant to capture non-generic error codes specific to a device. - * For example DEFINE_CUSTOM_ERROR( MY_CUSTOM_ERROR ,1 ) macro defines the following values:\n - * ERROR_CODE_MY_CUSTOM_ERROR = MBED_CUSTOM_ERROR_BASE+1\n - * ERROR_MY_CUSTOM_ERROR = MAKE_MBED_ERROR(ERROR_TYPE_CUSTOM, MBED_MODULE_UNKNOWN, ERROR_CODE_MY_CUSTOM_ERROR)\n - * Its effectively equivalent to:\n - * ERROR_CODE_MY_CUSTOM_ERROR = 4097\n - * ERROR_MY_CUSTOM_ERROR = 0xA0FF1001\n (Note that MODULE field is set to MBED_MODULE_UNKNOWN) \n\n - * - * @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 - * 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. - * - * 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 - * much more efficient. - * - * @note - * **Searching for error codes in mbed-os source tree:** \n - * If you get an error report as below which you want to search for in mbed-os source tree, first take note of "Error Code" number. \n - * For example, the below error report has an error code of \b 259. Find the error name associated with the error code and in this case its \b INVALID_FORMAT. \n - * Use that error name(\b INVALID_FORMAT) to search the source tree for code locations setting that specific error code. \n - * If the Error module reported is not 255(which indicates unknown module), you can also use that to narrow down to the specific component reporting the error. - * See mbed_module_type_t enum above for module mapping. \n - * - * \verbatim - ++ MbedOS Error Info ++ - 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 - //defintions in mbed_retarget.h - // Error Name Error Code - MBED_DEFINE_POSIX_ERROR(EPERM, EPERM), /* 1 Operation not permitted */ - MBED_DEFINE_POSIX_ERROR(ENOENT, ENOENT), /* 2 No such file or directory */ - MBED_DEFINE_POSIX_ERROR(ESRCH, ESRCH), /* 3 No such process */ - MBED_DEFINE_POSIX_ERROR(EINTR, EINTR), /* 4 Interrupted system call */ - MBED_DEFINE_POSIX_ERROR(EIO, EIO), /* 5 I/O error */ - MBED_DEFINE_POSIX_ERROR(ENXIO, ENXIO), /* 6 No such device or address */ - MBED_DEFINE_POSIX_ERROR(E2BIG, E2BIG), /* 7 Argument list too long */ - MBED_DEFINE_POSIX_ERROR(ENOEXEC, ENOEXEC), /* 8 Exec format error */ - MBED_DEFINE_POSIX_ERROR(EBADF, EBADF), /* 9 Bad file number */ - MBED_DEFINE_POSIX_ERROR(ECHILD, ECHILD), /* 10 No child processes */ - MBED_DEFINE_POSIX_ERROR(EAGAIN, EAGAIN), /* 11 Try again */ - MBED_DEFINE_POSIX_ERROR(ENOMEM, ENOMEM), /* 12 Out of memory */ - MBED_DEFINE_POSIX_ERROR(EACCES, EACCES), /* 13 Permission denied */ - MBED_DEFINE_POSIX_ERROR(EFAULT, EFAULT), /* 14 Bad address */ - MBED_DEFINE_POSIX_ERROR(ENOTBLK, ENOTBLK), /* 15 Block device required */ - MBED_DEFINE_POSIX_ERROR(EBUSY, EBUSY), /* 16 Device or resource busy */ - MBED_DEFINE_POSIX_ERROR(EEXIST, EEXIST), /* 17 File exists */ - MBED_DEFINE_POSIX_ERROR(EXDEV, EXDEV), /* 18 Cross-device link */ - MBED_DEFINE_POSIX_ERROR(ENODEV, ENODEV), /* 19 No such device */ - MBED_DEFINE_POSIX_ERROR(ENOTDIR, ENOTDIR), /* 20 Not a directory */ - MBED_DEFINE_POSIX_ERROR(EISDIR, EISDIR), /* 21 Is a directory */ - MBED_DEFINE_POSIX_ERROR(EINVAL, EINVAL), /* 22 Invalid argument */ - MBED_DEFINE_POSIX_ERROR(ENFILE, ENFILE), /* 23 File table overflow */ - MBED_DEFINE_POSIX_ERROR(EMFILE, EMFILE), /* 24 Too many open files */ - MBED_DEFINE_POSIX_ERROR(ENOTTY, ENOTTY), /* 25 Not a typewriter */ - MBED_DEFINE_POSIX_ERROR(ETXTBSY, ETXTBSY), /* 26 Text file busy */ - MBED_DEFINE_POSIX_ERROR(EFBIG, EFBIG), /* 27 File too large */ - MBED_DEFINE_POSIX_ERROR(ENOSPC, ENOSPC), /* 28 No space left on device */ - MBED_DEFINE_POSIX_ERROR(ESPIPE, ESPIPE), /* 29 Illegal seek */ - MBED_DEFINE_POSIX_ERROR(EROFS, EROFS), /* 30 Read-only file system */ - MBED_DEFINE_POSIX_ERROR(EMLINK, EMLINK), /* 31 Too many links */ - MBED_DEFINE_POSIX_ERROR(EPIPE, EPIPE), /* 32 Broken pipe */ - MBED_DEFINE_POSIX_ERROR(EDOM, EDOM), /* 33 Math argument out of domain of func */ - MBED_DEFINE_POSIX_ERROR(ERANGE, ERANGE), /* 34 Math result not representable */ - MBED_DEFINE_POSIX_ERROR(EDEADLK, EDEADLK), /* 35 Resource deadlock would occur */ - MBED_DEFINE_POSIX_ERROR(ENAMETOOLONG, ENAMETOOLONG), /* 36 File name too long */ - MBED_DEFINE_POSIX_ERROR(ENOLCK, ENOLCK), /* 37 No record locks available */ - MBED_DEFINE_POSIX_ERROR(ENOSYS, ENOSYS), /* 38 Function not implemented */ - MBED_DEFINE_POSIX_ERROR(ENOTEMPTY, ENOTEMPTY), /* 39 Directory not empty */ - MBED_DEFINE_POSIX_ERROR(ELOOP, ELOOP), /* 40 Too many symbolic links encountered */ - MBED_DEFINE_POSIX_ERROR(EWOULDBLOCK, EAGAIN), /* EAGAIN Operation would block */ - MBED_DEFINE_POSIX_ERROR(ENOMSG, ENOMSG), /* 42 No message of desired type */ - MBED_DEFINE_POSIX_ERROR(EIDRM, EIDRM), /* 43 Identifier removed */ - MBED_DEFINE_POSIX_ERROR(ECHRNG, ECHRNG), /* 44 Channel number out of range */ - MBED_DEFINE_POSIX_ERROR(EL2NSYNC, EL2NSYNC), /* 45 Level 2 not synchronized */ - MBED_DEFINE_POSIX_ERROR(EL3HLT, EL3HLT), /* 46 Level 3 halted */ - MBED_DEFINE_POSIX_ERROR(EL3RST, EL3RST), /* 47 Level 3 reset */ - MBED_DEFINE_POSIX_ERROR(ELNRNG, ELNRNG), /* 48 Link number out of range */ - MBED_DEFINE_POSIX_ERROR(EUNATCH, EUNATCH), /* 49 Protocol driver not attached */ - MBED_DEFINE_POSIX_ERROR(ENOCSI, ENOCSI), /* 50 No CSI structure available */ - MBED_DEFINE_POSIX_ERROR(EL2HLT, EL2HLT), /* 51 Level 2 halted */ - MBED_DEFINE_POSIX_ERROR(EBADE, EBADE), /* 52 Invalid exchange */ - MBED_DEFINE_POSIX_ERROR(EBADR, EBADR), /* 53 Invalid request descriptor */ - MBED_DEFINE_POSIX_ERROR(EXFULL, EXFULL), /* 54 Exchange full */ - MBED_DEFINE_POSIX_ERROR(ENOANO, ENOANO), /* 55 No anode */ - MBED_DEFINE_POSIX_ERROR(EBADRQC, EBADRQC), /* 56 Invalid request code */ - MBED_DEFINE_POSIX_ERROR(EBADSLT, EBADSLT), /* 57 Invalid slot */ - MBED_DEFINE_POSIX_ERROR(EDEADLOCK, EDEADLK), /* EDEADLK Resource deadlock would occur */ - MBED_DEFINE_POSIX_ERROR(EBFONT, EBFONT), /* 59 Bad font file format */ - MBED_DEFINE_POSIX_ERROR(ENOSTR, ENOSTR), /* 60 Device not a stream */ - MBED_DEFINE_POSIX_ERROR(ENODATA, ENODATA), /* 61 No data available */ - MBED_DEFINE_POSIX_ERROR(ETIME, ETIME), /* 62 Timer expired */ - MBED_DEFINE_POSIX_ERROR(ENOSR, ENOSR), /* 63 Out of streams resources */ - MBED_DEFINE_POSIX_ERROR(ENONET, ENONET), /* 64 Machine is not on the network */ - MBED_DEFINE_POSIX_ERROR(ENOPKG, ENOPKG), /* 65 Package not installed */ - MBED_DEFINE_POSIX_ERROR(EREMOTE, EREMOTE), /* 66 Object is remote */ - MBED_DEFINE_POSIX_ERROR(ENOLINK, ENOLINK), /* 67 Link has been severed */ - MBED_DEFINE_POSIX_ERROR(EADV, EADV), /* 68 Advertise error */ - MBED_DEFINE_POSIX_ERROR(ESRMNT, ESRMNT), /* 69 Srmount error */ - MBED_DEFINE_POSIX_ERROR(ECOMM, ECOMM), /* 70 Communication error on send */ - MBED_DEFINE_POSIX_ERROR(EPROTO, EPROTO), /* 71 Protocol error */ - MBED_DEFINE_POSIX_ERROR(EMULTIHOP, EMULTIHOP), /* 72 Multihop attempted */ - MBED_DEFINE_POSIX_ERROR(EDOTDOT, EDOTDOT), /* 73 RFS specific error */ - MBED_DEFINE_POSIX_ERROR(EBADMSG, EBADMSG), /* 74 Not a data message */ - MBED_DEFINE_POSIX_ERROR(EOVERFLOW, EOVERFLOW), /* 75 Value too large for defined data type */ - MBED_DEFINE_POSIX_ERROR(ENOTUNIQ, ENOTUNIQ), /* 76 Name not unique on network */ - MBED_DEFINE_POSIX_ERROR(EBADFD, EBADFD), /* 77 File descriptor in bad state */ - MBED_DEFINE_POSIX_ERROR(EREMCHG, EREMCHG), /* 78 Remote address changed */ - MBED_DEFINE_POSIX_ERROR(ELIBACC, ELIBACC), /* 79 Can not access a needed shared library */ - MBED_DEFINE_POSIX_ERROR(ELIBBAD, ELIBBAD), /* 80 Accessing a corrupted shared library */ - MBED_DEFINE_POSIX_ERROR(ELIBSCN, ELIBSCN), /* 81 .lib section in a.out corrupted */ - MBED_DEFINE_POSIX_ERROR(ELIBMAX, ELIBMAX), /* 82 Attempting to link in too many shared libraries */ - MBED_DEFINE_POSIX_ERROR(ELIBEXEC, ELIBEXEC), /* 83 Cannot exec a shared library directly */ - MBED_DEFINE_POSIX_ERROR(EILSEQ, EILSEQ), /* 84 Illegal byte sequence */ - MBED_DEFINE_POSIX_ERROR(ERESTART, ERESTART), /* 85 Interrupted system call should be restarted */ - MBED_DEFINE_POSIX_ERROR(ESTRPIPE, ESTRPIPE), /* 86 Streams pipe error */ - MBED_DEFINE_POSIX_ERROR(EUSERS, EUSERS), /* 87 Too many users */ - MBED_DEFINE_POSIX_ERROR(ENOTSOCK, ENOTSOCK), /* 88 Socket operation on non-socket */ - MBED_DEFINE_POSIX_ERROR(EDESTADDRREQ, EDESTADDRREQ), /* 89 Destination address required */ - MBED_DEFINE_POSIX_ERROR(EMSGSIZE, EMSGSIZE), /* 90 Message too long */ - MBED_DEFINE_POSIX_ERROR(EPROTOTYPE, EPROTOTYPE), /* 91 Protocol wrong type for socket */ - MBED_DEFINE_POSIX_ERROR(ENOPROTOOPT, ENOPROTOOPT), /* 92 Protocol not available */ - MBED_DEFINE_POSIX_ERROR(EPROTONOSUPPORT, EPROTONOSUPPORT), /* 93 Protocol not supported */ - MBED_DEFINE_POSIX_ERROR(ESOCKTNOSUPPORT, ESOCKTNOSUPPORT), /* 94 Socket type not supported */ - MBED_DEFINE_POSIX_ERROR(EOPNOTSUPP, EOPNOTSUPP), /* 95 Operation not supported on transport endpoint */ - MBED_DEFINE_POSIX_ERROR(EPFNOSUPPORT, EPFNOSUPPORT), /* 96 Protocol family not supported */ - MBED_DEFINE_POSIX_ERROR(EAFNOSUPPORT, EAFNOSUPPORT), /* 97 Address family not supported by protocol */ - MBED_DEFINE_POSIX_ERROR(EADDRINUSE, EADDRINUSE), /* 98 Address already in use */ - MBED_DEFINE_POSIX_ERROR(EADDRNOTAVAIL, EADDRNOTAVAIL), /* 99 Cannot assign requested address */ - MBED_DEFINE_POSIX_ERROR(ENETDOWN, ENETDOWN), /* 100 Network is down */ - MBED_DEFINE_POSIX_ERROR(ENETUNREACH, ENETUNREACH), /* 101 Network is unreachable */ - MBED_DEFINE_POSIX_ERROR(ENETRESET, ENETRESET), /* 102 Network dropped connection because of reset */ - MBED_DEFINE_POSIX_ERROR(ECONNABORTED, ECONNABORTED), /* 103 Software caused connection abort */ - MBED_DEFINE_POSIX_ERROR(ECONNRESET, ECONNRESET), /* 104 Connection reset by peer */ - MBED_DEFINE_POSIX_ERROR(ENOBUFS, ENOBUFS), /* 105 No buffer space available */ - MBED_DEFINE_POSIX_ERROR(EISCONN, EISCONN), /* 106 Transport endpoint is already connected */ - MBED_DEFINE_POSIX_ERROR(ENOTCONN, ENOTCONN), /* 107 Transport endpoint is not connected */ - MBED_DEFINE_POSIX_ERROR(ESHUTDOWN, ESHUTDOWN), /* 108 Cannot send after transport endpoint shutdown */ - MBED_DEFINE_POSIX_ERROR(ETOOMANYREFS, ETOOMANYREFS), /* 109 Too many references: cannot splice */ - MBED_DEFINE_POSIX_ERROR(ETIMEDOUT, ETIMEDOUT), /* 110 Connection timed out */ - MBED_DEFINE_POSIX_ERROR(ECONNREFUSED, ECONNREFUSED), /* 111 Connection refused */ - MBED_DEFINE_POSIX_ERROR(EHOSTDOWN, EHOSTDOWN), /* 112 Host is down */ - MBED_DEFINE_POSIX_ERROR(EHOSTUNREACH, EHOSTUNREACH), /* 113 No route to host */ - MBED_DEFINE_POSIX_ERROR(EALREADY, EALREADY), /* 114 Operation already in progress */ - MBED_DEFINE_POSIX_ERROR(EINPROGRESS, EINPROGRESS), /* 115 Operation now in progress */ - MBED_DEFINE_POSIX_ERROR(ESTALE, ESTALE), /* 116 Stale NFS file handle */ - MBED_DEFINE_POSIX_ERROR(EUCLEAN, EUCLEAN), /* 117 Structure needs cleaning */ - MBED_DEFINE_POSIX_ERROR(ENOTNAM, ENOTNAM), /* 118 Not a XENIX named type file */ - MBED_DEFINE_POSIX_ERROR(ENAVAIL, ENAVAIL), /* 119 No XENIX semaphores available */ - MBED_DEFINE_POSIX_ERROR(EISNAM, EISNAM), /* 120 Is a named type file */ - MBED_DEFINE_POSIX_ERROR(EREMOTEIO, EREMOTEIO), /* 121 Remote I/O error */ - MBED_DEFINE_POSIX_ERROR(EDQUOT, EDQUOT), /* 122 Quota exceeded */ - MBED_DEFINE_POSIX_ERROR(ENOMEDIUM, ENOMEDIUM), /* 123 No medium found */ - MBED_DEFINE_POSIX_ERROR(EMEDIUMTYPE, EMEDIUMTYPE), /* 124 Wrong medium type */ - MBED_DEFINE_POSIX_ERROR(ECANCELED, ECANCELED), /* 125 Operation Canceled */ - MBED_DEFINE_POSIX_ERROR(ENOKEY, ENOKEY), /* 126 Required key not available */ - MBED_DEFINE_POSIX_ERROR(EKEYEXPIRED, EKEYEXPIRED), /* 127 Key has expired */ - MBED_DEFINE_POSIX_ERROR(EKEYREVOKED, EKEYREVOKED), /* 128 Key has been revoked */ - MBED_DEFINE_POSIX_ERROR(EKEYREJECTED, EKEYREJECTED), /* 129 Key was rejected by service */ - MBED_DEFINE_POSIX_ERROR(EOWNERDEAD, EOWNERDEAD), /* 130 Owner died */ - MBED_DEFINE_POSIX_ERROR(ENOTRECOVERABLE, ENOTRECOVERABLE), /* 131 State not recoverable */ - - //Below are MBED SYSTEM ERROR CODE definitions - //MBED SYSTEM ERROR CODE definitions starts at offset MBED_SYSTEM_ERROR_BASE, see above. - // Error Name Error Offset Error Code - MBED_DEFINE_SYSTEM_ERROR(UNKNOWN, 0), /* 256 Unknown error */ - MBED_DEFINE_SYSTEM_ERROR(INVALID_ARGUMENT, 1), /* 257 Invalid Argument */ - 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 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 */ - MBED_DEFINE_SYSTEM_ERROR(UNSUPPORTED, 9), /* 265 Unsupported */ - MBED_DEFINE_SYSTEM_ERROR(BUFFER_FULL, 10), /* 266 Buffer Full */ - MBED_DEFINE_SYSTEM_ERROR(MEDIA_FULL, 11), /* 267 Media/Disk Full */ - MBED_DEFINE_SYSTEM_ERROR(ALREADY_IN_USE, 12), /* 268 Already in use */ - MBED_DEFINE_SYSTEM_ERROR(TIME_OUT, 13), /* 269 Timeout error */ - MBED_DEFINE_SYSTEM_ERROR(NOT_READY, 14), /* 270 Not Ready */ - MBED_DEFINE_SYSTEM_ERROR(FAILED_OPERATION, 15), /* 271 Requested Operation failed */ - MBED_DEFINE_SYSTEM_ERROR(OPERATION_PROHIBITED, 16), /* 272 Operation prohibited */ - 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 Semaphore lock failed */ - MBED_DEFINE_SYSTEM_ERROR(MUTEX_LOCK_FAILED, 21), /* 277 Mutex lock 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 */ - MBED_DEFINE_SYSTEM_ERROR(CLOSE_FAILED, 26), /* 282 Close failed */ - MBED_DEFINE_SYSTEM_ERROR(READ_FAILED, 27), /* 283 Read failed */ - MBED_DEFINE_SYSTEM_ERROR(WRITE_FAILED, 28), /* 284 Write failed */ - MBED_DEFINE_SYSTEM_ERROR(INITIALIZATION_FAILED, 29), /* 285 Initialization failed */ - MBED_DEFINE_SYSTEM_ERROR(BOOT_FAILURE, 30), /* 286 Boot failure */ - MBED_DEFINE_SYSTEM_ERROR(OUT_OF_MEMORY, 31), /* 287 Out of memory */ - MBED_DEFINE_SYSTEM_ERROR(OUT_OF_RESOURCES, 32), /* 288 Out of resources */ - MBED_DEFINE_SYSTEM_ERROR(ALLOC_FAILED, 33), /* 289 Alloc failed */ - MBED_DEFINE_SYSTEM_ERROR(FREE_FAILED, 34), /* 290 Free failed */ - MBED_DEFINE_SYSTEM_ERROR(OVERFLOW, 35), /* 291 Overflow error */ - MBED_DEFINE_SYSTEM_ERROR(UNDERFLOW, 36), /* 292 Underflow error */ - MBED_DEFINE_SYSTEM_ERROR(STACK_OVERFLOW, 37), /* 293 Stack overflow error */ - MBED_DEFINE_SYSTEM_ERROR(ISR_QUEUE_OVERFLOW, 38), /* 294 ISR queue overflow */ - MBED_DEFINE_SYSTEM_ERROR(TIMER_QUEUE_OVERFLOW, 39), /* 295 Timer Queue overflow */ - MBED_DEFINE_SYSTEM_ERROR(CLIB_SPACE_UNAVAILABLE, 40), /* 296 Standard library error - Space unavailable */ - MBED_DEFINE_SYSTEM_ERROR(CLIB_EXCEPTION, 41), /* 297 Standard library error - Exception */ - MBED_DEFINE_SYSTEM_ERROR(CLIB_MUTEX_INIT_FAILURE, 42), /* 298 Standard library error - Mutex Init failure */ - MBED_DEFINE_SYSTEM_ERROR(CREATE_FAILED, 43), /* 299 Create failed */ - MBED_DEFINE_SYSTEM_ERROR(DELETE_FAILED, 44), /* 300 Delete failed */ - MBED_DEFINE_SYSTEM_ERROR(THREAD_CREATE_FAILED, 45), /* 301 Thread Create failed */ - MBED_DEFINE_SYSTEM_ERROR(THREAD_DELETE_FAILED, 46), /* 302 Thread Delete failed */ - MBED_DEFINE_SYSTEM_ERROR(PROHIBITED_IN_ISR_CONTEXT, 47), /* 303 Operation Prohibited in ISR context */ - MBED_DEFINE_SYSTEM_ERROR(PINMAP_INVALID, 48), /* 304 Pinmap Invalid */ - MBED_DEFINE_SYSTEM_ERROR(RTOS_EVENT, 49), /* 305 Unknown Rtos Error */ - MBED_DEFINE_SYSTEM_ERROR(RTOS_THREAD_EVENT, 50), /* 306 Rtos Thread Error */ - MBED_DEFINE_SYSTEM_ERROR(RTOS_MUTEX_EVENT, 51), /* 307 Rtos Mutex Error */ - MBED_DEFINE_SYSTEM_ERROR(RTOS_SEMAPHORE_EVENT, 52), /* 308 Rtos Semaphore Error */ - MBED_DEFINE_SYSTEM_ERROR(RTOS_MEMORY_POOL_EVENT, 53), /* 309 Rtos Memory Pool Error */ - MBED_DEFINE_SYSTEM_ERROR(RTOS_TIMER_EVENT, 54), /* 310 Rtos Timer Error */ - MBED_DEFINE_SYSTEM_ERROR(RTOS_EVENT_FLAGS_EVENT, 55), /* 311 Rtos Event flags Error */ - MBED_DEFINE_SYSTEM_ERROR(RTOS_MESSAGE_QUEUE_EVENT, 56), /* 312 Rtos Message queue Error */ - 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 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 */ - MBED_DEFINE_SYSTEM_ERROR(USAGEFAULT_EXCEPTION, 64), /* 320 UsageFault exception*/ - 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 */ - MBED_DEFINE_SYSTEM_ERROR(AUTHENTICATION_FAILED, 69), /* 325 Authentication Failed */ - MBED_DEFINE_SYSTEM_ERROR(RBP_AUTHENTICATION_FAILED, 70), /* 326 Rollback Protection Authentication Failed */ - MBED_DEFINE_SYSTEM_ERROR(BLE_USE_INCOMPATIBLE_API, 71), /* 327 Concurrent use of incompatible versions of a BLE API */ - MBED_DEFINE_SYSTEM_ERROR(BLE_ILLEGAL_STATE, 72), /* 328 BLE stack entered illegal state */ - - //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 - - //MBED CUSTOM ERROR CODE definitions starts at offset MBED_CUSTOM_ERROR_BASE, see above. - /* Add More/Custom Error Codes here, See example below */ - //DEFINE_CUSTOM_ERROR( MY_CUSTOM_ERROR , 1 ), - -} mbed_error_code_t; - -/** mbed_error_ctx struct - * - * This struct captures the context information at the time of error.\n - * It primarily contains information about the thread where the error originated,\n - * filename/line number of the source file where the error occurred, a context specific error value(error_value)\n - * and the address where the error originated.\n - * - * @note - * Below are the members of mbed_error_ctx struct\n - * error_status mbed_error_status_t value for this error\n - * error_function_address Address where the error occurred\n - * thread_id ID of the thread which generated the error\n - * thread_entry_address Entry function of the thread which generated the error\n - * thread_stack_size Stack Size of the thread which generated the error\n - * thread_stack_mem Stack Top of the thread which generated the error\n - * thread_current_sp Current Stack Pointer of the thread which generated the error\n - * error_value A context/error specific value associated with this error\n - * error_filename Filename where the error originated\n - * error_line_number Line number in error_filename where the error originated\n - */ -typedef struct _mbed_error_ctx { - mbed_error_status_t error_status; - uint32_t error_address; - uint32_t error_value; - uint32_t thread_id; - uint32_t thread_entry_address; - uint32_t thread_stack_size; - uint32_t thread_stack_mem; - uint32_t thread_current_sp; -#ifdef MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN - char error_filename[MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN]; - uint32_t error_line_number; -#endif -#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED - int32_t error_reboot_count;//everytime we write this struct we increment this value by 1, irrespective of time between reboots. Note that the data itself might change, but everytime we reboot due to error we update this count by 1 - int32_t is_error_processed;//once this error is processed set this value to 1 - uint32_t crc_error_ctx;//crc_error_ctx should always be the last member in this struct -#endif -} mbed_error_ctx; - -/** To generate a fatal compile-time error, you can use the pre-processor #error directive. - * - * @param format C string that contains data stream to be printed. - * Code snippets below show valid format. - * - * @code - * #error "That shouldn't have happened!" - * @endcode - * - * If the compiler evaluates this line, it will report the error and stop the compile. - * - * For example, you could use this to check some user-defined compile-time variables: - * - * @code - * #define NUM_PORTS 7 - * #if (NUM_PORTS > 4) - * #error "NUM_PORTS must be less than 4" - * #endif - * @endcode - * - * Reporting Run-Time Errors: - * To generate a fatal run-time error, you can use the mbed error() function. - * - * @code - * error("That shouldn't have happened!"); - * @endcode - * - * If the mbed running the program executes this function, it will print the - * message via the USB serial port, and then die with the blue lights of death! - * - * The message can use printf-style formatting, so you can report variables in the - * message too. For example, you could use this to check a run-time condition: - * - * @code - * if(x >= 5) { - * error("expected x to be less than 5, but got %d", x); - * } - * @endcode - * - * - */ - -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 - * @param module Module generating the error code. If its unknown, pass MBED_MODULE_UNKNOWN. See mbed_module_type_t for module types. - * @param error_code The mbed_error_code_t code to be used in generating the mbed_error_status_t. See mbed_error_code_t for error codes. - * - * @code - * - * mbed_error_status_t driver_error = MBED_MAKE_SYSTEM_ERROR( MODULE_DRIVER_USB, MBED_ERROR_CODE_INITIALIZATION_FAILED ) - * - * @endcode - * @note This macro generate mbed_error_status_t-es with error type set to MBED_ERROR_TYPE_SYSTEM - * - */ -#define MBED_MAKE_SYSTEM_ERROR(module, error_code) MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, module, error_code) - -/** - * Call this Macro to generate a mbed_error_status_t value for a Custom error - * @param module Module generating the error code. If its unknown, pass MBED_MODULE_UNKNOWN. See mbed_module_type_t for module types. - * @param error_code The mbed_error_code_t code to be used in generating the mbed_error_status_t. See mbed_error_code_t for error codes. - * - * @code - * - * mbed_error_status_t custom_error = MBED_MAKE_CUSTOM_ERROR( MBED_MODULE_APPLICATION, 0xDEAD//16-bit custom error code ) - * - * @endcode - * @note This macro generate mbed_error_status_t-es with error type set to MBED_ERROR_TYPE_CUSTOM - * - */ -#define MBED_MAKE_CUSTOM_ERROR(module, error_code) MAKE_MBED_ERROR(MBED_ERROR_TYPE_CUSTOM, module, error_code) - -/** - * Call this Macro to generate a mbed_error_status_t value for a System error - * @param module Module generating the error code. If its unknown, pass MBED_MODULE_UNKNOWN. See mbed_module_type_t for module types. - * @param error_code The mbed_error_code_t code to be used in generating the mbed_error_status_t. See mbed_error_code_t for error codes. - * - * @code - * - * mbed_error_status_t new_error = MBED_MAKE_ERROR( MODULE_DRIVER_USB, MBED_ERROR_INITIALIZATION_FAILED ) - * - * @endcode - * @note This macro generate mbed_error_status_t-es with error type set to MBED_ERROR_TYPE_SYSTEM - * - */ -#define MBED_MAKE_ERROR(module, error_code) MBED_MAKE_SYSTEM_ERROR(module, error_code) - -/** - * 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_ctx Error context structure associated with this error. - * @return void - * - */ -typedef void (*mbed_error_hook_t)(const mbed_error_ctx *error_ctx); - -/** - * Callback/Error hook function. If application implementation needs to receive this callback when an error is reported, - * mbed_error_hook function should be overridden with custom implementation. 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_ctx Error context structure associated with this error. - * @return void - * - */ -void mbed_error_hook(const mbed_error_ctx *error_context); - -/** - * Callback function for reporting error context during boot up. When MbedOS error handling system detects a fatal error - * it will auto-reboot the system(if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED is enabled) after capturing the - * error info in special crash data RAM region. Once rebooted, MbedOS initialization routines will call this function with a pointer to - * the captured mbed_error_ctx structure. If application implementation needs to receive this callback, mbed_error_reboot_callback - * function should be overridden with custom implementation. By default it's defined as a WEAK function in mbed_error.c. - * Note that this callback will be invoked before the system starts executing main() function. So the implementation of - * the callback should be aware any resource limitations/availability of resources which are yet to be initialized by application main(). - * - * @param error_ctx Error context structure associated with this error. - * @return void - * - */ -void mbed_error_reboot_callback(mbed_error_ctx *error_context); - -/** - * Initialize error handling system, this is called by the mbed-os boot sequence. This is not required to be called by Application unless the boot sequence is overridden by the system implementation. - * NOTE: If MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED is enabled and if the current reboot count exceeds MBED_CONF_PLATFORM_ERROR_REBOOT_MAX the system will halt when this function is called, - * and in such cases the caller will not get the control back. Also note that calling this function may trigger mbed_error_reboot_callback() if application side overides mbed_error_reboot_callback(). - * @return MBED_SUCCESS on success. - * - */ - -mbed_error_status_t mbed_error_initialize(void); - -/** - * Call this function to retrieve the error context after a fatal error which triggered a system reboot. The function retrieves the error context stored in crash-report ram area which is preserved over reboot. - * @param error_info Pointer to mbed_error_ctx struct allocated by the caller. This is the mbed_error_ctx info captured as part of the fatal error which triggered the reboot. - * @return 0 or MBED_SUCCESS on success. - * MBED_ERROR_INVALID_ARGUMENT in case of invalid error_info pointer - * MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system - * - */ -mbed_error_status_t mbed_get_reboot_error_info(mbed_error_ctx *error_info); - -/** - * Calling this function resets the current reboot context captured by the system(stored in special crash data RAM region). - * @return MBED_SUCCESS on success. - * MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system - */ -mbed_error_status_t mbed_reset_reboot_error_info(void); - -/** - * Calling this function resets the current reboot count stored as part of error context captured in special crash data RAM region. - * The function will also update the CRC value stored as part of error context accordingly. - * @return MBED_SUCCESS on success. - * MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system - */ -mbed_error_status_t mbed_reset_reboot_count(void); - -/** - * Call this function to set a system error/warning. This function will log the error status with the context info and return to caller. - * - * @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. - * @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 - * - * @code - * - * mbed_error( ERROR_OUT_OF_MEMORY, "Out of memory error", 0, __FILE__, __LINE__ ) - * - * @endcode - * - * @note See MBED_WARNING/MBED_ERROR macros which provides a wrapper on this API - */ -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); - -/** - * Returns the first system error reported. - * @return mbed_error_status_t code logged for the first error or MBED_SUCCESS if no errors are logged. - * - */ -mbed_error_status_t mbed_get_first_error(void); - -/** - * Returns the most recent system error reported. - * @return mbed_error_status_t code logged for the last error or MBED_SUCCESS if no errors are logged. - * - */ -mbed_error_status_t mbed_get_last_error(void); - -/** - * Returns the number of system errors reported after boot. - * @return int Number of errors reported. - * - */ -int mbed_get_error_count(void); - -/** - * Returns whether we are processing a fatal mbed error. - * @return bool Whether a fatal error has occurred. - * - */ -bool mbed_get_error_in_progress(void); - -/** - * Call this function to set a fatal system error and halt the system. This function will log the fatal error with the context info and prints the error report and halts the system. - * - * @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. - * @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 Does not return. - * - * @code - * - * mbed_error( MBED_ERROR_PROHIBITED_OPERATION, "Prohibited operation tried", 0, __FILE__, __LINE__ ) - * - * @endcode - * - * @note See MBED_WARNING/MBED_ERROR macros which provides a wrapper on this API - */ -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. - * This function will be called with error context info whenever system handles a mbed_error/mbed_warning call - * NOTE: This function should be implemented for re-entrancy as multiple threads may invoke mbed_error which may cause error hook to be called. - * @param custom_error_hook mbed_error_status_t status to be set(See mbed_error_status_t enum above for available error status values). - * @return 0 or MBED_SUCCESS on success. - * MBED_ERROR_INVALID_ARGUMENT in case of NULL for custom_error_hook - * - * @code - * - * mbed_error_status_t my_custom_error_hook(mbed_error_status_t error_status, const mbed_error_ctx *error_ctx) { - * //Do something with the error_status or error_ctx - * } - * - * mbed_set_error_hook( my_custom_error_hook ) - * - * @endcode - * @note The error hook function implementation should be re-entrant. - * - * @deprecated You should use an overridden mbed_error_hook() function if you like to catch errors in your application. - * With mbed_set_error_hook() it is not possible to catch errors before your application started. - */ -mbed_error_status_t mbed_set_error_hook(mbed_error_hook_t custom_error_hook); - -/** - * Reads the first error context information captured. - * @param error_info This is the mbed_error_context info captured as part of the first mbed_error call. The caller should pass a pointer to mbed_error_context struct allocated by the caller. - * @return 0 or MBED_SUCCESS on success. - * MBED_ERROR_INVALID_ARGUMENT in case of invalid index - * - */ -mbed_error_status_t mbed_get_first_error_info(mbed_error_ctx *error_info); - -/** - * Reads the last error context information captured. - * @param error_info This is the mbed_error_context info captured as part of the last mbed_error call. The caller should pass a pointer to mbed_error_context struct allocated by the caller. - * @return 0 or MBED_ERROR_SUCCESS on success. - * MBED_ERROR_INVALID_ARGUMENT in case of invalid index - * - */ -mbed_error_status_t mbed_get_last_error_info(mbed_error_ctx *error_info); - -/** - * Clears the last error, first error, error count and all entries in the error history. - * @return 0 or MBED_SUCCESS on success. - * - */ -mbed_error_status_t mbed_clear_all_errors(void); - -/** - * Generates a mbed_error_status_t value based on passed in values for type, module and error code. - * @param error_type Error type based on mbed_error_type_t enum. - * @param module Module type based on mbed_module_type_t enum. - * @param error_code Error codes defined by mbed_error_code_t enum - * @return 0 or MBED_ERROR_SUCCESS on success. - * - */ -mbed_error_status_t mbed_make_error(mbed_error_type_t error_type, mbed_module_type_t module, mbed_error_code_t error_code); - -/** - * Returns the current number of entries in the error history, if there has been more than max number of errors logged the number returned will be max depth of error history. - * @return Current number of entries in the error history. - * - */ -int mbed_get_error_hist_count(void); - -/** - * Reads the error context information for a specific error from error history, specified by the index. - * - * @param index index of the error context entry in the history to be retrieved.\n - * The number of entries in the error history is configured during build and the max index depends on max depth of error history.\n - * index = 0 points to the oldest entry in the history, and index = (max history depth - 1) points to the latest entry in the error history.\n - * @param error_info This is the mbed_error_context info captured as part of the error history. The caller should pass a pointer to mbed_error_context struct allocated by the caller. - * @return 0 or MBED_SUCCESS on success. - * MBED_ERROR_INVALID_ARGUMENT in case of invalid index - * - */ -mbed_error_status_t mbed_get_error_hist_info(int index, mbed_error_ctx *error_info); - -/** - * Saves the error history information to a file - * - * @param path path to the file in the filesystem - * @return 0 or MBED_ERROR_SUCCESS on success. - * MBED_ERROR_WRITE_FAILED if writing to file failed - * MBED_ERROR_INVALID_ARGUMENT if path is not valid - * - * @note Filesystem support is required in order for this function to work. - * - */ -mbed_error_status_t mbed_save_error_hist(const char *path); - -#ifdef __cplusplus -} -#endif - -#endif - -/** @}*/ -/** @}*/ - - diff --git a/platform/mbed_interface.h b/platform/mbed_interface.h deleted file mode 100644 index f6d0738..0000000 --- a/platform/mbed_interface.h +++ /dev/null @@ -1,189 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_INTERFACE_H -#define MBED_INTERFACE_H - -#include - -#include "platform/mbed_toolchain.h" -#include "device.h" - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_interface Network interface and other utility functions - * @{ - */ - -/* Mbed interface mac address - * if MBED_MAC_ADD_x are zero, interface uid sets mac address, - * otherwise MAC_ADD_x are used. - */ -#define MBED_MAC_ADDR_INTERFACE 0x00 -#define MBED_MAC_ADDR_0 MBED_MAC_ADDR_INTERFACE -#define MBED_MAC_ADDR_1 MBED_MAC_ADDR_INTERFACE -#define MBED_MAC_ADDR_2 MBED_MAC_ADDR_INTERFACE -#define MBED_MAC_ADDR_3 MBED_MAC_ADDR_INTERFACE -#define MBED_MAC_ADDR_4 MBED_MAC_ADDR_INTERFACE -#define MBED_MAC_ADDR_5 MBED_MAC_ADDR_INTERFACE -#define MBED_MAC_ADDRESS_SUM (MBED_MAC_ADDR_0 | MBED_MAC_ADDR_1 | MBED_MAC_ADDR_2 | MBED_MAC_ADDR_3 | MBED_MAC_ADDR_4 | MBED_MAC_ADDR_5) - -#ifdef __cplusplus -extern "C" { -#endif - -#if DEVICE_SEMIHOST - -/** - * \defgroup platform_interface interface functions - * @{ - */ - -/** Functions to control the mbed interface - * - * mbed Microcontrollers have a built-in interface to provide functionality such as - * drag-n-drop download, reset, serial-over-usb, and access to the mbed local file - * system. These functions provide means to control the interface using semihost - * calls it supports. - */ - -/** Determine whether the mbed interface is connected, based on whether debug is enabled - * - * @returns - * 1 if interface is connected, - * 0 otherwise - */ -int mbed_interface_connected(void); - -/** Instruct the mbed interface to reset, as if the reset button had been pressed - * - * @returns - * 1 if successful, - * 0 otherwise (e.g. interface not present) - */ -int mbed_interface_reset(void); - -/** This will disconnect the debug aspect of the interface, so semihosting will be disabled. - * The interface will still support the USB serial aspect - * - * @returns - * 0 if successful, - * -1 otherwise (e.g. interface not present) - */ -int mbed_interface_disconnect(void); - -/** This will disconnect the debug aspect of the interface, and if the USB cable is not - * connected, also power down the interface. If the USB cable is connected, the interface - * will remain powered up and visible to the host - * - * @returns - * 0 if successful, - * -1 otherwise (e.g. interface not present) - */ -int mbed_interface_powerdown(void); - -/** This returns a string containing the 32-character UID of the mbed interface - * This is a weak function that can be overwritten if required - * - * @param uid A 33-byte array to write the null terminated 32-byte string - * - * @returns - * 0 if successful, - * -1 otherwise (e.g. interface not present) - */ -int mbed_interface_uid(char *uid); - -#endif - -/** This returns a unique 6-byte MAC address, based on the interface UID - * If the interface is not present, it returns a default fixed MAC address (00:02:F7:F0:00:00) - * - * This is a weak function that can be overwritten if you want to provide your own mechanism to - * provide a MAC address. - * - * @param mac A 6-byte array to write the MAC address - */ -void mbed_mac_address(char *mac); - -/** Cause the mbed to flash the BLOD (Blue LEDs Of Death) sequence - */ -MBED_NORETURN void mbed_die(void); - -/** Print out an error message. This is typically called when - * handling a crash. - * - * @note Synchronization level: Interrupt safe, as long as the - * FileHandle::write of the stderr device is. See mbed_error_puts - * for more information. - * @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. - * - * @code - * mbed_error_printf("Failed: %s, file: %s, line %d \n", expr, file, line); - * @endcode - * - */ -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. - * - * @note Synchronization level: Interrupt safe, as long as the - * FileHandle::write of the stderr device is. See mbed_error_puts - * for more information. - * - * @param format C string that contains data stream to be printed. - * @param arg Variable arguments list - * - */ -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, as long as the - * FileHandle::write of the stderr device is. The default - * serial console is safe, either buffered or not. If the - * console has not previously been initialized, an attempt - * to use this from interrupt may crash during console initialization. - * Special handling of `mbed_error` relaxes various system traps - * to increase the chance of initialization working. - * - * @param str C string that contains data stream to be printed. - * - */ -void mbed_error_puts(const char *str); - -/** @}*/ - - -#ifdef __cplusplus -} -#endif - -#endif - -/** @}*/ diff --git a/platform/mbed_mem_trace.h b/platform/mbed_mem_trace.h deleted file mode 100644 index 2c5bc40..0000000 --- a/platform/mbed_mem_trace.h +++ /dev/null @@ -1,174 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_MEM_TRACE_H__ -#define __MBED_MEM_TRACE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * enum Memory operation types for tracer - */ -enum { - 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 */ -}; - -/** - * \defgroup platform_mem_trace mem_trace functions - * @{ - */ - -/* Prefix for the output of the default tracer */ -#define MBED_MEM_DEFAULT_TRACER_PREFIX "#" - -/** - * Type of the callback used by the memory tracer. This callback is called when a memory - * allocation operation (malloc, realloc, calloc, free) is called and tracing is enabled - * for that memory allocation function. - * - * @param op the ID of the operation (MBED_MEM_TRACE_MALLOC, MBED_MEM_TRACE_REALLOC, - * MBED_MEM_TRACE_CALLOC or MBED_MEM_TRACE_FREE). - * @param res the result that the memory operation returned (NULL for 'free'). - * @param caller the caller of the memory operation. Note that the value of 'caller' might be - * unreliable. - * - * The rest of the parameters passed 'mbed_mem_trace_cb_t' are the same as the memory operations - * that triggered its call (see 'man malloc' for details): - * - * - for malloc: cb(MBED_MEM_TRACE_MALLOC, res, caller, size). - * - for realloc: cb(MBED_MEM_TRACE_REALLOC, res, caller, ptr, size). - * - for calloc: cb(MBED_MEM_TRACE_CALLOC, res, caller, nmemb, size). - * - for free: cb(MBED_MEM_TRACE_FREE, NULL, caller, ptr). - */ -typedef void (*mbed_mem_trace_cb_t)(uint8_t op, void *res, void *caller, ...); - -/** - * Set the callback used by the memory tracer (use NULL for disable tracing). - * - * @param cb the callback to call on each memory operation. - */ -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 realloc/calloc - */ -void mbed_mem_trace_lock(); - -/** - * Trace unlock. - */ -void mbed_mem_trace_unlock(); - -/** - * Trace a call to 'malloc'. - * @param res the result of running 'malloc'. - * @param size the 'size' argument given to 'malloc'. - * @param caller the caller of the memory operation. - * @return 'res' (the first argument). - */ -void *mbed_mem_trace_malloc(void *res, size_t size, void *caller); - -/** - * Trace a call to 'realloc'. - * @param res the result of running 'realloc'. - * @param ptr the 'ptr' argument given to 'realloc'. - * @param size the 'size' argument given to 'realloc'. - * @param caller the caller of the memory operation. - * @return 'res' (the first argument). - */ -void *mbed_mem_trace_realloc(void *res, void *ptr, size_t size, void *caller); - -/** - * Trace a call to 'calloc'. - * @param res the result of running 'calloc'. - * @param num the 'nmemb' argument given to 'calloc'. - * @param size the 'size' argument given to 'calloc'. - * @param caller the caller of the memory operation. - * @return 'res' (the first argument). - */ -void *mbed_mem_trace_calloc(void *res, size_t num, size_t size, void *caller); - -/** - * Trace a call to 'free'. - * @param ptr the 'ptr' argument given to 'free'. - * @param caller the caller of the memory operation. - */ -void mbed_mem_trace_free(void *ptr, void *caller); - -/** - * Default memory trace callback. DO NOT CALL DIRECTLY. It is meant to be used - * as the second argument of 'mbed_mem_trace_setup'. - * - * The default callback outputs trace data using 'printf', in a format that's - * easily parsable by an external tool. For each memory operation, the callback - * outputs a line that begins with "#:<0xresult>;<0xcaller>-": - * - * @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 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. - * - * The rest of the output depends on the operation being traced: - * - * - for 'malloc': 'size', where 'size' is the original argument to 'malloc'. - * - for 'realloc': '0xptr;size', where 'ptr' (base 16) and 'size' are the original arguments to 'realloc'. - * - for 'calloc': 'nmemb;size', where 'nmemb' and 'size' are the original arguments to 'calloc'. - * - for 'free': '0xptr', where 'ptr' (base 16) is the original argument to 'free'. - * - * Examples: - * - * - "#m:0x20003240;0x600d-50" encodes a 'malloc' that returned 0x20003240, was called - * by the instruction at 0x600D with a the 'size' argument equal to 50. - * - "#f:0x0;0x602f-0x20003240" encodes a 'free' that was called by the instruction at - * 0x602f with the 'ptr' argument equal to 0x20003240. - */ -void mbed_mem_trace_default_callback(uint8_t op, void *res, void *caller, ...); - -/** @}*/ - -#ifdef __cplusplus -} -#endif - -#endif// #ifndef __MBED_MEM_TRACE_H__ - - -/** @}*/ diff --git a/platform/mbed_mktime.h b/platform/mbed_mktime.h deleted file mode 100644 index 0a748c2..0000000 --- a/platform/mbed_mktime.h +++ /dev/null @@ -1,132 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017-2019 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_MKTIME_H -#define MBED_MKTIME_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_mktime mktime functions - * @{ - */ - -/* Time range across the whole 32-bit range should be supported which means that years in range 1970 - 2106 can be - * encoded. We have two types of RTC devices: - * a) RTCs which handles all leap years in the mentioned year range correctly. Leap year is determined by checking if - * the year counter value is divisible by 400, 100, and 4. No problem here. - * b) RTCs which handles leap years correctly up to 2100. The RTC does a simple bit comparison to see if the two - * lowest order bits of the year counter are zero. In this case 2100 year will be considered - * incorrectly as a leap year, so the last valid point in time will be 28.02.2100 23:59:59 and next day will be - * 29.02.2100 (invalid). So after 28.02.2100 the day counter will be off by a day. - */ -typedef enum { - RTC_FULL_LEAP_YEAR_SUPPORT, - RTC_4_YEAR_LEAP_YEAR_SUPPORT -} rtc_leap_year_support_t; - -/** Compute if a year is a leap year or not. - * - * @param year The year to test it shall be in the range [70:206]. Year 0 is - * translated into year 1900 CE. - * @param leap_year_support use RTC_FULL_LEAP_YEAR_SUPPORT if RTC device is able - * to correctly detect all leap years in range [70:206] otherwise use RTC_4_YEAR_LEAP_YEAR_SUPPORT. - * - * @return true if the year in input is a leap year and false otherwise. - * - * @note For use by the HAL only - * @note Year 2100 is treated differently for devices with full leap year support and devices with - * partial leap year support. Devices with partial leap year support treats 2100 as a leap year. - */ -bool _rtc_is_leap_year(int year, rtc_leap_year_support_t leap_year_support); - -/* Convert a calendar time into time since UNIX epoch as a time_t. - * - * This function is a thread safe (partial) replacement for mktime. It is - * tailored around RTC peripherals needs and is not by any mean a complete - * replacement of mktime. - * - * @param time The calendar time to convert into a time_t since epoch. - * The fields from tm used for the computation are: - * - tm_sec - * - tm_min - * - tm_hour - * - tm_mday - * - tm_mon - * - tm_year - * Other fields are ignored and won't be renormalized by a call to this function. - * A valid calendar time is comprised between: - * the 1st of January 1970 at 00:00:00 to the 7th of February 2106 at 06:28:15. - * @param leap_year_support use RTC_FULL_LEAP_YEAR_SUPPORT if RTC device is able - * to correctly detect all leap years in range [70:206] otherwise use RTC_4_YEAR_LEAP_YEAR_SUPPORT. - * @param seconds holder for the result - calendar time as seconds since UNIX epoch. - * - * @return true on success, false if conversion error occurred. - * - * @note Leap seconds are not supported. - * @note Values in output range from 0 to UINT_MAX. - * @note Full and partial leap years support. - * @note For use by the HAL only - */ -bool _rtc_maketime(const struct tm *time, time_t *seconds, rtc_leap_year_support_t leap_year_support); - -/* Convert a given time in seconds since epoch into calendar time. - * - * This function is a thread safe (partial) replacement for localtime. It is - * tailored around RTC peripherals specification and is not by any means a - * complete of localtime. - * - * @param timestamp The time (in seconds) to convert into calendar time. Valid - * input are in the range [0 : UINT32_MAX]. - * @param calendar_time Pointer to the object which will contain the result of - * the conversion. The tm fields filled by this function are: - * - tm_sec - * - tm_min - * - tm_hour - * - tm_mday - * - tm_mon - * - tm_year - * - tm_wday - * - tm_yday - * The object remains untouched if the time in input is invalid. - * @param leap_year_support use RTC_FULL_LEAP_YEAR_SUPPORT if RTC device is able - * to correctly detect all leap years in range [70:206] otherwise use RTC_4_YEAR_LEAP_YEAR_SUPPORT. - * @return true if the conversion was successful, false otherwise. - * - * @note For use by the HAL only. - * @note Full and partial leap years support. - */ -bool _rtc_localtime(time_t timestamp, struct tm *time_info, rtc_leap_year_support_t leap_year_support); - -/** @}*/ - -#ifdef __cplusplus -} -#endif - -#endif /* MBED_MKTIME_H */ - -/** @}*/ diff --git a/platform/mbed_mpu_mgmt.h b/platform/mbed_mpu_mgmt.h deleted file mode 100644 index 01f9e78..0000000 --- a/platform/mbed_mpu_mgmt.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited and affiliates. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MBED_MPU_MGMT_H -#define MBED_MPU_MGMT_H - -#include "hal/mpu_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_mpu_mgmt MPU management functions - * @{ - */ - -#if (DEVICE_MPU && MBED_CONF_PLATFORM_USE_MPU) || defined(DOXYGEN_ONLY) - -#define mbed_mpu_manager_init() mbed_mpu_init() - -#define mbed_mpu_manager_deinit() mbed_mpu_free() - -/** Lock ram execute never mode off - * - * This disables the MPU's execute never ram protection and allows - * functions to run from RAM. Execution directly from ram will be - * allowed if this function is invoked at least once (the internal - * counter is non-zero). - * - * Use this locking mechanism for code which needs to execute from - * ram such as flash programming algorithms and ram thunks. - * - * The lock is a counter, can be locked up to USHRT_MAX - * This function is IRQ and thread safe - */ -void mbed_mpu_manager_lock_ram_execution(void); - -/** Unlock ram execute never mode - * - * Use unlocking in pair with mbed_mpu_manager_lock_ram_execution(). - * - * The lock is a counter, should be equally unlocked as locked - * This function is IRQ and thread safe - */ -void mbed_mpu_manager_unlock_ram_execution(void); - -/** Lock rom write never mode off - * - * This disables the MPU's read only ROM protection and allows - * ROM to be written to. Writing to ROM will not result in an MPU - * fault if this function is invoked at least once (the internal - * counter is non-zero). - * - * Use this locking mechanism for code which needs to write to - * ROM such as flash programming algorithms. - * - * The lock is a counter, can be locked up to USHRT_MAX - * This function is IRQ and thread safe - */ -void mbed_mpu_manager_lock_rom_write(void); - -/** Unlock rom write never mode - * - * Use unlocking in pair with mbed_mpu_manager_lock_rom_write(). - * - * The lock is a counter, should be equally unlocked as locked - * This function is IRQ and thread safe - */ -void mbed_mpu_manager_unlock_rom_write(void); - -#else - -#define mbed_mpu_manager_init() (void)0 - -#define mbed_mpu_manager_deinit() (void)0 - -#define mbed_mpu_manager_lock_ram_execution() (void)0 - -#define mbed_mpu_manager_unlock_ram_execution() (void)0 - -#define mbed_mpu_manager_lock_rom_write() (void)0 - -#define mbed_mpu_manager_unlock_rom_write() (void)0 - -#endif - -#ifdef __cplusplus -} -#endif - -#endif - -/** @}*/ -/** @}*/ diff --git a/platform/mbed_poll.h b/platform/mbed_poll.h deleted file mode 100644 index 04a71c4..0000000 --- a/platform/mbed_poll.h +++ /dev/null @@ -1,62 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017-2019 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_POLL_H -#define MBED_POLL_H - -#define POLLIN 0x0001 ///< Data may be read without blocking -#define POLLOUT 0x0010 ///< Data may be written without blocking -#define POLLERR 0x1000 ///< An error has occurred on the device or stream -#define POLLHUP 0x2000 ///< The device has been disconnected -#define POLLNVAL 0x4000 ///< The specified file handle value is invalid - -namespace mbed { - -class FileHandle; - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_poll poll functions - * @{ - */ - -struct pollfh { - FileHandle *fh; - short events; - short revents; -}; - -/** A mechanism to multiplex input/output over a set of file handles(file descriptors). - * For every file handle provided, poll() examines it for any events registered for that particular - * file handle. - * - * @param fhs an array of PollFh struct carrying a FileHandle and bitmasks of events - * @param nfhs number of file handles - * @param timeout timer value to timeout or -1 for loop forever - * - * @return number of file handles selected (for which revents is non-zero). 0 if timed out with nothing selected. -1 for error. - */ -int poll(pollfh fhs[], unsigned nfhs, int timeout); - -/**@}*/ - -/**@}*/ - -} // namespace mbed - -#endif //MBED_POLL_H diff --git a/platform/mbed_power_mgmt.h b/platform/mbed_power_mgmt.h deleted file mode 100644 index caf1d02..0000000 --- a/platform/mbed_power_mgmt.h +++ /dev/null @@ -1,250 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_POWER_MGMT_H -#define MBED_POWER_MGMT_H - - -#include "platform/mbed_toolchain.h" -#include "hal/ticker_api.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_power_mgmt Power management functions - * @{ - */ - -/** - * @defgroup hal_sleep_manager Sleep manager API - * The sleep manager provides API to automatically select sleep mode. - * - * There are two sleep modes: - * - sleep - * - deepsleep - * - * Use locking/unlocking deepsleep for drivers that depend on features that - * 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 - * - * void driver::handler() - * { - * if (_sensor.get_event()) { - * // any event - we are finished, unlock the deepsleep - * sleep_manager_unlock_deep_sleep(); - * _callback(); - * } - * } - * - * int driver::measure(event_t event, callback_t& callback) - * { - * _callback = callback; - * sleep_manager_lock_deep_sleep(); - * // start async transaction, we are waiting for an event - * 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); -void sleep_tracker_unlock(const char *const filename, int line); - -#define sleep_manager_lock_deep_sleep() \ - do \ - { \ - sleep_manager_lock_deep_sleep_internal(); \ - sleep_tracker_lock(MBED_FILENAME, __LINE__); \ - } while (0); - -#define sleep_manager_unlock_deep_sleep() \ - do \ - { \ - sleep_manager_unlock_deep_sleep_internal(); \ - sleep_tracker_unlock(MBED_FILENAME, __LINE__); \ - } while (0); - -#else - -#define sleep_manager_lock_deep_sleep() \ - sleep_manager_lock_deep_sleep_internal() - -#define sleep_manager_unlock_deep_sleep() \ - sleep_manager_unlock_deep_sleep_internal() - -#endif // MBED_SLEEP_TRACING_ENABLED - -/** Lock the deep sleep mode - * - * This locks the automatic deep mode selection. - * sleep_manager_sleep_auto() will ignore deepsleep mode if - * this function is invoked at least once (the internal counter is non-zero) - * - * Use this locking mechanism for interrupt driven API that are - * running in the background and deepsleep could affect their functionality - * - * The lock is a counter, can be locked up to USHRT_MAX - * This function is IRQ and thread safe - */ -void sleep_manager_lock_deep_sleep_internal(void); - -/** Unlock the deep sleep mode - * - * Use unlocking in pair with sleep_manager_lock_deep_sleep(). - * - * The lock is a counter, should be equally unlocked as locked - * This function is IRQ and thread safe - */ -void sleep_manager_unlock_deep_sleep_internal(void); - -/** Get the status of deep sleep allowance for a target - * - * @return true if a target can go to deepsleep, false otherwise - */ -bool sleep_manager_can_deep_sleep(void); - -/** Check if the target can deep sleep within a period of time - * - * This function in intended for use in testing. The amount - * of time this functions waits for deeps sleep to be available - * is currently 2ms. This may change in the future depending - * on testing requirements. - * - * @return true if a target can go to deepsleep, false otherwise - */ -bool sleep_manager_can_deep_sleep_test_check(void); - -/** 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 - * - * @note - * If MBED_DEBUG is defined, only hal_sleep is allowed. This ensures the debugger - * to be active for debug modes. - * - */ -void sleep_manager_sleep_auto(void); - -/** Send the microcontroller to sleep - * - * @note This function can be a noop if not implemented by the platform. - * @note This function will be a noop in debug mode (debug build profile when MBED_DEBUG is defined). - * @note This function will be a noop if the following conditions are met: - * - The RTOS is present - * - The processor turn off the Systick clock during sleep - * - The target does not implement tickless mode - * - * The processor is setup ready for sleep, and sent to sleep using __WFI(). In this mode, the - * system clock to the core is stopped until a reset or an interrupt occurs. This eliminates - * dynamic power used by the processor, memory systems and buses. The processor, peripheral and - * memory state are maintained, and the peripherals continue to work and can generate interrupts. - * - * The processor can be woken up by any internal peripheral interrupt or external pin interrupt. - * - * @note - * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. - * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be - * able to access the LocalFileSystem - */ -static inline void sleep(void) -{ -#if DEVICE_SLEEP -#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_SYSTICK_CLK_OFF_DURING_SLEEP == 0) || defined(MBED_TICKLESS) */ -#endif /* DEVICE_SLEEP */ -} - -/** Provides the time spent in sleep mode since boot. - * - * @return Time spent in sleep - * @note Works only if platform supports LP ticker. - */ -us_timestamp_t mbed_time_sleep(void); - -/** Provides the time spent in deep sleep mode since boot. - * - * @return Time spent in deep sleep - * @note Works only if platform supports LP ticker. - */ -us_timestamp_t mbed_time_deepsleep(void); - -/** Provides the time spent in idle mode since boot. - * - * @return Idle thread time. - * @note Works only if platform supports LP ticker. - */ -us_timestamp_t mbed_time_idle(void); - -/** Provides the time since the system is up i.e. boot. - * - * @return System uptime. - * @note Works only if platform supports LP ticker. - */ -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 - -#endif - -/** @}*/ -/** @}*/ diff --git a/platform/mbed_preprocessor.h b/platform/mbed_preprocessor.h deleted file mode 100644 index f7be2f1..0000000 --- a/platform/mbed_preprocessor.h +++ /dev/null @@ -1,87 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_PREPROCESSOR_H -#define MBED_PREPROCESSOR_H - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_preprocessor preprocessor macros - * @{ - */ - -/** MBED_CONCAT - * Concatenate tokens together - * - * @note - * Expands tokens before concatenation - * - * @code - * // Creates a unique label based on the line number - * int MBED_CONCAT(UNIQUE_LABEL_, __LINE__) = 1; - * @endcode - */ -#define MBED_CONCAT(a, b) MBED_CONCAT_(a, b) -#define MBED_CONCAT_(a, b) a##b - -/** MBED_STRINGIFY - * Converts tokens into strings - * - * @note - * Expands tokens before stringification - * - * @code - * // Creates a string based on the parameters - * const char *c = MBED_STRINGIFY(This is a ridiculous way to create a string) - * @endcode - */ -#define MBED_STRINGIFY(a) MBED_STRINGIFY_(a) -#define MBED_STRINGIFY_(a) #a - -/** MBED_STRLEN - * Reports string token length - * - * @note - * Expands tokens before calculating length - * - * @code - * // Get string length - * const int len = MBED_STRLEN("Get the length") - * @endcode - */ -#define MBED_STRLEN(a) MBED_STRLEN_(a) -#define MBED_STRLEN_(a) (sizeof(a) - 1) - -/** MBED_COUNT_VA_ARGS(...) - * Reports number of tokens passed - * - * @note - * Token limit is 16 - * - * @code - * // Get number of arguments - * const int count = MBED_COUNT_VA_ARGS("Address 0x%x, Data[0] = %d Data[1] = %d", 0x20001234, 10, 20) - * @endcode - */ -#define MBED_COUNT_VA_ARGS(...) GET_NTH_ARG_(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) -#define GET_NTH_ARG_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, N, ...) N - -#endif - -/** @}*/ -/** @}*/ diff --git a/platform/mbed_retarget.h b/platform/mbed_retarget.h deleted file mode 100644 index 380c8d2..0000000 --- a/platform/mbed_retarget.h +++ /dev/null @@ -1,670 +0,0 @@ -/* - * mbed Microcontroller Library - * Copyright (c) 2006-2019 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 RETARGET_H -#define RETARGET_H - -#if __cplusplus -#include -#else -#include -#endif //__cplusplus -#include -#include - -/* Include logic for errno so we can get errno defined but not bring in error_t, - * including errno here prevents an include later, which would redefine our - * error codes - */ -#ifndef __error_t_defined -#define __error_t_defined 1 -#endif -#include - -#if defined __has_include -# if __has_include () -# include -# define HAVE_SYS_STAT_H -# endif -#endif - -/* We can get the following standard types from sys/types for gcc, but we - * need to define the types ourselves for the other compilers that normally - * target embedded systems */ -typedef signed int ssize_t; ///< Signed size type, usually encodes negative errors -typedef signed long off_t; ///< Offset in a data stream -typedef unsigned int nfds_t; ///< Number of file descriptors -typedef unsigned long long fsblkcnt_t; ///< Count of file system blocks -#if defined(__ARMCC_VERSION) || !defined(__GNUC__) -typedef unsigned int mode_t; ///< Mode for opening files -typedef unsigned int dev_t; ///< Device ID type -typedef unsigned long ino_t; ///< File serial number -typedef unsigned int nlink_t; ///< Number of links to a file -typedef unsigned int uid_t; ///< User ID -typedef unsigned int gid_t; ///< Group ID -#endif - -/* Flags for open() and fcntl(GETFL/SETFL) - * At present, fcntl only supports reading and writing O_NONBLOCK - */ -#define O_RDONLY 0 ///< Open for reading -#define O_WRONLY 1 ///< Open for writing -#define O_RDWR 2 ///< Open for reading and writing -#define O_NONBLOCK 0x0004 ///< Non-blocking mode -#define O_APPEND 0x0008 ///< Set file offset to end of file prior to each write -#define O_CREAT 0x0200 ///< Create file if it does not exist -#define O_TRUNC 0x0400 ///< Truncate file to zero length -#define O_EXCL 0x0800 ///< Fail if file exists -#define O_BINARY 0x8000 ///< Open file in binary mode - -#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) - -#define NAME_MAX 255 ///< Maximum size of a name in a file path - -#define STDIN_FILENO 0 -#define STDOUT_FILENO 1 -#define STDERR_FILENO 2 - -#include - -/** \addtogroup platform-public-api */ -/** @{*/ - -#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY -/** - * \defgroup platform_retarget Retarget functions - * @{ - */ - -/* DIR declarations must also be here */ -#if __cplusplus -namespace mbed { -class FileHandle; -class DirHandle; - -/** Targets may implement this to change stdin, stdout, stderr. - * - * If the application hasn't provided mbed_override_console, this is called - * to give the target a chance to specify a FileHandle for the console. - * - * If this is not provided or returns NULL, the console will be: - * - BufferedSerial if configuration option "platform.stdio-buffered-serial" is - * true and the target has DEVICE_SERIAL; - * - Raw HAL serial via serial_getc and serial_putc if - * "platform.stdio-buffered-serial" is false and the target has DEVICE_SERIAL; - * - stdout/stderr will be a sink and stdin will input a stream of 0s if the - * target does not have DEVICE_SERIAL. - * - * @param fd file descriptor - STDIN_FILENO, STDOUT_FILENO or STDERR_FILENO - * @return pointer to FileHandle to override normal stream otherwise NULL - */ -FileHandle *mbed_target_override_console(int fd); - -/** Applications may implement this to change stdin, stdout, stderr. - * - * This hook gives the application a chance to specify a custom FileHandle - * for the console. - * - * If this is not provided or returns NULL, the console will be specified - * by mbed_target_override_console, else will default to serial - see - * mbed_target_override_console for more details. - * - * Example using BufferedSerial: - * @code - * FileHandle *mbed::mbed_override_console(int) { - * static BufferedSerial my_serial(D0, D1); - * return &my_serial; - * } - * @endcode - * - * Example using SingleWireOutput: - * @code - * FileHandle *mbed::mbed_override_console(int) { - * static SerialWireOutput swo; - * return &swo; - * } - * @endcode - * - * Example using arm semihosting: - * @code - * FileHandle *mbed::mbed_override_console(int fileno) { - * static LocalFileSystem fs("host"); - * if (fileno == STDIN_FILENO) { - * static FileHandle *in_terminal; - * static int in_open_result = fs.open(&in_terminal, ":tt", O_RDONLY); - * return in_terminal; - * } else { - * static FileHandle *out_terminal; - * static int out_open_result = fs.open(&out_terminal, ":tt", O_WRONLY); - * return out_terminal; - * } - * } - * @endcode - * - * @param fd file descriptor - STDIN_FILENO, STDOUT_FILENO or STDERR_FILENO - * @return pointer to FileHandle to override normal stream otherwise NULL - */ -FileHandle *mbed_override_console(int fd); - -/** Look up the Mbed file handle corresponding to a file descriptor - * - * This conversion function permits an application to find the underlying - * FileHandle object corresponding to a POSIX file descriptor. - * - * This allows access to specialized behavior only available via the - * FileHandle API. - * - * Example of saving power by disabling console input - for buffered serial, - * this would release the RX interrupt handler, which would release the - * deep sleep lock. - * @code - * mbed_file_handle(STDIN_FILENO)->enable_input(false); - * @endcode - * - * @param fd file descriptor - * @return FileHandle pointer - * NULL if descriptor does not correspond to a FileHandle (only - * possible if it's not open with current implementation). - */ -FileHandle *mbed_file_handle(int fd); -} - -typedef mbed::DirHandle DIR; -#else -typedef struct Dir DIR; -#endif -#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY - -/* The intent of this section is to unify the errno error values to match - * the POSIX definitions for the GCC_ARM, ARMCC and IAR compilers. This is - * necessary because the ARMCC/IAR errno.h, or sys/stat.h are missing some - * symbol definitions used by the POSIX filesystem API to return errno codes. - * Note also that ARMCC errno.h defines some symbol values differently from - * the GCC_ARM/IAR/standard POSIX definitions. The definitions guard against - * this and future changes by changing the symbol definition as shown below. - */ -#undef EPERM -#define EPERM 1 /* Operation not permitted */ -#undef ENOENT -#define ENOENT 2 /* No such file or directory */ -#undef ESRCH -#define ESRCH 3 /* No such process */ -#undef EINTR -#define EINTR 4 /* Interrupted system call */ -#undef EIO -#define EIO 5 /* I/O error */ -#undef ENXIO -#define ENXIO 6 /* No such device or address */ -#undef E2BIG -#define E2BIG 7 /* Argument list too long */ -#undef ENOEXEC -#define ENOEXEC 8 /* Exec format error */ -#undef EBADF -#define EBADF 9 /* Bad file number */ -#undef ECHILD -#define ECHILD 10 /* No child processes */ -#undef EAGAIN -#define EAGAIN 11 /* Try again */ -#undef ENOMEM -#define ENOMEM 12 /* Out of memory */ -#undef EACCES -#define EACCES 13 /* Permission denied */ -#undef EFAULT -#define EFAULT 14 /* Bad address */ -#undef ENOTBLK -#define ENOTBLK 15 /* Block device required */ -#undef EBUSY -#define EBUSY 16 /* Device or resource busy */ -#undef EEXIST -#define EEXIST 17 /* File exists */ -#undef EXDEV -#define EXDEV 18 /* Cross-device link */ -#undef ENODEV -#define ENODEV 19 /* No such device */ -#undef ENOTDIR -#define ENOTDIR 20 /* Not a directory */ -#undef EISDIR -#define EISDIR 21 /* Is a directory */ -#undef EINVAL -#define EINVAL 22 /* Invalid argument */ -#undef ENFILE -#define ENFILE 23 /* File table overflow */ -#undef EMFILE -#define EMFILE 24 /* Too many open files */ -#undef ENOTTY -#define ENOTTY 25 /* Not a typewriter */ -#undef ETXTBSY -#define ETXTBSY 26 /* Text file busy */ -#undef EFBIG -#define EFBIG 27 /* File too large */ -#undef ENOSPC -#define ENOSPC 28 /* No space left on device */ -#undef ESPIPE -#define ESPIPE 29 /* Illegal seek */ -#undef EROFS -#define EROFS 30 /* Read-only file system */ -#undef EMLINK -#define EMLINK 31 /* Too many links */ -#undef EPIPE -#define EPIPE 32 /* Broken pipe */ -#undef EDOM -#define EDOM 33 /* Math argument out of domain of func */ -#undef ERANGE -#define ERANGE 34 /* Math result not representable */ -#undef EDEADLK -#define EDEADLK 35 /* Resource deadlock would occur */ -#undef ENAMETOOLONG -#define ENAMETOOLONG 36 /* File name too long */ -#undef ENOLCK -#define ENOLCK 37 /* No record locks available */ -#undef ENOSYS -#define ENOSYS 38 /* Function not implemented */ -#undef ENOTEMPTY -#define ENOTEMPTY 39 /* Directory not empty */ -#undef ELOOP -#define ELOOP 40 /* Too many symbolic links encountered */ -#undef EWOULDBLOCK -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#undef ENOMSG -#define ENOMSG 42 /* No message of desired type */ -#undef EIDRM -#define EIDRM 43 /* Identifier removed */ -#undef ECHRNG -#define ECHRNG 44 /* Channel number out of range */ -#undef EL2NSYNC -#define EL2NSYNC 45 /* Level 2 not synchronized */ -#undef EL3HLT -#define EL3HLT 46 /* Level 3 halted */ -#undef EL3RST -#define EL3RST 47 /* Level 3 reset */ -#undef ELNRNG -#define ELNRNG 48 /* Link number out of range */ -#undef EUNATCH -#define EUNATCH 49 /* Protocol driver not attached */ -#undef ENOCSI -#define ENOCSI 50 /* No CSI structure available */ -#undef EL2HLT -#define EL2HLT 51 /* Level 2 halted */ -#undef EBADE -#define EBADE 52 /* Invalid exchange */ -#undef EBADR -#define EBADR 53 /* Invalid request descriptor */ -#undef EXFULL -#define EXFULL 54 /* Exchange full */ -#undef ENOANO -#define ENOANO 55 /* No anode */ -#undef EBADRQC -#define EBADRQC 56 /* Invalid request code */ -#undef EBADSLT -#define EBADSLT 57 /* Invalid slot */ -#undef EDEADLOCK -#define EDEADLOCK EDEADLK /* Resource deadlock would occur */ -#undef EBFONT -#define EBFONT 59 /* Bad font file format */ -#undef ENOSTR -#define ENOSTR 60 /* Device not a stream */ -#undef ENODATA -#define ENODATA 61 /* No data available */ -#undef ETIME -#define ETIME 62 /* Timer expired */ -#undef ENOSR -#define ENOSR 63 /* Out of streams resources */ -#undef ENONET -#define ENONET 64 /* Machine is not on the network */ -#undef ENOPKG -#define ENOPKG 65 /* Package not installed */ -#undef EREMOTE -#define EREMOTE 66 /* Object is remote */ -#undef ENOLINK -#define ENOLINK 67 /* Link has been severed */ -#undef EADV -#define EADV 68 /* Advertise error */ -#undef ESRMNT -#define ESRMNT 69 /* Srmount error */ -#undef ECOMM -#define ECOMM 70 /* Communication error on send */ -#undef EPROTO -#define EPROTO 71 /* Protocol error */ -#undef EMULTIHOP -#define EMULTIHOP 72 /* Multihop attempted */ -#undef EDOTDOT -#define EDOTDOT 73 /* RFS specific error */ -#undef EBADMSG -#define EBADMSG 74 /* Not a data message */ -#undef EOVERFLOW -#define EOVERFLOW 75 /* Value too large for defined data type */ -#undef ENOTUNIQ -#define ENOTUNIQ 76 /* Name not unique on network */ -#undef EBADFD -#define EBADFD 77 /* File descriptor in bad state */ -#undef EREMCHG -#define EREMCHG 78 /* Remote address changed */ -#undef ELIBACC -#define ELIBACC 79 /* Can not access a needed shared library */ -#undef ELIBBAD -#define ELIBBAD 80 /* Accessing a corrupted shared library */ -#undef ELIBSCN -#define ELIBSCN 81 /* .lib section in a.out corrupted */ -#undef ELIBMAX -#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#undef ELIBEXEC -#define ELIBEXEC 83 /* Cannot exec a shared library directly */ -#undef EILSEQ -#define EILSEQ 84 /* Illegal byte sequence */ -#undef ERESTART -#define ERESTART 85 /* Interrupted system call should be restarted */ -#undef ESTRPIPE -#define ESTRPIPE 86 /* Streams pipe error */ -#undef EUSERS -#define EUSERS 87 /* Too many users */ -#undef ENOTSOCK -#define ENOTSOCK 88 /* Socket operation on non-socket */ -#undef EDESTADDRREQ -#define EDESTADDRREQ 89 /* Destination address required */ -#undef EMSGSIZE -#define EMSGSIZE 90 /* Message too long */ -#undef EPROTOTYPE -#define EPROTOTYPE 91 /* Protocol wrong type for socket */ -#undef ENOPROTOOPT -#define ENOPROTOOPT 92 /* Protocol not available */ -#undef EPROTONOSUPPORT -#define EPROTONOSUPPORT 93 /* Protocol not supported */ -#undef ESOCKTNOSUPPORT -#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#undef EOPNOTSUPP -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#undef EPFNOSUPPORT -#define EPFNOSUPPORT 96 /* Protocol family not supported */ -#undef EAFNOSUPPORT -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#undef EADDRINUSE -#define EADDRINUSE 98 /* Address already in use */ -#undef EADDRNOTAVAIL -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#undef ENETDOWN -#define ENETDOWN 100 /* Network is down */ -#undef ENETUNREACH -#define ENETUNREACH 101 /* Network is unreachable */ -#undef ENETRESET -#define ENETRESET 102 /* Network dropped connection because of reset */ -#undef ECONNABORTED -#define ECONNABORTED 103 /* Software caused connection abort */ -#undef ECONNRESET -#define ECONNRESET 104 /* Connection reset by peer */ -#undef ENOBUFS -#define ENOBUFS 105 /* No buffer space available */ -#undef EISCONN -#define EISCONN 106 /* Transport endpoint is already connected */ -#undef ENOTCONN -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#undef ESHUTDOWN -#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#undef ETOOMANYREFS -#define ETOOMANYREFS 109 /* Too many references: cannot splice */ -#undef ETIMEDOUT -#define ETIMEDOUT 110 /* Connection timed out */ -#undef ECONNREFUSED -#define ECONNREFUSED 111 /* Connection refused */ -#undef EHOSTDOWN -#define EHOSTDOWN 112 /* Host is down */ -#undef EHOSTUNREACH -#define EHOSTUNREACH 113 /* No route to host */ -#undef EALREADY -#define EALREADY 114 /* Operation already in progress */ -#undef EINPROGRESS -#define EINPROGRESS 115 /* Operation now in progress */ -#undef ESTALE -#define ESTALE 116 /* Stale NFS file handle */ -#undef EUCLEAN -#define EUCLEAN 117 /* Structure needs cleaning */ -#undef ENOTNAM -#define ENOTNAM 118 /* Not a XENIX named type file */ -#undef ENAVAIL -#define ENAVAIL 119 /* No XENIX semaphores available */ -#undef EISNAM -#define EISNAM 120 /* Is a named type file */ -#undef EREMOTEIO -#define EREMOTEIO 121 /* Remote I/O error */ -#undef EDQUOT -#define EDQUOT 122 /* Quota exceeded */ -#undef ENOMEDIUM -#define ENOMEDIUM 123 /* No medium found */ -#undef EMEDIUMTYPE -#define EMEDIUMTYPE 124 /* Wrong medium type */ -#undef ECANCELED -#define ECANCELED 125 /* Operation Canceled */ -#undef ENOKEY -#define ENOKEY 126 /* Required key not available */ -#undef EKEYEXPIRED -#define EKEYEXPIRED 127 /* Key has expired */ -#undef EKEYREVOKED -#define EKEYREVOKED 128 /* Key has been revoked */ -#undef EKEYREJECTED -#define EKEYREJECTED 129 /* Key was rejected by service */ -#undef EOWNERDEAD -#define EOWNERDEAD 130 /* Owner died */ -#undef ENOTRECOVERABLE -#define ENOTRECOVERABLE 131 /* State not recoverable */ - -/* Missing stat.h defines. - * The following are sys/stat.h definitions not currently present in the ARMCC - * errno.h. Note, ARMCC errno.h defines some symbol values differing from - * GCC_ARM/IAR/standard POSIX definitions. Guard against this and future - * changes by changing the symbol definition for filesystem use. - */ -#define _IFMT 0170000 //< type of file -#define _IFSOCK 0140000 //< socket -#define _IFLNK 0120000 //< symbolic link -#define _IFREG 0100000 //< regular -#define _IFBLK 0060000 //< block special -#define _IFDIR 0040000 //< directory -#define _IFCHR 0020000 //< character special -#define _IFIFO 0010000 //< fifo special - -#define S_IFMT _IFMT //< type of file -#define S_IFSOCK _IFSOCK //< socket -#define S_IFLNK _IFLNK //< symbolic link -#define S_IFREG _IFREG //< regular -#define S_IFBLK _IFBLK //< block special -#define S_IFDIR _IFDIR //< directory -#define S_IFCHR _IFCHR //< character special -#define S_IFIFO _IFIFO //< fifo special - -#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) -#define S_IRUSR 0000400 ///< read permission, owner -#define S_IWUSR 0000200 ///< write permission, owner -#define S_IXUSR 0000100 ///< execute/search permission, owner -#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) -#define S_IRGRP 0000040 ///< read permission, group -#define S_IWGRP 0000020 ///< write permission, group -#define S_IXGRP 0000010 ///< execute/search permission, group -#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) -#define S_IROTH 0000004 ///< read permission, other -#define S_IWOTH 0000002 ///< write permission, other -#define S_IXOTH 0000001 ///< execute/search permission, other - -#ifndef HAVE_SYS_STAT_H - -/* Refer to sys/stat standard - * Note: Not all fields may be supported by the underlying filesystem - */ -struct stat { - dev_t st_dev; ///< Device ID containing file - ino_t st_ino; ///< File serial number - mode_t st_mode; ///< Mode of file - nlink_t st_nlink; ///< Number of links to file - - uid_t st_uid; ///< User ID - gid_t st_gid; ///< Group ID - - off_t st_size; ///< Size of file in bytes - - time_t st_atime; ///< Time of last access - time_t st_mtime; ///< Time of last data modification - time_t st_ctime; ///< Time of last status change -}; - -#endif - -struct statvfs { - unsigned long f_bsize; ///< Filesystem block size - unsigned long f_frsize; ///< Fragment size (block size) - - fsblkcnt_t f_blocks; ///< Number of blocks - fsblkcnt_t f_bfree; ///< Number of free blocks - fsblkcnt_t f_bavail; ///< Number of free blocks for unprivileged users - - unsigned long f_fsid; ///< Filesystem ID - - unsigned long f_namemax; ///< Maximum filename length -}; - -/* The following are dirent.h definitions are declared here to guarantee - * consistency where structure may be different with different toolchains - */ -struct dirent { - char d_name[NAME_MAX + 1]; ///< Name of file - uint8_t d_type; ///< Type of file -}; - -enum { - DT_UNKNOWN, ///< The file type could not be determined. - DT_FIFO, ///< This is a named pipe (FIFO). - DT_CHR, ///< This is a character device. - DT_DIR, ///< This is a directory. - DT_BLK, ///< This is a block device. - DT_REG, ///< This is a regular file. - DT_LNK, ///< This is a symbolic link. - DT_SOCK, ///< This is a UNIX domain socket. -}; - -/* fcntl.h defines */ -#define F_GETFL 3 -#define F_SETFL 4 - -struct pollfd { - int fd; - short events; - short revents; -}; - -/* POSIX-compatible I/O functions */ -#if __cplusplus -extern "C" { -#endif -#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY - int open(const char *path, int oflag, ...); -#ifndef __IAR_SYSTEMS_ICC__ /* IAR provides fdopen itself */ -#if __cplusplus - std::FILE *fdopen(int fildes, const char *mode); -#else - FILE *fdopen(int fildes, const char *mode); -#endif -#endif -#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY - ssize_t write(int fildes, const void *buf, size_t nbyte); - ssize_t read(int fildes, void *buf, size_t nbyte); - int fsync(int fildes); - int isatty(int fildes); -#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY - off_t lseek(int fildes, off_t offset, int whence); - int ftruncate(int fildes, off_t length); - int fstat(int fildes, struct stat *st); - int fcntl(int fildes, int cmd, ...); - int poll(struct pollfd fds[], nfds_t nfds, int timeout); - int close(int fildes); - int stat(const char *path, struct stat *st); - int statvfs(const char *path, struct statvfs *buf); - DIR *opendir(const char *); - struct dirent *readdir(DIR *); - int closedir(DIR *); - void rewinddir(DIR *); - long telldir(DIR *); - void seekdir(DIR *, long); - int mkdir(const char *name, mode_t n); -#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY -#if __cplusplus -} // extern "C" - -namespace mbed { -#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY -/** This call is an analogue to POSIX fdopen(). - * - * It associates a C stream to an already-opened FileHandle, to allow you to - * use C printf/scanf/fwrite etc. The provided FileHandle must remain open - - * it will be closed by the C library when fclose(FILE) is called. - * - * The net effect is fdopen(bind_to_fd(fh), mode), with error handling. - * - * @param fh a pointer to an opened FileHandle - * @param mode operation upon the file descriptor, e.g., "w+" - * - * @returns a pointer to FILE - */ -std::FILE *fdopen(mbed::FileHandle *fh, const char *mode); - -/** Bind an mbed FileHandle to a POSIX file descriptor - * - * This is similar to fdopen, but only operating at the POSIX layer - it - * associates a POSIX integer file descriptor with a FileHandle, to allow you - * to use POSIX read/write calls etc. The provided FileHandle must remain open - - * it will be closed when close(int) is called. - * - * @param fh a pointer to an opened FileHandle - * - * @return an integer file descriptor, or negative if no descriptors available - */ -int bind_to_fd(mbed::FileHandle *fh); - -#else -/** Targets may implement this to override how to write to the console. - * - * If the target has provided minimal_console_putc, this is called - * to give the target a chance to specify an alternative minimal console. - * - * If this is not provided, serial_putc will be used if - * `target.console-uart` is `true`, else there will not be an output. - * - * @param c The char to write - * @return The written char - */ -int minimal_console_putc(int c); - -/** Targets may implement this to override how to read from the console. - * - * If the target has provided minimal_console_getc, this is called - * to give the target a chance to specify an alternative minimal console. - * - * If this is not provided, serial_getc will be used if - * `target.console-uart` is `true`, else no input would be captured. - * - * @return The char read from the serial port - */ -int minimal_console_getc(); -#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY - -} // namespace mbed - -#endif // __cplusplus - -/**@}*/ - -/**@}*/ - -#endif /* RETARGET_H */ diff --git a/platform/mbed_rtc_time.h b/platform/mbed_rtc_time.h deleted file mode 100644 index f85796b..0000000 --- a/platform/mbed_rtc_time.h +++ /dev/null @@ -1,136 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_RTC_TIME_H__ -#define __MBED_RTC_TIME_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_rtc_time rtc_time functions - * @{ - */ - -/* Timeval definition for non GCC_ARM toolchains */ -#if !defined(__GNUC__) || defined(__clang__) -struct timeval { - time_t tv_sec; - int32_t tv_usec; -}; -#endif - -/** Implementation of the C time.h functions - * - * Provides mechanisms to set and read the current time, based - * on the microcontroller Real-Time Clock (RTC), plus some - * standard C manipulation and formatting functions. - * - * Example: - * @code - * #include "mbed.h" - * - * int main() { - * set_time(1256729737); // Set RTC time to Wed, 28 Oct 2009 11:35:37 - * - * while (true) { - * time_t seconds = time(NULL); - * - * printf("Time as seconds since January 1, 1970 = %u\n", (unsigned int)seconds); - * - * printf("Time as a basic string = %s", ctime(&seconds)); - * - * char buffer[32]; - * strftime(buffer, 32, "%I:%M %p\n", localtime(&seconds)); - * printf("Time as a custom formatted string = %s", buffer); - * - * ThisThread::sleep_for(1000); - * } - * } - * @endcode - */ - -/** Set the current time - * - * 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). - * - * @param t Number of seconds since January 1, 1970 (the UNIX timestamp) - * - * @note Synchronization level: Thread safe - * - * Example: - * @code - * #include "mbed.h" - * - * int main() { - * set_time(1256729737); // Set time to Wed, 28 Oct 2009 11:35:37 - * } - * @endcode - */ -void set_time(time_t t); - -/** Attach an external RTC to be used for the C time functions - * - * @note Synchronization level: Thread safe - * - * @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 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)); - -/** Standard lib retarget, get time since Epoch - * - * @param tv Structure containing time_t seconds and useconds_t microseconds. Due to - * separate target specific RTC implementations only the seconds component is used. - * @param tz DEPRECATED IN THE STANDARD: This parameter is left in for legacy code. It is - * not used. - * @return 0 on success, -1 on a failure. - * @note Synchronization level: Thread safe - * - */ -int gettimeofday(struct timeval *tv, void *tz); - -/** Standard lib retarget, set time since Epoch - * - * @param tv Structure containing time_t seconds and useconds_t microseconds. Due to - * separate target specific RTC implementations only the seconds component is used. - * @param tz DEPRECATED IN THE STANDARD: This parameter is left in for legacy code. It is - * not used. - * @return Time in seconds on success, -1 on a failure. - * @note Synchronization level: Thread safe - * - */ -int settimeofday(const struct timeval *tv, const struct timezone *tz); - -#ifdef __cplusplus -} -#endif - -/** @}*/ -/** @}*/ - -#endif /* __MBED_RTC_TIME_H__ */ diff --git a/platform/mbed_semihost_api.h b/platform/mbed_semihost_api.h deleted file mode 100644 index 020e21a..0000000 --- a/platform/mbed_semihost_api.h +++ /dev/null @@ -1,98 +0,0 @@ - -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_SEMIHOST_H -#define MBED_SEMIHOST_H - -#include "device.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if DEVICE_SEMIHOST - -#if !defined(__ARMCC_VERSION) - -#if defined(__ICCARM__) -static inline int __semihost(int reason, const void *arg) -{ - return __semihosting(reason, (void *)arg); -} -#else - -#ifdef __thumb__ -# define AngelSWI 0xAB -# define AngelSWIInsn "bkpt" -# define AngelSWIAsm bkpt -#else -# define AngelSWI 0x123456 -# define AngelSWIInsn "swi" -# define AngelSWIAsm swi -#endif - -static inline int __semihost(int reason, const void *arg) -{ - int value; - - asm volatile( - "mov r0, %1" "\n\t" - "mov r1, %2" "\n\t" - AngelSWIInsn " %a3" "\n\t" - "mov %0, r0" - : "=r"(value) /* output operands */ - : "r"(reason), "r"(arg), "i"(AngelSWI) /* input operands */ - : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc" /* list of clobbered registers */ - ); - - return value; -} -#endif -#endif - -#if DEVICE_LOCALFILESYSTEM -FILEHANDLE semihost_open(const char *name, int openmode); -int semihost_close(FILEHANDLE fh); -int semihost_read(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode); -int semihost_write(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode); -int semihost_ensure(FILEHANDLE fh); -long semihost_flen(FILEHANDLE fh); -int semihost_seek(FILEHANDLE fh, long position); -int semihost_istty(FILEHANDLE fh); - -int semihost_remove(const char *name); -int semihost_rename(const char *old_name, const char *new_name); -#endif - -int semihost_uid(char *uid); -int semihost_reset(void); -int semihost_vbus(void); -int semihost_powerdown(void); -int semihost_exit(void); - -int semihost_connected(void); -int semihost_disabledebug(void); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif - - diff --git a/platform/mbed_stats.h b/platform/mbed_stats.h deleted file mode 100644 index f331c65..0000000 --- a/platform/mbed_stats.h +++ /dev/null @@ -1,185 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2016-2019 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_STATS_H -#define MBED_STATS_H -#include -#include -#include "hal/ticker_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_stats stats functions - * @{ - */ - -#ifdef MBED_ALL_STATS_ENABLED - -#ifndef MBED_SYS_STATS_ENABLED -#define MBED_SYS_STATS_ENABLED 1 -#endif -#ifndef MBED_STACK_STATS_ENABLED -#define MBED_STACK_STATS_ENABLED 1 -#endif -#ifndef MBED_CPU_STATS_ENABLED -#define MBED_CPU_STATS_ENABLED 1 -#endif -#ifndef MBED_HEAP_STATS_ENABLED -#define MBED_HEAP_STATS_ENABLED 1 -#endif -#ifndef MBED_THREAD_STATS_ENABLED -#define MBED_THREAD_STATS_ENABLED 1 -#endif - -#endif // MBED_ALL_STATS_ENABLED - -/** Maximum memory regions reported by mbed-os memory statistics */ -#define MBED_MAX_MEM_REGIONS 4 - -/** - * struct mbed_stats_heap_t definition - */ -typedef struct { - 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 the heap statistics. - * - * @param stats A pointer to the mbed_stats_heap_t structure to fill - */ -void mbed_stats_heap_get(mbed_stats_heap_t *stats); - -/** - * struct mbed_stats_stack_t definition - */ -typedef struct { - 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 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 - */ -void mbed_stats_stack_get(mbed_stats_stack_t *stats); - -/** - * 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. - * 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); - -/** - * struct mbed_stats_cpu_t definition - */ -typedef struct { - 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; - -/** - * Fill the passed in CPU stat structure with CPU statistics. - * - * @param stats A pointer to the mbed_stats_cpu_t structure to fill - */ -void mbed_stats_cpu_get(mbed_stats_cpu_t *stats); - -/** - * struct mbed_stats_thread_t definition - */ -typedef struct { - 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 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. - * 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); - -/** - * enum mbed_compiler_id_t definition - */ -typedef enum { - ARM = 1, /**< ARM */ - GCC_ARM, /**< GNU ARM */ - IAR /**< IAR */ -} mbed_compiler_id_t; - -/** - * struct mbed_stats_sys_t definition - */ -typedef struct { - 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 */ - uint32_t ram_start[MBED_MAX_MEM_REGIONS]; /**< Start addresses of all internal RAM memories */ - uint32_t ram_size[MBED_MAX_MEM_REGIONS]; /**< Size of all internal RAM memories in target */ - uint32_t rom_start[MBED_MAX_MEM_REGIONS]; /**< Start addresses of all internal ROM memories */ - uint32_t rom_size[MBED_MAX_MEM_REGIONS]; /**< Size of all internal ROM memories in target */ -} mbed_stats_sys_t; - -/** - * Fill the passed in system stat structure with system statistics. - * - * @param stats A pointer to the mbed_stats_sys_t structure to fill - */ -void mbed_stats_sys_get(mbed_stats_sys_t *stats); - -#ifdef __cplusplus -} -#endif - -#endif - -/** @}*/ - -/** @}*/ diff --git a/platform/mbed_thread.h b/platform/mbed_thread.h deleted file mode 100644 index 8b9fff1..0000000 --- a/platform/mbed_thread.h +++ /dev/null @@ -1,75 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2019 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_THREAD_H -#define MBED_THREAD_H -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \defgroup mbed_thread Mbed Thread - * \ingroup platform-public-api - * @{ - */ - -/** Generic thread functions. - * - * These are C versions of functions provided in C++ via rtos::Thread and rtos::ThisThread - */ - -/** Read the current RTOS kernel millisecond tick count. - 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 In a non-RTOS build, this computes an equivalent time in milliseconds, - based on a HAL timer. The time may be referenced as 0 on first call. - @note You cannot call this function from ISR context. - @note The equivalent functionality is accessible in C++ via rtos::Kernel::get_ms_count. - */ -uint64_t get_ms_count(void); - -/** Sleep for a specified time period in millisec: - @param millisec time delay value - @note You cannot call this function from ISR context. - @note The equivalent functionality is accessible in C++ via rtos::ThisThread::sleep_for. -*/ -void thread_sleep_for(uint32_t millisec); - -/** Sleep until a specified time in millisec - The specified time is according to Kernel::get_ms_count(). - @param millisec absolute time in millisec - @note You cannot call this function from ISR context. - @note if millisec is equal to or lower than the current tick count, this - returns immediately. - @note The equivalent functionality is accessible in C++ via ThisThread::sleep_until. -*/ -void thread_sleep_until(uint64_t millisec); - -/** @}*/ - -#ifdef __cplusplus -} -#endif - - -#endif //MBED_THREAD_H diff --git a/platform/mbed_toolchain.h b/platform/mbed_toolchain.h deleted file mode 100644 index 2fa91d6..0000000 --- a/platform/mbed_toolchain.h +++ /dev/null @@ -1,562 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_TOOLCHAIN_H -#define MBED_TOOLCHAIN_H - -#include "platform/mbed_preprocessor.h" - -/* Workaround to prevent GCC library defining error_t, which can collide */ -#ifndef __error_t_defined -#define __error_t_defined 1 -#endif - -/* Work around ARM Compiler 6 bug - assert does not work in constexpr - * functions unless you stop it from using its __promise built-in. - */ -#ifdef __ARMCC_VERSION -#ifndef __DO_NOT_LINK_PROMISE_WITH_ASSERT -#define __DO_NOT_LINK_PROMISE_WITH_ASSERT -#endif -#endif - -// Warning for unsupported compilers -#if !defined(__GNUC__) /* GCC */ \ - && !defined(__clang__) /* LLVM/Clang */ \ - && !defined(__ICCARM__) /* IAR */ -#warning "This compiler is not yet supported." -#endif - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_toolchain Toolchain functions - * @{ - */ - -// Attributes - -/** MBED_PACKED - * Pack a structure, preventing any padding from being added between fields. - * - * @code - * #include "mbed_toolchain.h" - * - * MBED_PACKED(struct) foo { - * char x; - * int y; - * }; - * @endcode - */ -#ifndef MBED_PACKED -#if defined(__ICCARM__) -#define MBED_PACKED(struct) __packed struct -#else -#define MBED_PACKED(struct) struct __attribute__((packed)) -#endif -#endif - -/** MBED_ALIGN(N) - * Declare a variable to be aligned on an N-byte boundary. - * - * @note - * IAR does not support alignment greater than word size on the stack - * - * @code - * #include "mbed_toolchain.h" - * - * MBED_ALIGN(16) char a; - * @endcode - */ -#ifndef MBED_ALIGN -#if __cplusplus >= 201103 -#define MBED_ALIGN(N) alignas(N) -#elif __STDC_VERSION__ >= 201112 -#define MBED_ALIGN(N) _Alignas(N) -#elif defined(__ICCARM__) -#define MBED_ALIGN(N) _Pragma(MBED_STRINGIFY(data_alignment=N)) -#else -#define MBED_ALIGN(N) __attribute__((aligned(N))) -#endif -#endif - -/** MBED_UNUSED - * Declare a function argument to be unused, suppressing compiler warnings - * - * @code - * #include "mbed_toolchain.h" - * - * void foo(MBED_UNUSED int arg) { - * - * } - * @endcode - */ -#ifndef MBED_UNUSED -#if defined(__GNUC__) || defined(__clang__) -#define MBED_UNUSED __attribute__((__unused__)) -#else -#define MBED_UNUSED -#endif -#endif - -/** MBED_USED - * Inform the compiler that a static variable is to be retained in the object file, even if it is unreferenced. - * - * @code - * #include "mbed_toolchain.h" - * - * MBED_USED int foo; - * - * @endcode - */ -#ifndef MBED_USED -#if defined(__GNUC__) || defined(__clang__) -#define MBED_USED __attribute__((used)) -#elif defined(__ICCARM__) -#define MBED_USED __root -#else -#define MBED_USED -#endif -#endif - -/** MBED_WEAK - * Mark a function as being weak. - * - * @note - * Functions should only be marked as weak in the source file. The header file - * should contain a regular function declaration to insure the function is emitted. - * A function marked weak will not be emitted if an alternative non-weak - * implementation is defined. - * - * @note - * Weak functions are not friendly to making code re-usable, as they can only - * be overridden once (and if they are multiply overridden the linker will emit - * no warning). You should not normally use weak symbols as part of the API to - * re-usable modules. - * - * @code - * #include "mbed_toolchain.h" - * - * MBED_WEAK void foo() { - * // a weak implementation of foo that can be overriden by a definition - * // without __weak - * } - * @endcode - */ -#ifndef MBED_WEAK -#if defined(__ICCARM__) -#define MBED_WEAK __weak -#elif defined(__MINGW32__) -#define MBED_WEAK -#else -#define MBED_WEAK __attribute__((weak)) -#endif -#endif - -/** MBED_COMPILER_BARRIER - * Stop the compiler moving memory accesses. - * - * The barrier stops memory accesses from being moved from one side of the - * barrier to the other for safety against other threads and interrupts. - * - * This macro should only be used if we know only one CPU is accessing the data, - * or we are otherwise synchronising CPUs via acquire/release instructions. - * Otherwise, use MBED_BARRIER, which will act as a compiler barrier and also - * a CPU barrier if necessary. - * - * @internal - * This is not for use by normal code - it is a building block for the - * higher-level functions in mbed_critical.h. Higher-level lock/unlock or - * acquire/release APIs always provide ordering semantics, using this if - * necessary. - * - * @code - * #include "mbed_toolchain.h" - * - * void atomic_flag_clear_armv8(atomic_flag *flagPtr) - * { - * // ARMv8 LDA and STL instructions provide sequential consistency against - * // other CPUs, so no CPU barrier is needed. But we still need compiler - * // barriers to give us sequentially-consistent release semantics with - * // respect to compiler reordering - __STLB does not currently - * // include this. - * MBED_COMPILER_BARRIER(); - * __STLB(&flagPtr->_flag, false); - * MBED_COMPILER_BARRIER(); - * } - */ -#if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__) -#define MBED_COMPILER_BARRIER() asm volatile("" : : : "memory") -#else -#error "Missing MBED_COMPILER_BARRIER implementation" -#endif - -/** MBED_BARRIER - * Stop the compiler, and CPU if SMP, from moving memory accesses. - * - * The barrier stops memory accesses from being moved from one side of the - * barrier to the other for safety against other threads and interrupts, - * potentially on other CPUs. - * - * In a single-CPU system, this is just a compiler barrier. - * If we supported multiple CPUs, this would be a DMB (with implied compiler - * barrier). - * - * @internal - * This is not for use by normal code - it is a building block for the - * higher-level functions in mbed_critical.h. Higher-level lock/unlock or - * acquire/release APIs always provide ordering semantics, using this if - * necessary. - * @code - * #include "mbed_toolchain.h" - * - * void atomic_flag_clear_armv7(atomic_flag *flagPtr) - * { - * // ARMv7 LDR and STR instructions do not provide any ordering - * // consistency against other CPUs, so explicit barrier DMBs are needed - * // for a multi-CPU system, otherwise just compiler barriers for single-CPU. - * MBED_BARRIER(); - * flagPtr->_flag = false; - * MBED_BARRIER(); - * } - */ -#define MBED_BARRIER() MBED_COMPILER_BARRIER() - -/** MBED_PURE - * Hint to the compiler that a function depends only on parameters - * - * @code - * #include "mbed_toolchain.h" - * - * MBED_PURE int foo(int arg){ - * // no access to global variables - * } - * @endcode - */ -#ifndef MBED_PURE -#if defined(__GNUC__) || defined(__clang__) -#define MBED_PURE __attribute__((const)) -#else -#define MBED_PURE -#endif -#endif - -/** MBED_NOINLINE - * Declare a function that must not be inlined. - * - * @code - * #include "mbed_toolchain.h" - * - * MBED_NOINLINE void foo() { - * - * } - * @endcode - */ -#ifndef MBED_NOINLINE -#if defined(__GNUC__) || defined(__clang__) -#define MBED_NOINLINE __attribute__((noinline)) -#elif defined(__ICCARM__) -#define MBED_NOINLINE _Pragma("inline=never") -#else -#define MBED_NOINLINE -#endif -#endif - -/** MBED_FORCEINLINE - * Declare a function that must always be inlined. Failure to inline - * such a function will result in an error. - * - * @code - * #include "mbed_toolchain.h" - * - * MBED_FORCEINLINE void foo() { - * - * } - * @endcode - */ -#ifndef MBED_FORCEINLINE -#if defined(__GNUC__) || defined(__clang__) -#define MBED_FORCEINLINE inline __attribute__((always_inline)) -#elif defined(__ICCARM__) -#define MBED_FORCEINLINE _Pragma("inline=forced") -#else -#define MBED_FORCEINLINE inline -#endif -#endif - -/** MBED_NORETURN - * Declare a function that will never return. - * - * @code - * #include "mbed_toolchain.h" - * - * MBED_NORETURN void foo() { - * // must never return - * while (1) {} - * } - * @endcode - */ -#ifndef MBED_NORETURN -#if __cplusplus >= 201103 -#define MBED_NORETURN [[noreturn]] -#elif __STDC_VERSION__ >= 201112 -#define MBED_NORETURN _Noreturn -#elif defined(__GNUC__) || defined(__clang__) -#define MBED_NORETURN __attribute__((noreturn)) -#elif defined(__ICCARM__) -#define MBED_NORETURN __noreturn -#else -#define MBED_NORETURN -#endif -#endif - -/** MBED_UNREACHABLE - * An unreachable statement. If the statement is reached, - * behavior is undefined. Useful in situations where the compiler - * cannot deduce if the code is unreachable. - * - * @code - * #include "mbed_toolchain.h" - * - * void foo(int arg) { - * switch (arg) { - * case 1: return 1; - * case 2: return 2; - * ... - * } - * MBED_UNREACHABLE; - * } - * @endcode - */ -#ifndef MBED_UNREACHABLE -#if (defined(__GNUC__) || defined(__clang__)) -#define MBED_UNREACHABLE __builtin_unreachable() -#else -#define MBED_UNREACHABLE while (1) -#endif -#endif - -/** MBED_FALLTHROUGH - * Marks a point in a switch statement where fallthrough can occur. - * Should be placed as the last statement before a label. - * - * @code - * #include "mbed_toolchain.h" - * - * int foo(int arg) { - * switch (arg) { - * case 1: - * case 2: - * case 3: - * arg *= 2; - * MBED_FALLTHROUGH; - * default: - * return arg; - * } - * } - * @endcode - */ -#ifndef MBED_FALLTHROUGH -#if __cplusplus >= 201703 -#define MBED_FALLTHROUGH [[fallthrough]] -#elif defined(__clang__) -#if __cplusplus >= 201103 -#define MBED_FALLTHROUGH [[clang::fallthrough]] -#elif __has_attribute(fallthrough) -#define MBED_FALLTHROUGH __attribute__((fallthrough)) -#else -#define MBED_FALLTHROUGH -#endif -#elif defined (__GNUC__) -#define MBED_FALLTHROUGH __attribute__((fallthrough)) -#else -#define MBED_FALLTHROUGH -#endif -#endif - -/** MBED_DEPRECATED("message string") - * Mark a function declaration as deprecated, if it used then a warning will be - * issued by the compiler possibly including the provided message. Note that not - * all compilers are able to display the message. - * - * @code - * #include "mbed_toolchain.h" - * - * MBED_DEPRECATED("don't foo any more, bar instead") - * void foo(int arg); - * @endcode - */ -#ifndef MBED_DEPRECATED -#if defined(__GNUC__) || defined(__clang__) -#define MBED_DEPRECATED(M) __attribute__((deprecated(M))) -#else -#define MBED_DEPRECATED(M) -#endif -#endif - -/** MBED_DEPRECATED_SINCE("version", "message string") - * Mark a function declaration as deprecated, noting that the declaration was - * deprecated on the specified version. If the function is used then a warning - * will be issued by the compiler possibly including the provided message. - * Note that not all compilers are able to display this message. - * - * @code - * #include "mbed_toolchain.h" - * - * MBED_DEPRECATED_SINCE("mbed-os-5.1", "don't foo any more, bar instead") - * void foo(int arg); - * @endcode - */ -#define MBED_DEPRECATED_SINCE(D, M) MBED_DEPRECATED(M " [since " D "]") - -/** MBED_CALLER_ADDR() - * Returns the caller of the current function. - * - * @note - * This macro is only implemented for GCC and ARMCC. - * - * @code - * #include "mbed_toolchain.h" - * - * printf("This function was called from %p", MBED_CALLER_ADDR()); - * @endcode - * - * @return Address of the calling function - */ -#ifndef MBED_CALLER_ADDR -#if (defined(__GNUC__) || defined(__clang__)) -#define MBED_CALLER_ADDR() __builtin_extract_return_addr(__builtin_return_address(0)) -#else -#define MBED_CALLER_ADDR() (NULL) -#endif -#endif - -#ifndef MBED_SECTION -#if (defined(__GNUC__) || defined(__clang__)) -#define MBED_SECTION(name) __attribute__ ((section (name))) -#elif defined(__ICCARM__) -#define MBED_SECTION(name) _Pragma(MBED_STRINGIFY(location=name)) -#else -#error "Missing MBED_SECTION directive" -#endif -#endif - -/** - * Macro expanding to a string literal of the enclosing function name. - * - * The string returned takes into account language specificity and yield human - * readable content. - * - * As an example, if the macro is used within a C++ function then the string - * literal containing the function name will contain the complete signature of - * the function - including template parameters - and namespace qualifications. - */ -#ifndef MBED_PRETTY_FUNCTION -#define MBED_PRETTY_FUNCTION __PRETTY_FUNCTION__ -#endif - -#ifndef MBED_PRINTF -#if defined(__GNUC__) -#define MBED_PRINTF(format_idx, first_param_idx) __attribute__ ((__format__(__printf__, format_idx, first_param_idx))) -#else -#define MBED_PRINTF(format_idx, first_param_idx) -#endif -#endif - -#ifndef MBED_PRINTF_METHOD -#if defined(__GNUC__) -#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 -#endif - -#ifndef MBED_SCANF -#if defined(__GNUC__) -#define MBED_SCANF(format_idx, first_param_idx) __attribute__ ((__format__(__scanf__, format_idx, first_param_idx))) -#else -#define MBED_SCANF(format_idx, first_param_idx) -#endif -#endif - -#ifndef MBED_SCANF_METHOD -#if defined(__GNUC__) -#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 -#endif - -// Macro containing the filename part of the value of __FILE__. Defined as -// string literal. -#ifndef MBED_FILENAME -#if defined(__GNUC__) -#define MBED_FILENAME (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __builtin_strrchr(__FILE__, '\\') ? __builtin_strrchr(__FILE__, '\\') + 1 : __FILE__) -#elif defined(__ICCARM__) -#define MBED_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) -#else -#define MBED_FILENAME __FILE__ -#endif -#endif // #ifndef MBED_FILENAME - -// FILEHANDLE declaration -#if defined(TOOLCHAIN_ARM) -#include -#endif - -#ifndef FILEHANDLE -typedef int FILEHANDLE; -#endif - -// Backwards compatibility -#ifndef WEAK -#define WEAK MBED_WEAK -#endif - -#ifndef PACKED -#define PACKED MBED_PACKED() -#endif - -#ifndef EXTERN -#define EXTERN extern -#endif - -/** MBED_NONSECURE_ENTRY - * Declare a function that can be called from non-secure world or secure world - * - * @code - * #include "mbed_toolchain.h" - * - * MBED_NONSECURE_ENTRY void foo() { - * - * } - * @endcode - */ -#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3L) -#if defined (__ICCARM__) -#define MBED_NONSECURE_ENTRY __cmse_nonsecure_entry -#else -#define MBED_NONSECURE_ENTRY __attribute__((cmse_nonsecure_entry)) -#endif -#else -#define MBED_NONSECURE_ENTRY -#endif - -#endif - -/** @}*/ -/** @}*/ diff --git a/platform/mbed_version.h b/platform/mbed_version.h deleted file mode 100644 index 4eb8703..0000000 --- a/platform/mbed_version.h +++ /dev/null @@ -1,73 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018-2019 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_VERSION_H -#define MBED_VERSION_H - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_version Version macros - * @{ - */ - -/** MBED_MAJOR_VERSION - * Mbed OS major version - * - * @note 99 is default value for development version (master branch) - */ -#define MBED_MAJOR_VERSION 6 - -/** MBED_MINOR_VERSION - * Mbed OS minor version - * - * @note 99 is default value for development version (master branch) - */ -#define MBED_MINOR_VERSION 2 - -/** MBED_PATCH_VERSION - * Mbed OS patch version - * - * @note 99 is default value for development version (master branch) - */ -#define MBED_PATCH_VERSION 0 - -#define MBED_ENCODE_VERSION(major, minor, patch) ((major)*10000 + (minor)*100 + (patch)) - -/** MBED_VERSION - * Mbed OS 5 version (MMmmpp - M(Major); m(minor); p(patch)) - * - * @note 999999 is default value for development version (master branch) - */ -#define MBED_VERSION MBED_ENCODE_VERSION(MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION) - -/** MBED_VERSION_CHECK - * Macro can be used to check minimum Mbed OS version required for feature/library. If current version - * is less than required, it will assert. - * - * @note: Version of master branch will be 999999 as default, hence no assert/warning is provided for - * master branch code - */ -#define MBED_VERSION_CHECK(major, minor, patch) do { \ - MBED_STATIC_ASSERT((MBED_VERSION >= MBED_ENCODE_VERSION((major),(minor),(patch))), "Incompatible mbed-os version detected!!"); \ - } while(0) - -#endif - -/** @}*/ -/** @}*/ diff --git a/platform/mbed_wait_api.h b/platform/mbed_wait_api.h deleted file mode 100644 index a6f85be..0000000 --- a/platform/mbed_wait_api.h +++ /dev/null @@ -1,156 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2019 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_WAIT_API_H -#define MBED_WAIT_API_H - -#include "platform/mbed_toolchain.h" -#include "platform/mbed_atomic.h" -#include "device.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup platform-public-api */ -/** @{*/ - -/** - * \defgroup platform_wait_api wait_api functions - * @{ - */ - -/** Generic wait functions. - * - * These provide simple NOP type wait capabilities. - * - * Example: - * @code - * #include "mbed.h" - * - * // Blinking rate in milliseconds - * #define BLINKING_RATE_MS 500 - * DigitalOut led(LED2); - * InterruptIn button(SW2); - * - * void blink_led() { - * led = 1; - * wait_us(BLINKING_RATE_MS * 1000); - * led = 0; - * } - * - * int main() { - * button.fall(&blink_led); - * while(1) { - * // Do nothing - * } - * } - * @endcode - */ - -/** Waits a number of microseconds. - * - * @param us the whole number of microseconds to wait - * - * @note - * This function always spins to get the exact number of microseconds. - * This will affect power and multithread performance. Therefore, spinning for - * millisecond wait is not recommended, and ThisThread::sleep_for should - * be used instead. - * - * @note You may call this function from ISR context, but large delays may - * impact system stability - interrupt handlers should take less than - * 50us. - */ -void wait_us(int us); - -/** Waits a number of nanoseconds. - * - * This function spins the CPU to produce a small delay. It should normally - * only be used for delays of 10us (10000ns) or less. As it is calculated - * based on the expected execution time of a software loop, it may well run - * slower than requested based on activity from other threads and interrupts. - * If greater precision is required, this can be called from inside a critical - * section. - * - * @param ns the number of nanoseconds to wait - * - * @note - * wait_us() will likely give more precise time than wait_ns for large-enough - * delays, as it is based on a timer, but its set-up time may be excessive - * for the smallest microsecond counts, at which point wait_ns() is better. - * - * @note - * Any delay larger than a millisecond (1000000ns) is liable to cause - * overflow in the internal loop calculation. You shouldn't normally be - * using this for such large delays anyway in real code, but be aware if - * calibrating. Make repeated calls for longer test runs. - * - * @note You may call this function from ISR context. - * - */ -void wait_ns(unsigned int ns); - -/* Optimize if we know the rate */ -#if DEVICE_USTICKER && defined US_TICKER_PERIOD_NUM -void _wait_us_ticks(uint32_t ticks); -void _wait_us_generic(unsigned int us); - -/* Further optimization if we know us_ticker is always running */ -#if MBED_CONF_TARGET_INIT_US_TICKER_AT_BOOT -#define _us_ticker_is_initialized true -#else -extern bool _us_ticker_initialized; -#define _us_ticker_is_initialized core_util_atomic_load_bool(&_us_ticker_initialized) -#endif - -#if US_TICKER_PERIOD_DEN == 1 && (US_TICKER_MASK * US_TICKER_PERIOD_NUM) >= 0xFFFFFFFF -/* Ticker is wide and slow enough to have full 32-bit range - can always use it directly */ -#define _us_is_small_enough(us) true -#else -/* Threshold is determined by specification of us_ticker_api.h - smallest possible - * time range for the us_ticker is 16-bit 8MHz, which gives 8192us. This also leaves - * headroom for the multiplication in 32 bits. - */ -#define _us_is_small_enough(us) ((us) < 8192) -#endif - -/* Speed optimisation for small wait_us. Care taken to preserve binary compatibility */ -inline void _wait_us_inline(unsigned int us) -{ - /* Threshold is determined by specification of us_ticker_api.h - smallest possible - * time range for the us_ticker is 16-bit 8MHz, which gives 8192us. This also leaves - * headroom for the multiplication in 32 bits. - */ - if (_us_is_small_enough(us) && _us_ticker_is_initialized) { - const uint32_t ticks = ((us * US_TICKER_PERIOD_DEN) + US_TICKER_PERIOD_NUM - 1) / US_TICKER_PERIOD_NUM; - _wait_us_ticks(ticks); - } else { - _wait_us_generic(us); - } -} - -#define wait_us(us) _wait_us_inline(us) -#endif // Known-rate, initialised timer - -#ifdef __cplusplus -} -#endif - -#endif - -/** @}*/ -/** @}*/ diff --git a/platform/platform.h b/platform/platform.h deleted file mode 100644 index 3268c7c..0000000 --- a/platform/platform.h +++ /dev/null @@ -1,36 +0,0 @@ - -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 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_PLATFORM_H -#define MBED_PLATFORM_H - -#include -#include -#include -#include - -#include "platform/mbed_retarget.h" -#include "platform/mbed_toolchain.h" -#include "device.h" -#include "PinNames.h" -#include "PeripheralNames.h" - -/** \defgroup platform-public-api Platform - * \ingroup mbed-os-public - */ - -#endif diff --git a/platform/tests/.mbedignore b/platform/tests/.mbedignore new file mode 100644 index 0000000..979080d --- /dev/null +++ b/platform/tests/.mbedignore @@ -0,0 +1 @@ +UNITTESTS/* \ No newline at end of file diff --git a/platform/tests/TESTS/host_tests/crash_reporting.py b/platform/tests/TESTS/host_tests/crash_reporting.py new file mode 100644 index 0000000..45bf566 --- /dev/null +++ b/platform/tests/TESTS/host_tests/crash_reporting.py @@ -0,0 +1,74 @@ +""" +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. +""" +import time +from mbed_host_tests import BaseHostTest +from mbed_host_tests.host_tests_runner.host_test_default import DefaultTestSelector + +DEFAULT_CYCLE_PERIOD = 10.0 + +MSG_VALUE_DUMMY = '0' + +MSG_KEY_DEVICE_READY = 'crash_reporting_ready' +MSG_KEY_DEVICE_ERROR = 'crash_reporting_inject_error' +MSG_KEY_SYNC = '__sync' + +class CrashReportingTest(BaseHostTest): + """Test for the crash reporting feature. + """ + + def __init__(self): + super(CrashReportingTest, self).__init__() + self.reset = False + self.test_steps_sequence = self.test_steps() + # Advance the coroutine to it's first yield statement. + self.test_steps_sequence.send(None) + + def setup(self): + self.register_callback(MSG_KEY_DEVICE_READY, self.cb_device_ready) + + def cb_device_ready(self, key, value, timestamp): + """Acknowledge device rebooted correctly and feed the test execution + """ + self.reset = True + + try: + if self.test_steps_sequence.send(value): + self.notify_complete(True) + except (StopIteration, RuntimeError) as exc: + self.notify_complete(False) + + def test_steps(self): + """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 + + #Wait 2 seconds for system to init + time.sleep(7.0) + #self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY) + self.send_kv(MSG_KEY_DEVICE_ERROR, MSG_VALUE_DUMMY) + time.sleep(5.0) + + system_reset = yield + if self.reset == False: + raise RuntimeError('Platform did not auto-reboot as expected.') + + # The sequence is correct -- test passed. + yield True diff --git a/platform/tests/TESTS/host_tests/system_reset.py b/platform/tests/TESTS/host_tests/system_reset.py new file mode 100644 index 0000000..13d2309 --- /dev/null +++ b/platform/tests/TESTS/host_tests/system_reset.py @@ -0,0 +1,76 @@ +""" +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. +""" +import time +from mbed_host_tests import BaseHostTest +from mbed_host_tests.host_tests_runner.host_test_default import DefaultTestSelector + +DEFAULT_CYCLE_PERIOD = 1.0 + +MSG_VALUE_DUMMY = '0' + +MSG_KEY_DEVICE_READY = 'ready' +MSG_KEY_DEVICE_RESET = 'reset' +MSG_KEY_SYNC = '__sync' + +class SystemResetTest(BaseHostTest): + """Test for the system_reset API. + + Given a device running code + When the device is restarted using @a system_reset() + Then the device is restarted + """ + + def __init__(self): + super(SystemResetTest, self).__init__() + self.reset = False + self.test_steps_sequence = self.test_steps() + # Advance the coroutine to it's first yield statement. + self.test_steps_sequence.send(None) + + def setup(self): + self.register_callback(MSG_KEY_DEVICE_READY, self.cb_device_ready) + + def cb_device_ready(self, key, value, timestamp): + """Acknowledge device rebooted correctly and feed the test execution + """ + self.reset = True + + try: + if self.test_steps_sequence.send(value): + self.notify_complete(True) + except (StopIteration, RuntimeError) as exc: + self.notify_complete(False) + + def test_steps(self): + """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(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 diff --git a/platform/tests/TESTS/mbed_platform/CircularBuffer/main.cpp b/platform/tests/TESTS/mbed_platform/CircularBuffer/main.cpp new file mode 100644 index 0000000..74c4816 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/CircularBuffer/main.cpp @@ -0,0 +1,502 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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 "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" + +#include "mbed.h" + +using namespace utest::v1; + +/* Structure for complex type. */ +typedef struct { + int a; + char b; + int c; +} COMPLEX_TYPE; + +/* Function to check if complex type object holds specified values.*/ +bool comp_is_equal(COMPLEX_TYPE *object, int a, char b, int c) +{ + if (object->a == a && object->b == b && object->c == c) { + return true; + } + + return false; +} + +/* Function to set complex type object fields.*/ +void comp_set(COMPLEX_TYPE *object, int a, char b, int c) +{ + object->a = a; + object->b = b; + object->c = c; +} + +/* Test circular buffer - input does not exceed capacity. + * + * Given is a circular buffer with the capacity equal to N (BufferSize). + * When circular buffer is filled with N elements. + * Then all elements are read from the circular buffer in the FIFO order. + * + */ +template +void test_input_does_not_exceed_capacity_push_max_pop_max() +{ + CircularBuffer cb; + T data = 0; + + for (uint32_t i = 0; i < BufferSize; i++) { + data = (0xAA + i); + cb.push(data); + TEST_ASSERT_EQUAL(i + 1, cb.size()); + } + + for (uint32_t i = 0; i < BufferSize; i++) { + TEST_ASSERT_TRUE(cb.pop(data)); + TEST_ASSERT_EQUAL(0xAA + i, data); + TEST_ASSERT_EQUAL(BufferSize - i - 1, cb.size()); + } +} + +/* Test circular buffer - input does not exceed capacity. + * + * Given is a circular buffer with the capacity equal to N (BufferSize). + * When circular buffer is filled as follows: (2 * N - 2) times 2 elements are pushed and 1 element is popped. + * Then all elements are read from the circular buffer in the FIFO order. + * + */ +template +void test_input_does_not_exceed_capacity_push_2_pop_1() +{ + CircularBuffer cb; + static const int num_of_elem_push = (2 * BufferSize - 2); + T push_buffer = 0; + T pop_buffer = 0; + + /* Push 2 elements and pop one element in each cycle. */ + for (uint32_t i = 0; i < num_of_elem_push; i += 2) { + push_buffer = (0xAA + i); + cb.push(push_buffer); + push_buffer++; + cb.push(push_buffer); + TEST_ASSERT_EQUAL(i / 2 + 2, cb.size()); + + TEST_ASSERT_TRUE(cb.pop(pop_buffer)); + TEST_ASSERT_EQUAL(0xAA + i / 2, pop_buffer); + TEST_ASSERT_EQUAL(i / 2 + 1, cb.size()); + } + + /* Pop the rest. */ + for (uint32_t i = 0; i < (num_of_elem_push / 2); i++) { + TEST_ASSERT_TRUE(cb.pop(pop_buffer)); + TEST_ASSERT_EQUAL(0xAA + num_of_elem_push / 2 + i, pop_buffer); + TEST_ASSERT_EQUAL(num_of_elem_push / 2 - 1 - i, cb.size()); + + } +} + +/* Test circular buffer - input exceeds capacity. + * + * Given is a circular buffer with the capacity equal to N (BufferSize). + * When circular buffer is filled with N + 1 elements. + * Then first pushed element is lost (overwritten by the last element) and + * elements are read from the circular buffer in the FIFO order. + * + */ +template +void test_input_exceeds_capacity_push_max_plus_1_pop_max() +{ + CircularBuffer cb; + static const int num_of_elem_push = (BufferSize + 1); + T data = 0; + + for (uint32_t i = 0; i < num_of_elem_push; i++) { + data = (0xAA + i); + cb.push(data); + if (i < BufferSize) { + TEST_ASSERT_EQUAL(i + 1, cb.size()); + } else { + TEST_ASSERT_EQUAL(BufferSize, cb.size()); + } + + } + + for (uint32_t i = 0; i < (BufferSize - 1); i++) { + TEST_ASSERT_TRUE(cb.pop(data)); + TEST_ASSERT_EQUAL(0xAA + i + 1, data); + TEST_ASSERT_EQUAL(BufferSize - 1 - i, cb.size()); + } + + /* First element should be overwritten. */ + TEST_ASSERT_TRUE(cb.pop(data)); + TEST_ASSERT_EQUAL((0xAA + num_of_elem_push - 1), data); + TEST_ASSERT_EQUAL(0, cb.size()); +} + +/* Test circular buffer - input exceeds capacity. + * + * Given is a circular buffer with the capacity equal to N (BufferSize). + * When circular buffer is filled as follows: (2 * N) times 2 elements are pushed and 1 element is popped. + * Then first pushed element is lost (overwritten by the last element) and + * elements are read from the circular buffer in the FIFO order. + * + */ +template +void test_input_exceeds_capacity_push_2_pop_1() +{ + CircularBuffer cb; + static const int num_of_elem_push = (2 * BufferSize); + T push_buffer = 0; + T pop_buffer = 0; + + /* Push 2 elements and pop one element in each cycle. */ + for (uint32_t i = 0; i < num_of_elem_push; i += 2) { + push_buffer = (0xAA + i); + cb.push(push_buffer); + push_buffer++; + cb.push(push_buffer); + if ((i / 2 + 1) < BufferSize) { + TEST_ASSERT_EQUAL(i / 2 + 2, cb.size()); + } else { + TEST_ASSERT_EQUAL(BufferSize, cb.size()); + } + + TEST_ASSERT_TRUE(cb.pop(pop_buffer)); + if ((i / 2 + 1) < BufferSize) { + TEST_ASSERT_EQUAL(i / 2 + 1, cb.size()); + } else { + TEST_ASSERT_EQUAL(BufferSize - 1, cb.size()); + } + + /* First element has been overwritten. */ + if (i == (num_of_elem_push - 2)) { + TEST_ASSERT_EQUAL(0xAA + i / 2 + 1, pop_buffer); + } else { + TEST_ASSERT_EQUAL(0xAA + i / 2, pop_buffer); + } + } + + /* Pop the rest - one element has been overwritten. */ + for (uint32_t i = 0; i < (num_of_elem_push / 2 - 1); i++) { + TEST_ASSERT_TRUE(cb.pop(pop_buffer)); + TEST_ASSERT_EQUAL(0xAA + num_of_elem_push / 2 + i + 1, pop_buffer); + } +} + +/* Test circular buffer - input exceeds capacity (complex type). + * + * Given is a circular buffer with the capacity equal to N (BufferSize). + * When circular buffer is filled as follows: (2 * N) times 2 elements are pushed and 1 element is popped. + * Then first pushed element is lost (overwritten by the last element) and + * elements are read from the circular buffer in the FIFO order. + * + */ +template +void test_input_exceeds_capacity_push_2_pop_1_complex_type() +{ + CircularBuffer cb; + static const int num_of_elem_push = (2 * BufferSize); + COMPLEX_TYPE push_buffer = {0}; + COMPLEX_TYPE pop_buffer = {0}; + + /* Push 2 elements and pop one element in each cycle. */ + for (uint32_t i = 0; i < num_of_elem_push; i += 2) { + comp_set(&push_buffer, 0xAA + i, 0xBB + i, 0xCC + i); + cb.push(push_buffer); + comp_set(&push_buffer, 0xAA + i + 1, 0xBB + i + 1, 0xCC + i + 1); + cb.push(push_buffer); + if ((i / 2 + 1) < BufferSize) { + TEST_ASSERT_EQUAL(i / 2 + 2, cb.size()); + } else { + TEST_ASSERT_EQUAL(BufferSize, cb.size()); + } + + TEST_ASSERT_TRUE(cb.pop(pop_buffer)); + if ((i / 2 + 1) < BufferSize) { + TEST_ASSERT_EQUAL(i / 2 + 1, cb.size()); + } else { + TEST_ASSERT_EQUAL(BufferSize - 1, cb.size()); + } + + /* First element has been overwritten. */ + if (i == (num_of_elem_push - 2)) { + const bool result = comp_is_equal(&pop_buffer, 0xAA + 1 + i / 2, 0xBB + 1 + i / 2, 0xCC + 1 + i / 2); + TEST_ASSERT_TRUE(result); + } else { + const bool result = comp_is_equal(&pop_buffer, 0xAA + i / 2, 0xBB + i / 2, 0xCC + i / 2); + TEST_ASSERT_TRUE(result); + } + } + + /* Pop the rest - one element has been overwritten. */ + for (uint32_t i = 0; i < (num_of_elem_push / 2 - 1); i++) { + TEST_ASSERT_TRUE(cb.pop(pop_buffer)); + const bool result = comp_is_equal(&pop_buffer, 0xAA + num_of_elem_push / 2 + i + 1, + 0xBB + num_of_elem_push / 2 + i + 1, 0xCC + num_of_elem_push / 2 + i + 1); + TEST_ASSERT_TRUE(result); + } +} + +/* Test circular buffer - test pop(), peek(), empty(), full(), size() after CircularBuffer creation. + * + * Given is a circular buffer. + * When circular buffer is created. + * Then circular buffer is empty: + * - empty() returns true, + * - pop() function returns false, + * - peek() function returns false, + * - full() function returns false, + * - size() function returns 0, + * + */ +void test_pop_empty_full_size_after_creation() +{ + CircularBuffer cb; + int data = 0; + + TEST_ASSERT_TRUE(cb.empty()); + TEST_ASSERT_FALSE(cb.pop(data)); + TEST_ASSERT_FALSE(cb.peek(data)); + TEST_ASSERT_FALSE(cb.full()); + TEST_ASSERT_EQUAL(0, cb.size()); +} + +/* Test circular buffer - test empty() function. + * + * Given is a circular buffer with the capacity equal to N (BufferSize). + * When operations on circular buffer are performed (push, pop). + * Then empty() function returns true if buffer is empty, false otherwise. + * + */ +template +void test_empty() +{ + CircularBuffer cb; + T data = 0; + + /* Push max elements. */ + for (uint32_t i = 0; i < BufferSize; i++) { + cb.push(data); + TEST_ASSERT_FALSE(cb.empty()); + } + + /* Push next 2*BufferSize elements (overwrite entries). */ + for (uint32_t i = 0; i < (2 * BufferSize); i++) { + cb.push(data); + TEST_ASSERT_FALSE(cb.empty()); + } + + /* Pop (BufferSize - 1) elements (leave one). */ + for (uint32_t i = 0; i < (BufferSize - 1); i++) { + TEST_ASSERT_TRUE(cb.pop(data)); + TEST_ASSERT_FALSE(cb.empty()); + } + + /* Take one which is left. */ + TEST_ASSERT_TRUE(cb.pop(data)); + TEST_ASSERT_TRUE(cb.empty()); + + /* Add one element to the empty buffer. */ + cb.push(data); + TEST_ASSERT_FALSE(cb.empty()); +} + +/* Test circular buffer - test full() function. + * + * Given is a circular buffer with the capacity equal to N (BufferSize). + * When operations on circular buffer are performed (push, pop). + * Then full() function returns true if buffer is full, false otherwise. + * + */ +template +void test_full() +{ + CircularBuffer cb; + T data = 0; + + /* Push max elements - 1. */ + for (uint32_t i = 0; i < (BufferSize - 1); i++) { + cb.push(data); + TEST_ASSERT_FALSE(cb.full()); + } + + /* Push one element - buffer should be full now. */ + cb.push(data); + TEST_ASSERT_TRUE(cb.full()); + + /* Push next 2*BufferSize elements (overwrite entries). */ + for (uint32_t i = 0; i < (2 * BufferSize); i++) { + cb.push(data); + TEST_ASSERT_TRUE(cb.full()); + } + + /* Pop all elements. */ + for (uint32_t i = 0; i < BufferSize; i++) { + TEST_ASSERT_TRUE(cb.pop(data)); + TEST_ASSERT_FALSE(cb.full()); + } +} + +/* Test circular buffer - test reset() function. + * + * Given is a circular buffer with the capacity equal to N (BufferSize). + * When reset operation is performed on circular buffer. + * Then circular buffer is cleared. + * + */ +template +void test_reset() +{ + CircularBuffer cb; + T data = 0xAA; + + /* Push max elements. */ + for (uint32_t i = 0; i < BufferSize; i++) { + cb.push(data); + } + + TEST_ASSERT_TRUE(cb.full()); + TEST_ASSERT_FALSE(cb.empty()); + TEST_ASSERT_EQUAL(BufferSize, cb.size()); + + cb.reset(); + + TEST_ASSERT_FALSE(cb.full()); + TEST_ASSERT_TRUE(cb.empty()); + TEST_ASSERT_FALSE(cb.pop(data)); + TEST_ASSERT_EQUAL(0, cb.size()); + + /* Check if after reset push and pop operations work. */ + for (uint32_t i = 0; i < BufferSize; i++) { + cb.push(data); + data++; + } + + for (uint32_t i = 0; i < BufferSize; i++) { + cb.pop(data); + TEST_ASSERT_EQUAL(0xAA + i, data); + } +} + +/* Test circular buffer - creation of circular buffer with max buffer size consistent with counter type. + * + * Given is a circular buffer. + * When circular buffer is created with buffer size equal to 255 and counter type equal to unsigned char. + * Then circular buffer is successfully created. + * + */ +void test_counter_type_buffer_size() +{ + CircularBuffer cb; + int data = 100; + + /* Perform some operations. */ + cb.push(data); + data = 0; + cb.pop(data); + TEST_ASSERT_EQUAL(100, data); +} + +/* Test circular buffer - peek should not update buffer data. + * + * When circular buffer peek operation is performed along with + * push and pop, it should not update the buffer data elements. + * Elements read using pop/peek operation should match. + * + */ +void test_peek_no_pop() +{ + CircularBuffer cb; + int data = 0; + int peek_data = 0; + + for (uint32_t i = 0; i < 3; i++) { + data = (0xAA + i); + cb.push(data); + cb.peek(peek_data); + TEST_ASSERT_EQUAL(i + 1, cb.size()); + } + + for (uint32_t i = 0; i < 3; i++) { + TEST_ASSERT_TRUE(cb.peek(peek_data)); + TEST_ASSERT_EQUAL(0xAA + i, peek_data); + TEST_ASSERT_TRUE(cb.pop(data)); + TEST_ASSERT_EQUAL(0xAA + i, data); + TEST_ASSERT_EQUAL(3 - i - 1, cb.size()); + } +} + +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; +} + +Case cases[] = { + Case("Input does not exceed capacity(1) push max, pop max.", + test_input_does_not_exceed_capacity_push_max_pop_max, greentea_failure_handler), + Case("Input does not exceed capacity(3) push max, pop max.", + test_input_does_not_exceed_capacity_push_max_pop_max, greentea_failure_handler), + + Case("Input does not exceed capacity(5) push 2, pop 1.", + test_input_does_not_exceed_capacity_push_2_pop_1, greentea_failure_handler), + Case("Input does not exceed capacity(10) push 2, pop 1.", + test_input_does_not_exceed_capacity_push_2_pop_1, greentea_failure_handler), + + Case("Input exceeds capacity(1) push max+1, pop max.", + test_input_exceeds_capacity_push_max_plus_1_pop_max, greentea_failure_handler), + Case("Input exceeds capacity(3) push max+1, pop max.", + test_input_exceeds_capacity_push_max_plus_1_pop_max, greentea_failure_handler), + + Case("Input exceeds capacity(5) push 2, pop 1.", + test_input_exceeds_capacity_push_2_pop_1, greentea_failure_handler), + Case("Input exceeds capacity(10) push 2, pop 1.", + test_input_exceeds_capacity_push_2_pop_1, greentea_failure_handler), + + Case("empty() returns true when buffer(3 elements) is empty.", test_empty, greentea_failure_handler), + Case("empty() returns true when buffer(5 elements) is empty.", test_empty, greentea_failure_handler), + + Case("full() returns true when buffer(3 elements) is full.", test_full, greentea_failure_handler), + Case("full() returns true when buffer(5 elements) is full.", test_full, greentea_failure_handler), + + Case("reset() clears the buffer.", test_reset, greentea_failure_handler), + + Case("Test pop(), peek(), empty(), full(), size() after CircularBuffer creation.", + test_pop_empty_full_size_after_creation, greentea_failure_handler), + + Case("Test CounterType/BufferSize boarder case.", test_counter_type_buffer_size, greentea_failure_handler), + + Case("Input exceeds capacity(5) push 2, pop 1 - complex type.", + test_input_exceeds_capacity_push_2_pop_1_complex_type<5, unsigned short>, greentea_failure_handler), + + Case("peek() return data without popping the element.", test_peek_no_pop, greentea_failure_handler), +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(15, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + return Harness::run(specification); +} diff --git a/platform/tests/TESTS/mbed_platform/FileHandle/TestFile.h b/platform/tests/TESTS/mbed_platform/FileHandle/TestFile.h new file mode 100644 index 0000000..c99d8cc --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/FileHandle/TestFile.h @@ -0,0 +1,160 @@ +/* mbed Microcontroller Library + * 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_TESTFILEHANDLE_H +#define MBED_TESTFILEHANDLE_H + +#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 mbed::FileHandle { +public: + TestFile(): _pos(0), _end(0) {} + ~TestFile() {} + + enum FunctionName { + fnNone, fnRead, fnWrite, fnSeek, fnClose, fnIsatty, fnTruncate + }; + + virtual ssize_t read(void *buffer, size_t size) + { + ssize_t read; + _fnCalled = fnRead; + + for (read = 0; (size_t)read < size; read++) { + if (POS_IS_VALID(_pos)) { + ((uint8_t *)buffer)[read] = _data[_pos++]; + } else { + break; + } + } // for + return read; + } + + virtual ssize_t write(const void *buffer, size_t size) + { + ssize_t written; + _fnCalled = fnWrite; + + for (written = 0; (size_t)written < size; written++) { + if (NEW_POS_IS_VALID(_pos)) { + _data[_pos++] = ((uint8_t *)buffer)[written]; + } else { + if (0 == written) { + return -ENOSPC; + } + break; + } + if (_end < _pos) { + _end++; + } + } // for + return written; + } + + virtual off_t seek(off_t offset, int whence) + { + _fnCalled = fnSeek; + int32_t new_pos = INVALID_POS; + + switch (whence) { + case SEEK_SET: + new_pos = offset; + break; + + case SEEK_CUR: + new_pos = _pos + offset; + break; + + case SEEK_END: + new_pos = _end - offset; + break; + + default: + // nothing todo + break; + } + + if (SEEK_POS_IS_VALID(new_pos)) { + _pos = new_pos; + } else { + return -EINVAL; + } + + return _pos; + } + + virtual int close() + { + _fnCalled = fnClose; + return 0; + } + + virtual off_t size() + { + return _end; + } + + virtual int truncate(off_t length) + { + _fnCalled = fnTruncate; + if (!NEW_POS_IS_VALID(length)) { + return -EINVAL; + } + while (_end < length) { + _data[_end++] = 0; + } + _end = length; + return 0; + } + + + static void resetFunctionCallHistory() + { + _fnCalled = fnNone; + } + + static bool functionCalled(FunctionName name) + { + return (name == _fnCalled); + } + + static FunctionName getFunctionCalled() + { + return _fnCalled; + } + +private: + + // stores last function call name + static FunctionName _fnCalled; + + // file storage + uint8_t _data[FILE_SIZE]; + + int32_t _pos, _end; +}; + +template +typename TestFile::FunctionName TestFile::_fnCalled; + + +#endif // MBED_TESTFILEHANDLE_H diff --git a/platform/tests/TESTS/mbed_platform/FileHandle/main.cpp b/platform/tests/TESTS/mbed_platform/FileHandle/main.cpp new file mode 100644 index 0000000..4efd8f4 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/FileHandle/main.cpp @@ -0,0 +1,574 @@ +/* mbed Microcontroller Library + * 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 "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" +#include "TestFile.h" +#include "mbed.h" + +using utest::v1::Case; + + +/** Test fopen and fclose + * + * Given a file to be opened + * + * When the file is open + * Then returned file descriptor is valid + * + * When the file is closed + * Then underneath retargeting layer function is called + * and the fclose function return with succeed + * + */ +void test_fopen_fclose() +{ + std::FILE *file; + const uint32_t FS = 5; + TestFile fh; + + file = fdopen(&fh, "w+"); + TEST_ASSERT_NOT_NULL(file); + + TestFile::resetFunctionCallHistory(); + int ret = std::fclose(file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnClose)); + TEST_ASSERT_EQUAL_INT(0, ret); +} + + +/** Test fwrite and fread + * + * Given already opened file + * + * When write some data to file + * Then underneath retargeting layer write function is called + * fwrite return number of successfully written elements + * when not all elements were written stream error is set + * + * When read previously written data from file + * Then underneath retargeting layer read function is called + * fread return number of successfully read elements + * read data match previously written + * when read less then expected stream eof is set + * + */ +void test_fwrite_fread() +{ + std::FILE *file; + const uint32_t FS = 5; + TestFile fh; + char read_buf[16]; + const char *str1 = "abc"; + const char *str2 = "def"; + const uint32_t str1_size = strlen(str1); + const uint32_t str2_size = strlen(str2); + std::size_t write_ret; + std::size_t read_ret; + + file = fdopen(&fh, "w+"); + TEST_ASSERT_NOT_NULL(file); + std::setbuf(file, NULL); + + // write 3; expected written 3 + TestFile::resetFunctionCallHistory(); + write_ret = std::fwrite(str1, 1, str1_size, file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); + TEST_ASSERT_EQUAL_INT(str1_size, write_ret); + + // write 3; expected written 2 + TestFile::resetFunctionCallHistory(); + write_ret = std::fwrite(str2, 1, str2_size, file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); +#if !defined(__MICROLIB) + TEST_ASSERT_TRUE(std::ferror(file) != 0); +#endif + std::clearerr(file); + + // ARMCC/IAR returns 0 here instead of number of elements successfully written !!! + TEST_ASSERT_TRUE(write_ret >= 0 && write_ret <= (str2_size - 1)); + + // write 3; expected written 0 + TestFile::resetFunctionCallHistory(); + write_ret = std::fwrite(str1, 1, str1_size, file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); +#if !defined(__MICROLIB) + TEST_ASSERT_TRUE(std::ferror(file) != 0); +#endif + TEST_ASSERT_EQUAL_INT(0, write_ret); + + std::rewind(file); + + // read 3; expected read 3 + TestFile::resetFunctionCallHistory(); + read_ret = std::fread(read_buf, 1, str1_size, file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); + TEST_ASSERT_EQUAL_INT(str1_size, read_ret); + TEST_ASSERT_EQUAL_INT(0, strncmp(str1, read_buf, str1_size)); + + // read 3; expected read 2 + TestFile::resetFunctionCallHistory(); + read_ret = std::fread(read_buf, 1, str2_size, file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); +#if !defined(__MICROLIB) + TEST_ASSERT_TRUE(std::feof(file) != 0); +#endif + std::clearerr(file); + TEST_ASSERT_EQUAL_INT(str2_size - 1, read_ret); + TEST_ASSERT_EQUAL_INT(0, strncmp(str2, read_buf, str2_size - 1)); + + // read 3; expected read 0 + TestFile::resetFunctionCallHistory(); + read_ret = std::fread(read_buf, 1, str2_size, file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); +#if !defined(__MICROLIB) + TEST_ASSERT_TRUE(std::feof(file) != 0); +#endif + TEST_ASSERT_EQUAL_INT(0, read_ret); + + std::fclose(file); +} + + + +/** Test fputc and fgetc + * + * Given already opened file + * + * When write some data to file + * Then underneath retargeting layer write function is called + * fputc return written element + * on failure, returns EOF and stream error is sets + * + * When read previously written data from file + * Then underneath retargeting layer read function is called + * fgetc return read element + * read data match previously written + * on failure, returns EOF and stream error/eof is sets respectively + * + */ +void test_fputc_fgetc() +{ + std::FILE *file; + const uint32_t FS = 3; + TestFile fh; + char char_buf[3] = {'a', 'b', 'c' }; + int ret; + + file = fdopen(&fh, "w+"); + TEST_ASSERT_NOT_NULL(file); + std::setbuf(file, NULL); + + // write 1; expected written 1 + TestFile::resetFunctionCallHistory(); + ret = std::fputc(char_buf[0], file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); + TEST_ASSERT_EQUAL_INT(char_buf[0], ret); + + // write 1; expected written 1 + TestFile::resetFunctionCallHistory(); + ret = std::fputc(char_buf[1], file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); + TEST_ASSERT_EQUAL_INT(char_buf[1], ret); + + // write 1; expected written 1 + TestFile::resetFunctionCallHistory(); + ret = std::fputc(char_buf[2], file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); + TEST_ASSERT_EQUAL_INT(char_buf[2], ret); + + // write 1; expected written 0 + TestFile::resetFunctionCallHistory(); + ret = std::fputc(char_buf[0], file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); +#if !defined(__MICROLIB) + TEST_ASSERT_TRUE(std::ferror(file) != 0); +#endif + TEST_ASSERT_EQUAL_INT(EOF, ret); + + std::rewind(file); + + // read 1; expected read 1 + TestFile::resetFunctionCallHistory(); + ret = std::fgetc(file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); + TEST_ASSERT_EQUAL_INT(char_buf[0], ret); + + // read 1; expected read 1 + TestFile::resetFunctionCallHistory(); + ret = std::fgetc(file); + TEST_ASSERT_EQUAL_INT(char_buf[1], ret); + + // read 1; expected read 1 + TestFile::resetFunctionCallHistory(); + ret = std::fgetc(file); + TEST_ASSERT_EQUAL_INT(char_buf[2], ret); + + // read 1; expected read 0 + TestFile::resetFunctionCallHistory(); + ret = std::fgetc(file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); +#if !defined(__MICROLIB) + TEST_ASSERT_TRUE(std::feof(file) != 0); +#endif + TEST_ASSERT_EQUAL_INT(EOF, ret); + + std::fclose(file); +} + +/** Test fputs and fgets + * + * Given already opened file + * + * When write some data to file + * Then underneath retargeting layer write function is called + * on success, returns a non-negative value + * on failure, returns EOF and set stream error + * + * When read previously written data from file + * Then underneath retargeting layer read function is called + * fgets return valid buffer, and read data match previously written + * when read less then expected stream EOF is set + * on failure, stream error is sets + * + */ +void test_fputs_fgets() +{ + std::FILE *file; + const uint32_t FS = 5; + TestFile fh; + const char *str1 = "abc"; + const char *str2 = "def"; + const uint32_t str1_size = strlen(str1); + const uint32_t str2_size = strlen(str2); + char read_buf[16]; + int fputs_ret; + char *fgets_ret; + + file = fdopen(&fh, "w+"); + TEST_ASSERT_NOT_NULL(file); + std::setbuf(file, NULL); + + // write 3; expected written 3 + TestFile::resetFunctionCallHistory(); + fputs_ret = std::fputs(str1, file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); + TEST_ASSERT_TRUE(fputs_ret >= 0); + + // write 3; expected written 2 + TestFile::resetFunctionCallHistory(); + fputs_ret = std::fputs(str2, file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); +#if !defined(__MICROLIB) + TEST_ASSERT_TRUE(std::ferror(file) != 0); +#endif + std::clearerr(file); + TEST_ASSERT_EQUAL_INT(EOF, fputs_ret); + + // write 3; expected written 0 + TestFile::resetFunctionCallHistory(); + fputs_ret = std::fputs(str1, file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); +#if !defined(__MICROLIB) + TEST_ASSERT_TRUE(std::ferror(file) != 0); +#endif + TEST_ASSERT_EQUAL_INT(EOF, fputs_ret); + + std::rewind(file); + + // read 3; expected read 3 + TestFile::resetFunctionCallHistory(); + fgets_ret = std::fgets(read_buf, str1_size + 1, file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); + TEST_ASSERT_EQUAL_INT(read_buf, fgets_ret); + TEST_ASSERT_EQUAL_INT(0, strncmp(read_buf, str1, str1_size)); + + // read 3; expected read 2 + TestFile::resetFunctionCallHistory(); + fgets_ret = std::fgets(read_buf, str2_size + 1, file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); +#if !defined(__MICROLIB) + TEST_ASSERT_TRUE(std::feof(file) != 0); +#endif + std::clearerr(file); + TEST_ASSERT_EQUAL_INT(read_buf, fgets_ret); + TEST_ASSERT_EQUAL_INT(0, strncmp(read_buf, str2, str2_size - 2)); + + // read 3; expected read 0 + TestFile::resetFunctionCallHistory(); + fgets_ret = std::fgets(read_buf, str2_size + 1, file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); +#if !defined(__MICROLIB) + TEST_ASSERT_TRUE(std::feof(file) != 0); +#endif + TEST_ASSERT_EQUAL_INT(NULL, fgets_ret); + + std::fclose(file); +} + +/** Test fprintf and fscanf + * + * Given already opened file + * + * When write some data to file + * Then underneath retargeting layer write function is called + * fprintf return number of written components + * fprintf return negative value if an error occurred and set stream error + * + * When read previously written data from file + * Then underneath retargeting layer read function is called + * fscanf return number of read components, and read data match previously written + * when read less then expected stream EOF is set + * on failure, stream error is sets + * + */ +void test_fprintf_fscanf() +{ + std::FILE *file; + const uint32_t FS = 5; + TestFile fh; + const char *str1 = "abc"; + const char *str2 = "def"; + const uint32_t str1_size = strlen(str1); + const uint32_t str2_size = strlen(str2); + char read_buf[16]; + int fprintf_ret; + int fscanf_ret; + + file = fdopen(&fh, "w+"); + TEST_ASSERT_NOT_NULL(file); + std::setbuf(file, NULL); + + // write 3; expected written 3 + TestFile::resetFunctionCallHistory(); + fprintf_ret = fprintf(file, "%s", str1); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); + TEST_ASSERT_EQUAL_INT(str1_size, fprintf_ret); + +#if !defined(__MICROLIB) + // feof() and ferror() functions are not supported in Microlib. + // write 3; expected written 2 + TestFile::resetFunctionCallHistory(); + fprintf_ret = fprintf(file, "%s", str2); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); + TEST_ASSERT_TRUE(std::ferror(file) != 0); + std::clearerr(file); + TEST_ASSERT_TRUE(fprintf_ret < 0); + + // write 3; expected written 0 + TestFile::resetFunctionCallHistory(); + fprintf_ret = fprintf(file, "%s", str2); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); + TEST_ASSERT_TRUE(std::ferror(file) != 0); + TEST_ASSERT_TRUE(fprintf_ret < 0); +#else + // Writing remaining available file space of 2 characters + // to make further fscanf() test to pass. + // write 2; expected written 2 + TestFile::resetFunctionCallHistory(); + fprintf_ret = 0; + fprintf_ret += fprintf(file, "%c", str2[0]); + fprintf_ret += fprintf(file, "%c", str2[1]); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); + TEST_ASSERT_EQUAL_INT(2, fprintf_ret); +#endif + std::rewind(file); + + // read 3; expected read 3 + TestFile::resetFunctionCallHistory(); + fscanf_ret = fscanf(file, "%3s", read_buf); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); + TEST_ASSERT_EQUAL_INT(1, fscanf_ret); + TEST_ASSERT_EQUAL_INT(0, strncmp(read_buf, str1, str1_size)); + + // read 3; expected read 2 + TestFile::resetFunctionCallHistory(); + fscanf_ret = fscanf(file, "%3s", read_buf); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); +#if !defined(__MICROLIB) + TEST_ASSERT_TRUE(std::feof(file) != 0); + std::clearerr(file); +#endif + TEST_ASSERT_EQUAL_INT(1, fscanf_ret); + TEST_ASSERT_EQUAL_INT(0, strncmp(read_buf, str2, str2_size - 1)); + + // read 3; expected read 0 + TestFile::resetFunctionCallHistory(); + fscanf_ret = fscanf(file, "%3s", read_buf); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); +#if !defined(__MICROLIB) + TEST_ASSERT_TRUE(std::feof(file) != 0); +#endif + TEST_ASSERT_EQUAL_INT(EOF, fscanf_ret); + + std::fclose(file); +} + +/** Test fseek and ftell + * + * ARM library is quite good at optimising out unnecessary calls to underlying + * seek, so only test real non empty files. + * + * Given already opened file is not empty + * + * When set the file position indicator via fseek + * Then underneath retargeting layer seek function is called + * fseek return with succeed and ftell return already set position + * Check actual character read or written. + * + */ +void test_fseek_ftell() +{ + std::FILE *file; + long ftell_ret; + int fssek_ret; + const uint32_t FS = 128; + TestFile fh; + + file = fdopen(&fh, "w+"); + TEST_ASSERT_NOT_NULL(file); + std::setbuf(file, NULL); + + TestFile::resetFunctionCallHistory(); + ftell_ret = std::ftell(file); + TEST_ASSERT_EQUAL(0, ftell_ret); + + const char *str = "Hello world"; + const std::size_t size = std::strlen(str); + + std::fwrite(str, 1, size, file); + + TestFile::resetFunctionCallHistory(); + ftell_ret = std::ftell(file); + TEST_ASSERT_EQUAL(size, ftell_ret); + + TestFile::resetFunctionCallHistory(); + fssek_ret = std::fseek(file, 5, SEEK_SET); + TEST_ASSERT_EQUAL(0, fssek_ret); + ftell_ret = std::ftell(file); + TEST_ASSERT_EQUAL(5, ftell_ret); + int c = std::fgetc(file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); + TEST_ASSERT_EQUAL(c, str[5]); + + TestFile::resetFunctionCallHistory(); + fssek_ret = std::fseek(file, -6, SEEK_CUR); + TEST_ASSERT_EQUAL(0, fssek_ret); + ftell_ret = std::ftell(file); + TEST_ASSERT_EQUAL(0, ftell_ret); + c = std::fgetc(file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnRead)); + TEST_ASSERT_EQUAL(c, str[0]); + + TestFile::resetFunctionCallHistory(); + fssek_ret = std::fseek(file, 0, SEEK_END); + TEST_ASSERT_EQUAL(0, fssek_ret); + ftell_ret = std::ftell(file); + TEST_ASSERT_EQUAL(size, ftell_ret); + c = std::fputc('!', file); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnWrite)); + TEST_ASSERT_EQUAL(c, '!'); + TEST_ASSERT_EQUAL(fh.size(), size + 1); + + std::fclose(file); +} + +/** Test ftruncate and fstat (st_size) + * + * Check we get EBADF for illegal handles + * + * Given already opened file is empty + * + * Check initial size is returned as 0 + * Call ftruncate with negative value - check our EINVAL is passed back + * Call ftruncate with positive value to increase size - check no error return + * Check fstat st_size now reads back as the value we set. + * Call ftruncate with smaller positive value to decrease size - check no error return + * Check fstat st_size now reads back as the value we set. + */ +void test_ftruncate_fstat() +{ + int fildes; + int ret; + struct stat st; + const uint32_t FS = 128; + TestFile fh; + + ret = ftruncate(12345678, 24); + TEST_ASSERT_EQUAL(-1, ret); + TEST_ASSERT_EQUAL(EBADF, errno); + + ret = fstat(12345678, &st); + TEST_ASSERT_EQUAL(-1, ret); + TEST_ASSERT_EQUAL(EBADF, errno); + + fildes = bind_to_fd(&fh); + TEST_ASSERT_TRUE(fildes >= 0); + + ret = fstat(fildes, &st); + TEST_ASSERT_EQUAL(0, ret); + TEST_ASSERT_EQUAL(0, st.st_size); + + TestFile::resetFunctionCallHistory(); + ret = ftruncate(fildes, -3); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnTruncate)); + TEST_ASSERT_EQUAL(-1, ret); + TEST_ASSERT_EQUAL(EINVAL, errno); + + TestFile::resetFunctionCallHistory(); + ret = ftruncate(fildes, 24); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnTruncate)); + TEST_ASSERT_EQUAL(0, ret); + + ret = fstat(fildes, &st); + TEST_ASSERT_EQUAL(0, ret); + TEST_ASSERT_EQUAL(24, st.st_size); + + ret = ftruncate(fildes, 12); + TEST_ASSERT_TRUE(TestFile::functionCalled(TestFile::fnTruncate)); + TEST_ASSERT_EQUAL(0, ret); + + ret = fstat(fildes, &st); + TEST_ASSERT_EQUAL(0, ret); + TEST_ASSERT_EQUAL(12, st.st_size); + + close(fildes); +} + +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 fopen/fclose", test_fopen_fclose), + Case("Test fwrite/fread", test_fwrite_fread), + Case("Test fputc/fgetc", test_fputc_fgetc), + Case("Test fputs/fgets", test_fputs_fgets), + Case("Test fprintf/fscanf", test_fprintf_fscanf), + Case("Test fseek/ftell", test_fseek_ftell), + Case("Test ftruncate/fstat", test_ftruncate_fstat) +}; + +utest::v1::Specification specification(test_setup, cases); + +int main() +{ + return !utest::v1::Harness::run(specification); +} diff --git a/platform/tests/TESTS/mbed_platform/SharedPtr/main.cpp b/platform/tests/TESTS/mbed_platform/SharedPtr/main.cpp new file mode 100644 index 0000000..f1321ee --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/SharedPtr/main.cpp @@ -0,0 +1,129 @@ +/* mbed Microcontroller Library + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + +#include "platform/SharedPtr.h" + +using utest::v1::Case; + +struct TestStruct { + TestStruct() + { + s_count++; + value = 42; + } + + ~TestStruct() + { + s_count--; + value = 0; + } + + int value; + static int s_count; +}; + +int TestStruct::s_count = 0; + +/** + * Test that a shared pointer correctly manages the lifetime of the underlying raw pointer + */ +void test_single_sharedptr_lifetime() +{ + // Sanity-check value of counter + TEST_ASSERT_EQUAL(0, TestStruct::s_count); + + // Create and destroy shared pointer in given scope + { + SharedPtr s_ptr(new TestStruct); + TEST_ASSERT_EQUAL(1, TestStruct::s_count); + } + + // Destroy shared pointer + TEST_ASSERT_EQUAL(0, TestStruct::s_count); +} + +/** + * Test that multiple instances of shared pointers correctly manage the reference count + * to release the object at the correct point + */ +void test_instance_sharing() +{ + SharedPtr s_ptr1(nullptr); + + // Sanity-check value of counter + TEST_ASSERT_EQUAL(0, TestStruct::s_count); + + // Create and destroy shared pointer in given scope + { + SharedPtr s_ptr2(new TestStruct); + TEST_ASSERT_EQUAL(1, TestStruct::s_count); + s_ptr1 = s_ptr2; + TEST_ASSERT_EQUAL(1, TestStruct::s_count); + } + + TEST_ASSERT_EQUAL(1, TestStruct::s_count); + + s_ptr1 = nullptr; + + // Destroy shared pointer + TEST_ASSERT_EQUAL(0, TestStruct::s_count); +} + +/** + * Test whether comparison operators operate as expected, both between + * shared pointers managing the same object, + * and a shared pointer and underlying raw pointer + */ +void test_equality_comparators() +{ + TestStruct *raw_ptr1 = new TestStruct; + TestStruct *raw_ptr2 = new TestStruct; + SharedPtr s_ptr1_1(raw_ptr1); + SharedPtr s_ptr1_2 = s_ptr1_1; + SharedPtr s_ptr2(raw_ptr2); + + // Pointers that should be deemed equal + TEST_ASSERT_TRUE(s_ptr1_1 == raw_ptr1); // Shared pointer / Raw pointer + TEST_ASSERT_TRUE(s_ptr1_1 == s_ptr1_2); // Shared pointer / Shared pointer + + // Pointers that should be deemed different + TEST_ASSERT_TRUE(s_ptr1_1 != raw_ptr2); // Shared pointer / Raw pointer + TEST_ASSERT_TRUE(s_ptr1_1 != s_ptr2); // Shared pointer / Shared pointer +} + +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 single shared pointer instance", test_single_sharedptr_lifetime), + Case("Test instance sharing across multiple shared pointers", test_instance_sharing), + Case("Test equality comparators", test_equality_comparators) +}; + +utest::v1::Specification specification(test_setup, cases); + +int main() +{ + return !utest::v1::Harness::run(specification); +} diff --git a/platform/tests/TESTS/mbed_platform/SingletonPtr/main.cpp b/platform/tests/TESTS/mbed_platform/SingletonPtr/main.cpp new file mode 100644 index 0000000..9a59bda --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/SingletonPtr/main.cpp @@ -0,0 +1,102 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + +using utest::v1::Case; + + +class InstanceTest { +public: + InstanceTest() + { + _instance_counter++; + } + + static int get_instance_counter() + { + return _instance_counter; + } + +private: + static int _instance_counter; +}; + +int InstanceTest::_instance_counter = 0; + + +SingletonPtr singleton; + + +/** Test SingletonPtr lazy initialization + * + * Given a global singleton of type SingletonPtr + * When before first singleton use + * Then underneath object is yet not created + */ +void test_lazy_initialization() +{ + TEST_ASSERT_MESSAGE(InstanceTest::get_instance_counter() == 0, "Initialized before first use!!!"); +} + +/** Test SingletonPtr single instance + * + * Given a singleton of type SingletonPtr + * + * When after first singleton use + * Then underneath object was created exactly once + * + * When after second singleton use + * Then underneath object was created exactly once + * and both (ref1 and ref2) are references to same instance + * + */ +void test_single_instance() +{ + InstanceTest *ref1 = singleton.get(); + TEST_ASSERT_NOT_NULL(ref1); + + TEST_ASSERT_EQUAL_INT(1, InstanceTest::get_instance_counter()); + + InstanceTest *ref2 = singleton.get(); + TEST_ASSERT_NOT_NULL(ref2); + + TEST_ASSERT_EQUAL_INT(1, InstanceTest::get_instance_counter()); + + // same instance + TEST_ASSERT_EQUAL_PTR(ref1, ref2); +} + +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 lazy initialization", test_lazy_initialization), + Case("Test single instance", test_single_instance), +}; + +utest::v1::Specification specification(test_setup, cases); + +int main() +{ + return !utest::v1::Harness::run(specification); +} diff --git a/platform/tests/TESTS/mbed_platform/Stream/main.cpp b/platform/tests/TESTS/mbed_platform/Stream/main.cpp new file mode 100644 index 0000000..7aa4b51 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/Stream/main.cpp @@ -0,0 +1,232 @@ +/* mbed Microcontroller Library + * 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 "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" +#include "mbed.h" +#include "Stream.h" + +/* This test suite verifies that write/read/write/read sequence can be + * successfully executed on the Stream objects. + * + * A qute from C99 standard, paragraph 7.19.5.3, point 6: + * + * When a file is opened with update mode ('+' as the second or third character in the + * above list of mode argument values), both input and output may be performed on the + * associated stream. However, output shall not be directly followed by input without an + * intervening call to the fflush function or to a file positioning function (fseek, + * fsetpos, or rewind), and input shall not be directly followed by output without an + * intervening call to a file positioning function, unless the input operation encounters end- + * of-file. + */ + +using utest::v1::Case; + +const char FMT[] = "Foo%02ibar."; +const size_t FORMATTED_STR_SIZE = 3 + 2 + 4 + 1; +// The test Stream instance has to be able to store two printf() output strings. +const size_t LOOPBACK_BUFF_SIZE = 2 * FORMATTED_STR_SIZE; + +class Loopback : public Stream { +public: + Loopback(const char *name = NULL) : Stream(name) + { + // The `fgets()` stops reading after a newline or EOF. + // Fill the buffer with newlines to simplify fgets() usage in this test. + memset(_buff, '\n', LOOPBACK_BUFF_SIZE); + _p_index = 0; + _g_index = 0; + } + + virtual ~Loopback() + { + } + + int test_vprintf(const char *fmt, ...) + { + int rc = -1; + std::va_list args; + va_start(args, fmt); + rc = vprintf(fmt, args); + va_end(args); + return rc; + } + + int test_vscanf(const char *fmt, ...) + { + int rc = EOF; + std::va_list args; + va_start(args, fmt); + rc = vscanf(fmt, args); + va_end(args); + return rc; + } + +protected: + virtual int _putc(int c) + { + if (_p_index >= LOOPBACK_BUFF_SIZE) { + return -1; + } + _buff[_p_index++] = (int8_t)c; + return c; + } + + virtual int _getc() + { + if (_g_index >= LOOPBACK_BUFF_SIZE) { + return -1; + } + return _buff[_g_index++]; + } + +private: + int8_t _buff[LOOPBACK_BUFF_SIZE]; + size_t _p_index; + size_t _g_index; +}; + +/* Test intermixed Stream::putc() / Stream::getc(). + * + * Given a Stream object, + * when a write/read/write/read sequence is executed + * with the use of Stream::putc() and Stream::getc() methods, + * then all operations succeed. + */ +void test_putc_getc() +{ + char char_buff[2] = {'a', 'b'}; + Loopback loop("loopback"); + int ret; + + ret = loop.putc(char_buff[0]); + TEST_ASSERT_EQUAL_INT(char_buff[0], ret); + ret = loop.getc(); + TEST_ASSERT_EQUAL_INT(char_buff[0], ret); + ret = loop.putc(char_buff[1]); + TEST_ASSERT_EQUAL_INT(char_buff[1], ret); + ret = loop.getc(); + TEST_ASSERT_EQUAL_INT(char_buff[1], ret); +} + +/* Test intermixed Stream::puts() / Stream::gets(). + * + * Given a Stream object, + * when a write/read/write/read sequence is executed, + * with the use of Stream::puts() and Stream::gets() methods, + * then all operations succeed. + */ +void test_puts_gets() +{ + const size_t STR_LEN = 3; + const size_t STR_SIZE = STR_LEN + 1; // +1 for '\0' + char strings[2][STR_SIZE] = {"Foo", "Bar"}; + const size_t GETS_BUFF_SIZE = STR_LEN + 2; // +1 for '\n' (gets() stops AFTER a '\n'), +1 for '\0' + char g_buff[GETS_BUFF_SIZE] = {}; + Loopback loop("loopback"); + int p_rc; + char *g_rc; + + p_rc = loop.puts(strings[0]); + TEST_ASSERT(p_rc >= 0); + g_rc = loop.gets(g_buff, GETS_BUFF_SIZE); + TEST_ASSERT_EQUAL_PTR(g_buff, g_rc); + + p_rc = loop.puts(strings[1]); + TEST_ASSERT(p_rc >= 0); + g_rc = loop.gets(g_buff, GETS_BUFF_SIZE); + TEST_ASSERT_EQUAL_PTR(g_buff, g_rc); +} + +/* Test intermixed Stream::printf() / Stream::scanf(). + * + * Given a Stream object, + * when a write/read/write/read sequence is executed, + * with the use of Stream::printf() and Stream::scanf() methods, + * then all operations succeed. + */ +void test_printf_scanf() +{ + Loopback loop("loopback"); + int p_val, g_val, rc; + + p_val = 42; + g_val = p_val + 1; + rc = loop.printf(FMT, p_val); + TEST_ASSERT(rc > 0); + rc = loop.scanf(FMT, &g_val); + TEST_ASSERT(rc == 1); + TEST_ASSERT_EQUAL_INT(p_val, g_val); + + p_val += 5; + g_val = p_val + 1; + rc = loop.printf(FMT, p_val); + TEST_ASSERT(rc > 0); + rc = loop.scanf(FMT, &g_val); + TEST_ASSERT(rc == 1); + TEST_ASSERT_EQUAL_INT(p_val, g_val); +} + +/* Test intermixed Stream::vprintf() / Stream::vscanf(). + * + * Given a Stream object, + * when a write/read/write/read sequence is executed, + * with the use of Stream::vprintf() and Stream::vscanf() methods, + * then all operations succeed. + */ +void test_vprintf_vscanf() +{ + Loopback loop("loopback"); + int p_val, g_val, rc; + + p_val = 42; + g_val = p_val + 1; + rc = loop.test_vprintf(FMT, p_val); + TEST_ASSERT(rc > 0); + rc = loop.test_vscanf(FMT, &g_val); + TEST_ASSERT(rc == 1); + TEST_ASSERT_EQUAL_INT(p_val, g_val); + + p_val += 5; + g_val = p_val + 1; + rc = loop.test_vprintf(FMT, p_val); + TEST_ASSERT(rc > 0); + rc = loop.test_vscanf(FMT, &g_val); + TEST_ASSERT(rc == 1); + TEST_ASSERT_EQUAL_INT(p_val, g_val); +} + +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), + Case("Test puts/gets", test_puts_gets), + Case("Test printf/scanf", test_printf_scanf), + Case("Test vprintf/vscanf", test_vprintf_vscanf) +}; + +utest::v1::Specification specification(test_setup, cases); + +int main() +{ + return !utest::v1::Harness::run(specification); +} diff --git a/platform/tests/TESTS/mbed_platform/Transaction/main.cpp b/platform/tests/TESTS/mbed_platform/Transaction/main.cpp new file mode 100644 index 0000000..3b327d0 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/Transaction/main.cpp @@ -0,0 +1,104 @@ +/* mbed Microcontroller Library + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" +#include "platform/Transaction.h" + +using utest::v1::Case; + +static void dummy_callback(int) +{ + /* do nothing. */ +} + +/** Test Transaction class - creation with initialisation + * + * Given is Transaction class. + * When object of the Transaction class is created and initialised. + * Then get_object() returns object's instance for the transaction and get_transaction() returns the transaction. + * + */ +template +void test_Transaction_init() +{ + Type object; + const size_t tx_buffer_size = 24; + const size_t rx_buffer_size = 16; + const uint32_t event_id = 123; + const uint8_t word_width = 8; + unsigned char tx_buffer[tx_buffer_size]; + unsigned char rx_buffer[rx_buffer_size]; + const event_callback_t &callback = dummy_callback; + transaction_t transaction_data = + { tx_buffer, tx_buffer_size, rx_buffer, rx_buffer_size, event_id, callback, word_width }; + + Transaction test_transaction(&object, transaction_data); + + TEST_ASSERT_EQUAL(&object, test_transaction.get_object()); + + TEST_ASSERT_EQUAL((void *)tx_buffer, test_transaction.get_transaction()->tx_buffer); + TEST_ASSERT_EQUAL((void *)rx_buffer, test_transaction.get_transaction()->rx_buffer); + TEST_ASSERT_EQUAL(tx_buffer_size, test_transaction.get_transaction()->tx_length); + TEST_ASSERT_EQUAL(rx_buffer_size, test_transaction.get_transaction()->rx_length); + TEST_ASSERT_EQUAL(event_id, test_transaction.get_transaction()->event); + TEST_ASSERT_EQUAL(word_width, test_transaction.get_transaction()->width); +#if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE + TEST_ASSERT_TRUE(callback == test_transaction.get_transaction()->callback); +#else + TEST_ASSERT_FALSE(nullptr == test_transaction.get_transaction()->callback) +#endif +} + +/** Test Transaction class - creation without initialisation + * + * Given is Transaction class. + * When object of the Transaction class is created. + * Then this operation is successful. + * + */ +template +void test_Transaction_empty() +{ + Type object; + + Transaction test_transaction; + + /* Just indicate successful execution of the test case. */ + TEST_ASSERT_TRUE(true); +} + +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 Transaction - init ", test_Transaction_init), + Case("Test Transaction - init ", test_Transaction_init), + Case("Test Transaction - no init ", test_Transaction_empty), + Case("Test Transaction - no init ", test_Transaction_empty), +}; + +utest::v1::Specification specification(test_setup, cases); + +int main() +{ + return !utest::v1::Harness::run(specification); +} diff --git a/platform/tests/TESTS/mbed_platform/atomic/main.cpp b/platform/tests/TESTS/mbed_platform/atomic/main.cpp new file mode 100644 index 0000000..ed22373 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/atomic/main.cpp @@ -0,0 +1,284 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest/utest.h" + +#include + +#if !MBED_CONF_RTOS_PRESENT +#error [NOT_SUPPORTED] test not supported +#else + +#define THREAD_STACK 512 + +using utest::v1::Case; + +namespace { + +using mstd::atomic; + +/* Lock-free operations will be much faster - keep runtime down */ +#define ADD_UNLOCKED_ITERATIONS (SystemCoreClock / 1000) +#define ADD_LOCKED_ITERATIONS (SystemCoreClock / 8000) + +template +static inline long add_iterations(A &a) +{ + return a.is_lock_free() ? ADD_UNLOCKED_ITERATIONS : ADD_LOCKED_ITERATIONS; +} + +template +struct add_incrementer { + static void op(A *ptr) + { + for (long i = add_iterations(*ptr); i > 0; i--) { + ++(*ptr); + } + } +}; + +template +struct add_release_incrementer { + static void op(A *ptr) + { + for (long i = add_iterations(*ptr); i > 0; i--) { + ptr->fetch_add(1, mstd::memory_order_release); + } + } +}; + +template +struct sub_incrementer { + static void op(A *ptr) + { + for (long i = add_iterations(*ptr); i > 0; i--) { + ptr->fetch_sub(-1); + } + } +}; + +template +struct bitops_incrementer { + static void op(A *ptr) + { + for (long i = add_iterations(*ptr); i > 0; i--) { + (*ptr) += 1; + (*ptr) &= -1; + (*ptr) |= 0; + } + } +}; + +template +struct weak_incrementer { + static void op(A *ptr) + { + for (long i = add_iterations(*ptr); i > 0; i--) { + typename A::value_type val = ptr->load(); + do { + } while (!ptr->compare_exchange_weak(val, val + 1)); + } + } +}; + +template +struct strong_incrementer { + static void op(A *ptr) + { + for (long i = add_iterations(*ptr); i > 0; i--) { + typename A::value_type val = ptr->load(); + do { + } while (!ptr->compare_exchange_strong(val, val + 1)); + } + } +}; + + + +/* + * Run multiple threads incrementing each data item + * ADD_ITERATIONS times, and at the end, check that + * each item is * ADD_ITERATIONS. + * Items are adjacent to catch any interference. + * + * Using core_util_atomic_ templates, and exercising + * load and store briefly. + */ +template class Fn> +void test_atomic_add() +{ + struct { + volatile T nonatomic1; + atomic atomic1; + volatile atomic atomic2; // use volatile just to exercise the templates' volatile methods + volatile T nonatomic2; + } data = { 0, { 0 }, { 1 }, 0 }; // test initialisation + + TEST_ASSERT_EQUAL(sizeof(T), sizeof data.nonatomic1); + TEST_ASSERT_EQUAL(sizeof(T), sizeof data.atomic1); + TEST_ASSERT_EQUAL(4 * sizeof(T), sizeof data); + + // test store + data.atomic2 = 0; + + Thread t1(osPriorityNormal, THREAD_STACK); + Thread t2(osPriorityNormal, THREAD_STACK); + Thread t3(osPriorityNormal, THREAD_STACK); + Thread t4(osPriorityNormal, THREAD_STACK); + + TEST_ASSERT_EQUAL(osOK, t1.start(callback(Fn::op, &data.atomic1))); + TEST_ASSERT_EQUAL(osOK, t2.start(callback(Fn::op, &data.atomic1))); + TEST_ASSERT_EQUAL(osOK, t3.start(callback(Fn::op, &data.atomic2))); + TEST_ASSERT_EQUAL(osOK, t4.start(callback(Fn::op, &data.atomic2))); + + for (long i = ADD_UNLOCKED_ITERATIONS; i > 0; i--) { + data.nonatomic1++; + data.nonatomic2++; + } + + t1.join(); + t2.join(); + t3.join(); + t4.join(); + + TEST_ASSERT_EQUAL(T(ADD_UNLOCKED_ITERATIONS), data.nonatomic1); + TEST_ASSERT_EQUAL(T(2 * add_iterations(data.atomic1)), data.atomic1); + TEST_ASSERT_EQUAL(T(2 * add_iterations(data.atomic2)), data.atomic2); + TEST_ASSERT_EQUAL(T(ADD_UNLOCKED_ITERATIONS), data.nonatomic2); +} + +// This should fit into a uint32_t container, and there +// will be 1 byte of padding to ignore. +struct small { + uint8_t a; + uint8_t b; + uint8_t c; +}; + +// An 11-byte weird structure. Should work with critical sections. +struct large { + uint8_t a; + uint8_t b; + uint8_t c; + uint8_t dummy[8]; +}; + +template +void struct_incrementer_a(A *data) +{ + for (long i = add_iterations(*data); i > 0; i--) { + typename A::value_type curval = *data, newval; + do { + newval = curval; + newval.a++; + } while (!data->compare_exchange_weak(curval, newval)); + } +} + +template +void struct_incrementer_b(A *data) +{ + for (long i = add_iterations(*data); i > 0; i--) { + typename A::value_type curval = *data, newval; + do { + newval = curval; + newval.b++; + } while (!data->compare_exchange_weak(curval, newval)); + } +} + +template +void test_atomic_struct() +{ + TEST_ASSERT_EQUAL(N, sizeof(atomic)); + + // Small structures don't have value constructor implemented; + atomic data; + atomic_init(&data, T{0, 0, 0}); + + Thread t1(osPriorityNormal, THREAD_STACK); + Thread t2(osPriorityNormal, THREAD_STACK); + + TEST_ASSERT_EQUAL(osOK, t1.start(callback(struct_incrementer_a >, &data))); + TEST_ASSERT_EQUAL(osOK, t2.start(callback(struct_incrementer_b >, &data))); + + for (long i = add_iterations(data); i > 0; i--) { + T curval = data, newval; + do { + newval = curval; + newval.c++; + } while (!data.compare_exchange_weak(curval, newval)); + } + + t1.join(); + t2.join(); + + T final_val = data; + + TEST_ASSERT_EQUAL(uint8_t(add_iterations(data)), final_val.a); + TEST_ASSERT_EQUAL(uint8_t(add_iterations(data)), final_val.b); + TEST_ASSERT_EQUAL(uint8_t(add_iterations(data)), final_val.c); +} + +} // namespace + +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(60, "default_auto"); + return utest::v1::verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Test atomic add 8-bit", test_atomic_add), + Case("Test atomic add 16-bit", test_atomic_add), + Case("Test atomic add 32-bit", test_atomic_add), + Case("Test atomic add 64-bit", test_atomic_add), + Case("Test atomic add signed 8-bit", test_atomic_add), + Case("Test atomic add signed 16-bit", test_atomic_add), + Case("Test atomic add signed 32-bit", test_atomic_add), + Case("Test atomic add signed 64-bit", test_atomic_add), + Case("Test atomic add release 32-bit", test_atomic_add), + Case("Test atomic sub 8-bit", test_atomic_add), + Case("Test atomic sub 16-bit", test_atomic_add), + Case("Test atomic sub 32-bit", test_atomic_add), + Case("Test atomic sub 64-bit", test_atomic_add), + Case("Test atomic bitops 8-bit", test_atomic_add), + Case("Test atomic bitops 16-bit", test_atomic_add), + Case("Test atomic bitops 32-bit", test_atomic_add), + Case("Test atomic bitops 64-bit", test_atomic_add), + Case("Test atomic compare exchange weak 8-bit", test_atomic_add), + Case("Test atomic compare exchange weak 16-bit", test_atomic_add), + Case("Test atomic compare exchange weak 32-bit", test_atomic_add), + Case("Test atomic compare exchange weak 64-bit", test_atomic_add), + Case("Test atomic compare exchange strong 8-bit", test_atomic_add), + Case("Test atomic compare exchange strong 16-bit", test_atomic_add), + Case("Test atomic compare exchange strong 32-bit", test_atomic_add), + Case("Test atomic compare exchange strong 64-bit", test_atomic_add), + Case("Test small atomic custom structure", test_atomic_struct), + Case("Test large atomic custom structure", test_atomic_struct) +}; + +utest::v1::Specification specification(test_setup, cases); + +int main() +{ + return !utest::v1::Harness::run(specification); +} + +#endif // !MBED_CONF_RTOS_PRESENT diff --git a/platform/tests/TESTS/mbed_platform/crash_reporting/main.cpp b/platform/tests/TESTS/mbed_platform/crash_reporting/main.cpp new file mode 100644 index 0000000..5f93f73 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/crash_reporting/main.cpp @@ -0,0 +1,83 @@ +/* mbed Microcontroller Library + * 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 "mbed.h" +#include "mbed_error.h" +#include "mbed_crash_data_offsets.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" + +#if !MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED +#error [NOT_SUPPORTED] crash_reporting test not supported +#else + +#define MSG_VALUE_DUMMY "0" +#define MSG_VALUE_LEN 32 +#define MSG_KEY_LEN 64 + +#define MSG_KEY_DEVICE_READY "crash_reporting_ready" +#define MSG_KEY_DEVICE_ERROR "crash_reporting_inject_error" + +static mbed_error_ctx saved_error_ctx = {0}; + +void mbed_error_reboot_callback(mbed_error_ctx *error_context) +{ + + TEST_ASSERT_EQUAL_PTR(error_context, &MBED_CRASH_DATA); + memcpy(&saved_error_ctx, error_context, sizeof(mbed_error_ctx)); + mbed_reset_reboot_error_info(); + + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_OUT_OF_MEMORY, saved_error_ctx.error_status); + TEST_ASSERT_EQUAL_UINT(1, saved_error_ctx.error_reboot_count); + + //Send the ready msg to host to indicate test pass + greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_DUMMY); +} + +void test_crash_reporting() +{ + //Clear any previous status + mbed_reset_reboot_error_info(); + + // Report readiness + greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_DUMMY); + printf("\nMessage sent: %s\n", MSG_KEY_DEVICE_READY); + + static char _key[MSG_KEY_LEN + 1] = { }; + static char _value[MSG_VALUE_LEN + 1] = { }; + + printf("\nWaiting for crash inject error message: %s\n", MSG_KEY_DEVICE_ERROR); + greentea_parse_kv(_key, _value, MSG_KEY_LEN, MSG_VALUE_LEN); + printf("\nCrash inject error message received\n"); + + if (strcmp(_key, MSG_KEY_DEVICE_ERROR) == 0) { + printf("\nForcing error\n"); + MBED_ERROR1(MBED_ERROR_OUT_OF_MEMORY, "Executing crash reporting test.", 0xDEADBAD); + TEST_ASSERT_MESSAGE(0, "crash_reporting() error call failed."); + } + TEST_ASSERT_MESSAGE(0, "Unexpected message received."); +} + +int main(void) +{ + GREENTEA_SETUP(40, "crash_reporting"); + test_crash_reporting(); + GREENTEA_TESTSUITE_RESULT(0); + + return 0; +} + +#endif // !MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED diff --git a/platform/tests/TESTS/mbed_platform/critical_section/main.cpp b/platform/tests/TESTS/mbed_platform/critical_section/main.cpp new file mode 100644 index 0000000..0fec9d1 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/critical_section/main.cpp @@ -0,0 +1,228 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest/utest.h" + + +using utest::v1::Case; + + +bool callback_called; + +void tiemout_callback(void) +{ + core_util_atomic_store(&callback_called, true); +} + +template +void critical_section_raii_recursive(Timeout &timeout) +{ + static uint32_t depth = 0; + CriticalSectionLock cs; + + depth++; + TEST_ASSERT_TRUE(core_util_in_critical_section()); + + if (depth < N) { + critical_section_raii_recursive(timeout); + } else { + // max depth reached - do the test + const us_timestamp_t timeout_time_us = 1; + const int wait_time_us = timeout_time_us * 100; + + timeout.attach_us(callback(tiemout_callback), timeout_time_us); + wait_us(wait_time_us); + } + TEST_ASSERT_TRUE(core_util_in_critical_section()); + TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called)); +} + + +/** Template for tests + + Test C API of critical section + Given a Timeout with callback attached + When before critical section + Then interrupts are enabled and timeout callback is fired + When inside critical section + Then interrupts are disabled and timeout callback is blocked + When after critical section + Then interrupts are enabled and timeout callback is fired + + Test C API of critical section - nested lock + Given a Timeout with callback attached + When before critical section + Then interrupts are enabled and timeout callback is fired + When inside nested critical section + Then interrupts are disabled and timeout callback is blocked + When after critical section + Then interrupts are enabled and timeout callback is fired + */ +template +void test_C_API(void) +{ + Timeout timeout; + const us_timestamp_t timeout_time_us = 1; + const int wait_time_us = timeout_time_us * 100; + + TEST_ASSERT_FALSE(core_util_in_critical_section()); + + core_util_atomic_store(&callback_called, false); + timeout.attach_us(callback(tiemout_callback), timeout_time_us); + wait_us(wait_time_us); + TEST_ASSERT_TRUE(core_util_atomic_exchange(&callback_called, false)); + + for (int i = 0; i < N; i++) { + core_util_critical_section_enter(); + TEST_ASSERT_TRUE(core_util_in_critical_section()); + } + + timeout.attach_us(callback(tiemout_callback), timeout_time_us); + wait_us(wait_time_us); + TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called)); + TEST_ASSERT_TRUE(core_util_in_critical_section()); + + for (int i = 0; i < N - 1; i++) { + core_util_critical_section_exit(); + TEST_ASSERT_TRUE(core_util_in_critical_section()); + TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called)); + } + + core_util_critical_section_exit(); + TEST_ASSERT_FALSE(core_util_in_critical_section()); + TEST_ASSERT_TRUE(core_util_atomic_load(&callback_called)); +} + +/** Template for tests + + Test C++ API of critical section constructor/destructor + Given a Timeout with callback attached + When before critical section + Then interrupts are enabled and timeout callback is fired + When inside critical section + Then interrupts are disabled and timeout callback is blocked + When after critical section + Then interrupts are enabled and timeout callback is fired + + Test C++ API of critical section constructor/destructor - nested lock + Given a Timeout with callback attached + When before critical section + Then interrupts are enabled and timeout callback is fired + When inside nested critical section + Then interrupts are disabled and timeout callback is blocked + When after critical section + Then interrupts are enabled and timeout callback is fired + */ +template +void test_CPP_API_constructor_destructor(void) +{ + Timeout timeout; + const us_timestamp_t timeout_time_us = 1; + const int wait_time_us = timeout_time_us * 100; + + TEST_ASSERT_FALSE(core_util_in_critical_section()); + + core_util_atomic_store(&callback_called, false); + timeout.attach_us(callback(tiemout_callback), timeout_time_us); + wait_us(wait_time_us); + TEST_ASSERT_TRUE(core_util_atomic_exchange(&callback_called, false)); + + critical_section_raii_recursive(timeout); + + TEST_ASSERT_FALSE(core_util_in_critical_section()); + TEST_ASSERT_TRUE(core_util_atomic_load(&callback_called)); +} + +/** Template for tests + + Test C++ API of critical section enable/disable + Given a Timeout with attached callback + When before critical section + Then interrupts are enabled and timeout callback is fired + When inside critical section + Then interrupts are disabled and timeout callback is blocked + When after critical section + Then interrupts are enabled and timeout callback is fired + + Test C++ API of critical section enable/disable - nested lock + Given a Timeout with attached callback + When before critical section + Then interrupts are enabled and timeout callback is fired + When inside nested critical section + Then interrupts are disabled and timeout callback is blocked + When after critical section + Then interrupts are enabled and timeout callback is fired + */ +template +void test_CPP_API_enable_disable(void) +{ + Timeout timeout; + const us_timestamp_t timeout_time_us = 1; + const int wait_time_us = timeout_time_us * 100; + + TEST_ASSERT_FALSE(core_util_in_critical_section()); + + core_util_atomic_store(&callback_called, false); + timeout.attach_us(callback(tiemout_callback), timeout_time_us); + wait_us(wait_time_us); + TEST_ASSERT_TRUE(core_util_atomic_exchange(&callback_called, false)); + + for (int i = 0; i < N; i++) { + CriticalSectionLock::enable(); + TEST_ASSERT_TRUE(core_util_in_critical_section()); + } + + timeout.attach_us(callback(tiemout_callback), timeout_time_us); + wait_us(wait_time_us); + TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called)); + TEST_ASSERT_TRUE(core_util_in_critical_section()); + + for (int i = 0; i < N - 1; i++) { + CriticalSectionLock::disable(); + TEST_ASSERT_TRUE(core_util_in_critical_section()); + TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called)); + } + + CriticalSectionLock::disable(); + TEST_ASSERT_FALSE(core_util_in_critical_section()); + TEST_ASSERT_TRUE(core_util_atomic_load(&callback_called)); +} + + +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 critical section C API", test_C_API<1>), + Case("Test critical section C API nested lock", test_C_API<10>), + Case("Test critical section C++ API constructor/destructor", test_CPP_API_constructor_destructor<1>), + Case("Test critical section C++ API constructor/destructor nested lock", test_CPP_API_constructor_destructor<10>), + Case("Test critical section C++ API enable/disable", test_CPP_API_enable_disable<1>), + Case("Test critical section C++ API enable/disable nested lock", test_CPP_API_enable_disable<10>) +}; + +utest::v1::Specification specification(test_setup, cases); + +int main() +{ + return !utest::v1::Harness::run(specification); +} diff --git a/platform/tests/TESTS/mbed_platform/error_handling/main.cpp b/platform/tests/TESTS/mbed_platform/error_handling/main.cpp new file mode 100644 index 0000000..cb97eb0 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/error_handling/main.cpp @@ -0,0 +1,380 @@ +/* mbed Microcontroller Library + * 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 "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" +#include "mbed.h" +#include +#include "HeapBlockDevice.h" + +using utest::v1::Case; + +/** Test error count and reset functionality + */ +void test_error_count_and_reset() +{ + int count = 7; + + //Log multiple errors and get the error count and make sure its 15 + for (int i = 0; i < count; i++) { + MBED_WARNING1(MBED_ERROR_OUT_OF_MEMORY, "Out of memory", i); + } + + TEST_ASSERT_EQUAL_INT(count, mbed_get_error_count()); + + //clear the errors and error count to 0 + mbed_clear_all_errors(); + + //Now the error count should be 0 + TEST_ASSERT_EQUAL_INT(0, mbed_get_error_count()); + +} + +/** Test error type encoding and test capturing of system, custom, posix errors + * and ensure the status/error code/type/error value is correct + */ +void test_error_capturing() +{ + uint32_t error_value = 0xAA11BB22; + mbed_error_ctx error_ctx = {0}; + + //first clear all errors and start afresh + + MBED_WARNING1(MBED_ERROR_OUT_OF_RESOURCES, "System type error", 0x1100); + mbed_error_status_t lastError = mbed_get_last_error(); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_TYPE_SYSTEM, MBED_GET_ERROR_TYPE(lastError)); + TEST_ASSERT_EQUAL_UINT(MBED_MODULE_UNKNOWN, MBED_GET_ERROR_MODULE(lastError)); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_CODE_OUT_OF_RESOURCES, MBED_GET_ERROR_CODE(lastError)); + + mbed_error_status_t error = MBED_MAKE_ERROR(MBED_MODULE_DRIVER_SERIAL, MBED_ERROR_CODE_OUT_OF_RESOURCES); + MBED_WARNING1(error, "Error Serial", 0xAA); + lastError = mbed_get_last_error(); + TEST_ASSERT_EQUAL_UINT(error, lastError); + + error = MBED_MAKE_CUSTOM_ERROR(MBED_MODULE_APPLICATION, MBED_ERROR_CODE_UNKNOWN); + MBED_WARNING1(error, "Custom Error Unknown", 0x1234); + lastError = mbed_get_last_error(); + TEST_ASSERT_EQUAL_UINT(error, lastError); + + MBED_WARNING1(MBED_ERROR_EPERM, "Posix Error Eperm", 0x1234); + lastError = mbed_get_last_error(); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_EPERM, lastError); + + error = MBED_MAKE_CUSTOM_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_CREATE_FAILED); + MBED_WARNING1(error, "Custom Error Type", error_value); + lastError = mbed_get_last_error(); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_TYPE_CUSTOM, MBED_GET_ERROR_TYPE(lastError)); + TEST_ASSERT_EQUAL_UINT(MBED_MODULE_PLATFORM, MBED_GET_ERROR_MODULE(lastError)); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_CODE_CREATE_FAILED, MBED_GET_ERROR_CODE(lastError)); + mbed_error_status_t status = mbed_get_last_error_info(&error_ctx); + TEST_ASSERT(status == MBED_SUCCESS); + TEST_ASSERT_EQUAL_UINT(error_value, error_ctx.error_value); + + error_value = 0xAABBCC; + MBED_WARNING1(MBED_ERROR_EACCES, "Posix Error", error_value); + lastError = mbed_get_last_error(); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_TYPE_POSIX, MBED_GET_ERROR_TYPE(lastError)); + TEST_ASSERT_EQUAL_UINT(MBED_MODULE_UNKNOWN, MBED_GET_ERROR_MODULE(lastError)); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_CODE_EACCES, MBED_GET_ERROR_CODE(lastError)); + status = mbed_get_last_error_info(&error_ctx); + TEST_ASSERT(status == MBED_SUCCESS); + TEST_ASSERT_EQUAL_UINT(error_value, error_ctx.error_value); + + error_value = 0; + error = MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_UNKNOWN); + MBED_WARNING1(error, "HAL Entity error", error_value); + lastError = mbed_get_last_error(); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_TYPE_SYSTEM, MBED_GET_ERROR_TYPE(lastError)); + TEST_ASSERT_EQUAL_UINT(MBED_MODULE_HAL, MBED_GET_ERROR_MODULE(lastError)); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_CODE_UNKNOWN, MBED_GET_ERROR_CODE(lastError)); + status = mbed_get_last_error_info(&error_ctx); + TEST_ASSERT(status == MBED_SUCCESS); + TEST_ASSERT_EQUAL_UINT(error_value, error_ctx.error_value); + + MBED_WARNING1(MBED_ERROR_MUTEX_LOCK_FAILED, "Mutex lock failed", 0x4455); + error = mbed_get_last_error(); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_MUTEX_LOCK_FAILED, error); + + error = mbed_get_first_error(); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_OUT_OF_RESOURCES, error); + +} + +/** Test error context capture + */ +void test_error_context_capture() +{ + uint32_t error_value = 0xABCD; + mbed_error_ctx error_ctx = {0}; + + MBED_WARNING1(MBED_ERROR_INVALID_ARGUMENT, "System type error", error_value); + mbed_error_status_t status = mbed_get_last_error_info(&error_ctx); + TEST_ASSERT(status == MBED_SUCCESS); + TEST_ASSERT_EQUAL_UINT(error_value, error_ctx.error_value); +#if defined(MBED_CONF_RTOS_PRESENT) + TEST_ASSERT_EQUAL_UINT((uint32_t)osThreadGetId(), error_ctx.thread_id); + + //Capture thread info and compare + osRtxThread_t *current_thread = osRtxInfo.thread.run.curr; + TEST_ASSERT_EQUAL_UINT((uint32_t)current_thread->thread_addr, error_ctx.thread_entry_address); + TEST_ASSERT_EQUAL_UINT((uint32_t)current_thread->stack_size, error_ctx.thread_stack_size); + TEST_ASSERT_EQUAL_UINT((uint32_t)current_thread->stack_mem, error_ctx.thread_stack_mem); +#if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED + TEST_ASSERT_EQUAL_STRING(MBED_FILENAME, error_ctx.error_filename); +#endif +#endif +} + +#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED +/** Test error logging functionality + */ +void test_error_logging() +{ + mbed_error_ctx error_ctx = {0}; + + //clear the current errors first + mbed_clear_all_errors(); + + //log 3 errors and retrieve them to ensure they are correct + MBED_WARNING1(MBED_ERROR_INVALID_ARGUMENT, "Invalid argument", 1); + MBED_WARNING1(MBED_ERROR_INVALID_SIZE, "Invalid size", 2); + MBED_WARNING1(MBED_ERROR_INVALID_FORMAT, "Invalid format", 3); + + mbed_error_status_t status = mbed_get_error_hist_info(0, &error_ctx); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_INVALID_ARGUMENT, error_ctx.error_status); + TEST_ASSERT_EQUAL_UINT(1, error_ctx.error_value); + + status = mbed_get_error_hist_info(1, &error_ctx); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_INVALID_SIZE, error_ctx.error_status); + TEST_ASSERT_EQUAL_UINT(2, error_ctx.error_value); + + status = mbed_get_error_hist_info(2, &error_ctx); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_INVALID_FORMAT, error_ctx.error_status); + TEST_ASSERT_EQUAL_UINT(3, error_ctx.error_value); + + //Log a bunch of errors to overflow the error log and retrieve them + MBED_WARNING1(MBED_ERROR_INVALID_ARGUMENT, "Invalid argument", 6); + MBED_WARNING1(MBED_ERROR_INVALID_SIZE, "Invalid size", 7); + MBED_WARNING1(MBED_ERROR_INVALID_FORMAT, "Invalid format", 8); + MBED_WARNING1(MBED_ERROR_NOT_READY, "Not ready error", 9); + + //Last 4 entries + MBED_WARNING1(MBED_ERROR_TIME_OUT, "Timeout error", 10); + MBED_WARNING1(MBED_ERROR_ALREADY_IN_USE, "Already in use error", 11); + MBED_WARNING1(MBED_ERROR_UNSUPPORTED, "Not supported", 12); + MBED_WARNING1(MBED_ERROR_ACCESS_DENIED, "Access denied", 13); + + status = mbed_get_error_hist_info(0, &error_ctx); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_TIME_OUT, error_ctx.error_status); + TEST_ASSERT_EQUAL_UINT(10, error_ctx.error_value); + + status = mbed_get_error_hist_info(1, &error_ctx); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_ALREADY_IN_USE, error_ctx.error_status); + TEST_ASSERT_EQUAL_UINT(11, error_ctx.error_value); + + status = mbed_get_error_hist_info(2, &error_ctx); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_UNSUPPORTED, error_ctx.error_status); + TEST_ASSERT_EQUAL_UINT(12, error_ctx.error_value); + + status = mbed_get_error_hist_info(3, &error_ctx); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_ACCESS_DENIED, error_ctx.error_status); + TEST_ASSERT_EQUAL_UINT(13, error_ctx.error_value); + + //Try an index which is invalid, we should get ERROR_INVALID_ARGUMENT back + status = mbed_get_error_hist_info(99, &error_ctx); + TEST_ASSERT_EQUAL_UINT(MBED_ERROR_INVALID_ARGUMENT, status); + +} + +#define NUM_TEST_THREADS 5 +#define THREAD_STACK_SIZE 512 + +//Error logger threads +void err_thread_func(mbed_error_status_t *error_status) +{ + MBED_WARNING1(*error_status, "Error from Multi-Threaded error logging test", *error_status); +} + + +/** Test error logging multithreaded + */ +void test_error_logging_multithread() +{ + uint8_t *dummy = new (std::nothrow) uint8_t[NUM_TEST_THREADS * THREAD_STACK_SIZE]; + TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory for test"); + delete[] dummy; + + mbed_error_ctx error_ctx = {0}; + int i; + Thread *errThread[NUM_TEST_THREADS]; + mbed_error_status_t error_status[NUM_TEST_THREADS] = { + MBED_ERROR_INVALID_ARGUMENT, MBED_ERROR_INVALID_DATA_DETECTED, MBED_ERROR_INVALID_FORMAT, MBED_ERROR_INVALID_SIZE, MBED_ERROR_INVALID_OPERATION + }; + + + for (i = 0; i < NUM_TEST_THREADS; i++) { + errThread[i] = new Thread(osPriorityNormal1, THREAD_STACK_SIZE, NULL, NULL); + errThread[i]->start(callback(err_thread_func, &error_status[i])); + } + ThisThread::sleep_for(2000); + for (i = 0; i < NUM_TEST_THREADS; i++) { + errThread[i]->join(); + } + + i = mbed_get_error_hist_count() - 1; + + for (; i >= 0; --i) { + mbed_error_status_t status = mbed_get_error_hist_info(i, &error_ctx); + if (status != MBED_SUCCESS) { + TEST_FAIL(); + } + + TEST_ASSERT_EQUAL_UINT((unsigned int)error_ctx.error_value, (unsigned int)error_ctx.error_status); + } +} +#endif + +#if defined(MBED_CONF_RTOS_PRESENT) +static Semaphore callback_sem; +void MyErrorHook(const mbed_error_ctx *error_ctx) +{ + callback_sem.release(); +} +#endif + +/** Test error hook + */ +#if defined(MBED_CONF_RTOS_PRESENT) +void test_error_hook() +{ + if (MBED_SUCCESS != mbed_set_error_hook(MyErrorHook)) { + TEST_FAIL(); + } + + MBED_WARNING1(MBED_ERROR_INVALID_ARGUMENT, "Test for error hook", 1234); + bool acquired = callback_sem.try_acquire_for(5000); + + TEST_ASSERT(acquired); +} +#endif + +#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED && defined(MBED_TEST_SIM_BLOCKDEVICE) + +// test configuration +#ifndef MBED_TEST_FILESYSTEM +#define MBED_TEST_FILESYSTEM LittleFileSystem +#endif + +#ifndef MBED_TEST_FILESYSTEM_DECL +#define MBED_TEST_FILESYSTEM_DECL MBED_TEST_FILESYSTEM fs("fs") +#endif + +#ifndef MBED_TEST_BLOCK_COUNT +#define MBED_TEST_BLOCK_COUNT 64 +#endif + +#ifndef MBED_TEST_SIM_BLOCKDEVICE_DECL +#define MBED_TEST_SIM_BLOCKDEVICE_DECL MBED_TEST_SIM_BLOCKDEVICE fd(MBED_TEST_BLOCK_COUNT*512, 1, 1, 512) +#endif + +// declarations +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x +#define INCLUDE(x) STRINGIZE(x.h) + +#include INCLUDE(MBED_TEST_FILESYSTEM) +#include INCLUDE(MBED_TEST_SIM_BLOCKDEVICE) + +MBED_TEST_FILESYSTEM_DECL; +MBED_TEST_SIM_BLOCKDEVICE_DECL; + +/** Test save error log + */ +void test_save_error_log() +{ + //Log some errors + MBED_WARNING1(MBED_ERROR_TIME_OUT, "Timeout error", 1); + MBED_WARNING1(MBED_ERROR_ALREADY_IN_USE, "Already in use error", 2); + MBED_WARNING1(MBED_ERROR_UNSUPPORTED, "Not supported error", 3); + MBED_WARNING1(MBED_ERROR_ACCESS_DENIED, "Access denied error", 4); + MBED_WARNING1(MBED_ERROR_ITEM_NOT_FOUND, "Not found error", 5); + + int error = 0; + + error = MBED_TEST_FILESYSTEM::format(&fd); + if (error < 0) { + TEST_FAIL_MESSAGE("Failed formatting"); + } + + error = fs.mount(&fd); + if (error < 0) { + TEST_FAIL_MESSAGE("Failed mounting fs"); + } + + if (MBED_SUCCESS != mbed_save_error_hist("/fs/errors.log")) { + TEST_FAIL_MESSAGE("Failed saving error log"); + } + + FILE *error_file = fopen("/fs/errors.log", "r"); + if (error_file == NULL) { + TEST_FAIL_MESSAGE("Unable to find error log in fs"); + } + + char buff[64] = {0}; + while (!feof(error_file)) { + int size = fread(&buff[0], 1, 15, error_file); + fwrite(&buff[0], 1, size, stdout); + } + fclose(error_file); + + error = fs.unmount(); + if (error < 0) { + TEST_FAIL_MESSAGE("Failed unmounting fs"); + } +} + +#endif + +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(120, "default_auto"); + return utest::v1::verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Test error counting and reset", test_error_count_and_reset), + Case("Test error encoding, value capture, first and last errors", test_error_capturing), + Case("Test error context capture", test_error_context_capture), +#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED + Case("Test error logging", test_error_logging), +#if MBED_CONF_RTOS_PRESENT + Case("Test error hook", test_error_hook), + Case("Test error handling multi-threaded", test_error_logging_multithread), +#endif //MBED_CONF_RTOS_PRESENT +#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED && defined(MBED_TEST_SIM_BLOCKDEVICE) + Case("Test error save log", test_save_error_log), +#endif //MBED_TEST_SIM_BLOCKDEVICE +#endif //MBED_CONF_ERROR_HIST_DISABLED +}; + +utest::v1::Specification specification(test_setup, cases); + +int main() +{ + return !utest::v1::Harness::run(specification); +} diff --git a/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/README.md b/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/README.md new file mode 100644 index 0000000..32c038e --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/README.md @@ -0,0 +1,9 @@ +# Description + +This document describes how to run minimal-printf tests. + +## Running tests + +You can use the following command to run tests: + +`mbed test -m K64F -t GCC_ARM -n *printf* -v -c --app-config TESTS/mbed_platform/minimal-printf/compliance/test_config.json` diff --git a/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/main.cpp b/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/main.cpp new file mode 100644 index 0000000..1633ddc --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/main.cpp @@ -0,0 +1,1095 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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. + */ + +#ifdef TARGET_LIKE_MBED +#include "mbed.h" +#endif +#include "mbed_printf.h" + +#include "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" + +#include +#include +#include +#include + +#ifndef ULLONG_MAX +#define ULLONG_MAX UINT64_MAX +#endif + +#ifndef LLONG_MAX +#define LLONG_MAX INT64_MAX +#endif + +#ifndef LLONG_MIN +#define LLONG_MIN INT64_MIN +#endif + +using namespace utest::v1; + +#define MAX_STRING_SIZE 100 +// Buffer used by test cases to store a test string +static char expected_string[MAX_STRING_SIZE]; + +#define BASE_10 10 +#define BASE_16 16 + +/** This function converts an integer into a string representing the integer in base 10 or base 16. + * + * @param value to be converted to a string. + * @param str is an array where to store the resulting null-terminated string. + * @param base used to represent the string. + * + * @return + * A pointer to the resulting null-terminated string, same as parameter str. + */ +static char *convert_to_string( + uint64_t value, + char str[], + int base = BASE_10, + bool is_negative = false) +{ + int i = 0; + + if (base != BASE_10 && base != BASE_16) { + MBED_ASSERT(0); + } + + if (value == 0) { + str[0] = '0'; + str[1] = '\0'; + return str; + } + + if (is_negative && ((long long) value < 0)) { + value = -value; + } + // Convert a value to a string stored in reverse order in memory. + while (value) { + int remainder = value % base; + str[i++] = (remainder > 9) ? (remainder - 10) + 'A' : remainder + '0'; + value = value / base; + } + + if (is_negative) { + str[i++] = '-'; + } + + str[i] = '\0'; + + // Reverse the string. + int start = 0; + int end = i - 1; + while (start < end) { + swap(*(str + start), *(str + end)); + start++; + end--; + } + return str; +} + +/** This function is using a global buffer to build the test string 'prefix + data + suffix' and + * returns its length. + * + * @param prefix is a null-terminated string. + * @param value to be converted to a string. + * @param base used to represent the string. + * @param suffix is a null-terminated string. + * @param is_negative is used to represent a positive or negative value + * + * @return + * string length + */ +static int make_test_string( + const char *prefix = nullptr, + long long value = 0, + int base = BASE_10, + const char *suffix = nullptr, + bool is_negative = false +) +{ + char *exp_str = &expected_string[0]; + int str_length = 0; + memset(exp_str, 0, MAX_STRING_SIZE); + if (prefix) { + str_length = strlen(prefix); + MBED_ASSERT(str_length < MAX_STRING_SIZE); + strncpy(exp_str, prefix, str_length); + } + + convert_to_string(value, &exp_str[str_length], base, is_negative); + if (suffix) { + str_length = strlen(exp_str); + MBED_ASSERT(strlen(suffix) < (MAX_STRING_SIZE - str_length)); + strncat(exp_str, suffix, str_length); + } + return strlen(exp_str); +} + +// Extract the prefix string which is all characters until '%'. +static void extract_prefix(const char *fmt, char *prefix) +{ + int i = 0; + while (fmt && prefix && fmt[i] != '%') { + prefix[i] = fmt[i]; + i++; + } +} + +static control_t test_printf_d(const size_t call_count) +{ + int result_baseline; + int result_minimal; + int result_file; + + /*************************************************************************/ + /*************************************************************************/ + result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MIN); + result_file = mbed_fprintf(stderr, "hhd: %hhd\r\n", SCHAR_MIN); + result_baseline = make_test_string("hhd: ", SCHAR_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MAX); + result_file = mbed_fprintf(stderr, "hhd: %hhd\r\n", SCHAR_MAX); + result_baseline = make_test_string("hhd: ", SCHAR_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MIN); + result_file = mbed_fprintf(stderr, "hd: %hd\r\n", SHRT_MIN); + result_baseline = make_test_string("hd: ", SHRT_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MAX); + result_file = mbed_fprintf(stderr, "hd: %hd\r\n", SHRT_MAX); + result_baseline = make_test_string("hd: ", SHRT_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("d: %d\r\n", INT_MIN); + result_file = mbed_fprintf(stderr, "d: %d\r\n", INT_MIN); + result_baseline = make_test_string("d: ", INT_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("d: %d\r\n", INT_MAX); + result_file = mbed_fprintf(stderr, "d: %d\r\n", INT_MAX); + result_baseline = make_test_string("d: ", INT_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("ld: %ld\r\n", LONG_MIN); + result_file = mbed_fprintf(stderr, "ld: %ld\r\n", LONG_MIN); + result_baseline = make_test_string("ld: ", LONG_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("ld: %ld\r\n", LONG_MAX); + result_file = mbed_fprintf(stderr, "ld: %ld\r\n", LONG_MAX); + result_baseline = make_test_string("ld: ", LONG_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MIN); + result_file = mbed_fprintf(stderr, "lld: %lld\r\n", LLONG_MIN); + result_baseline = make_test_string("lld: ", LLONG_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MAX); + result_file = mbed_fprintf(stderr, "lld: %lld\r\n", LLONG_MAX); + result_baseline = make_test_string("lld: ", LLONG_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + +#ifdef TARGET_LIKE_MBED + printf("%%jd not supported by mbed\r\n"); +#else + result_minimal = mbed_printf("jd: %jd\r\n", INT32_MIN); + result_file = mbed_fprintf(stderr, "jd: %jd\r\n", INT32_MIN); + result_baseline = make_test_string("jd: ", (intmax_t) INT32_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("jd: %jd\r\n", INT32_MAX); + result_file = mbed_fprintf(stderr, "jd: %jd\r\n", INT32_MAX); + result_baseline = make_test_string("jd: ", (intmax_t) INT32_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%zd not supported by mbed\r\n"); +#else + result_minimal = mbed_printf("zd: %zd\r\n", INT32_MIN); + result_file = mbed_fprintf(stderr, "zd: %zd\r\n", INT32_MIN); + result_baseline = make_test_string("zd: ", (ssize_t) INT32_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("zd: %zd\r\n", INT32_MAX); + result_file = mbed_fprintf(stderr, "zd: %zd\r\n", INT32_MAX); + result_baseline = make_test_string("zd: ", (ssize_t) INT32_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%td not supported by mbed\r\n"); +#else + result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MIN); + result_file = mbed_fprintf(stderr, "td: %td\r\n", PTRDIFF_MIN); + result_baseline = make_test_string("td: ", PTRDIFF_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MAX); + result_file = mbed_fprintf(stderr, "td: %td\r\n", PTRDIFF_MAX); + result_baseline = make_test_string("td: ", PTRDIFF_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); +#endif + + return CaseNext; +} + +static control_t test_printf_u(const size_t call_count) +{ + int result_baseline; + int result_minimal; + int result_file; + + /*************************************************************************/ + /*************************************************************************/ + result_minimal = mbed_printf("hhu: %hhu\r\n", 0); + result_file = mbed_fprintf(stderr, "hhu: %hhu\r\n", 0); + result_baseline = make_test_string("hhu: ", 0, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("hhu: %hhu\r\n", UCHAR_MAX); + result_file = mbed_fprintf(stderr, "hhu: %hhu\r\n", UCHAR_MAX); + result_baseline = make_test_string("hhu: ", UCHAR_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("hu: %hu\r\n", 0); + result_file = mbed_fprintf(stderr, "hu: %hu\r\n", 0); + result_baseline = make_test_string("hu: ", 0, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("hu: %hu\r\n", USHRT_MAX); + result_file = mbed_fprintf(stderr, "hu: %hu\r\n", USHRT_MAX); + result_baseline = make_test_string("hu: ", USHRT_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("u: %u\r\n", 0); + result_file = mbed_fprintf(stderr, "u: %u\r\n", 0); + result_baseline = make_test_string("u: ", 0, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("u: %u\r\n", UINT_MAX); + result_file = mbed_fprintf(stderr, "u: %u\r\n", UINT_MAX); + result_baseline = make_test_string("u: ", UINT_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("lu: %lu\r\n", 0UL); + result_file = mbed_fprintf(stderr, "lu: %lu\r\n", 0UL); + result_baseline = make_test_string("lu: ", 0UL, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("lu: %lu\r\n", ULONG_MAX); + result_file = mbed_fprintf(stderr, "lu: %lu\r\n", ULONG_MAX); + result_baseline = make_test_string("lu: ", ULONG_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("llu: %llu\r\n", 0ULL); + result_file = mbed_fprintf(stderr, "llu: %llu\r\n", 0ULL); + result_baseline = make_test_string("llu: ", 0ULL, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("llu: %llu\r\n", ULLONG_MAX); + result_file = mbed_fprintf(stderr, "llu: %llu\r\n", ULLONG_MAX); + result_baseline = make_test_string("llu: ", ULLONG_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + +#ifdef TARGET_LIKE_MBED + printf("%%ju not supported by mbed\r\n"); +#else + result_minimal = mbed_printf("ju: %ju\r\n", (uintmax_t) 0); + result_file = mbed_fprintf(stderr, "ju: %ju\r\n", (uintmax_t) 0); + result_baseline = make_test_string("ju: ", (uintmax_t) 0, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("ju: %ju\r\n", UINTMAX_MAX); + result_file = mbed_fprintf(stderr, "ju: %ju\r\n", UINTMAX_MAX); + result_baseline = make_test_string("ju: ", UINTMAX_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%zu not supported by mbed\r\n"); +#else + result_minimal = mbed_printf("zu: %zu\r\n", 0); + result_file = mbed_fprintf(stderr, "zu: %zu\r\n", 0); + result_baseline = make_test_string("zu: ", 0, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("zu: %zu\r\n", SIZE_MAX); + result_file = mbed_fprintf(stderr, "zu: %zu\r\n", SIZE_MAX); + result_baseline = make_test_string("zu: ", SIZE_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%tu not supported by mbed\r\n"); +#else + result_minimal = mbed_printf("tu: %tu\r\n", 0); + result_file = mbed_fprintf(stderr, "tu: %tu\r\n", 0); + result_baseline = make_test_string("tu: ", 0, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("tu: %tu\r\n", UINTPTR_MAX); + result_file = mbed_fprintf(stderr, "tu: %tu\r\n", UINTPTR_MAX); + result_baseline = make_test_string("tu: ", UINTPTR_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); +#endif + + return CaseNext; +} + +static control_t test_printf_x(const size_t call_count) +{ + int result_baseline; + int result_minimal; + int result_file; + + /*************************************************************************/ + /*************************************************************************/ + result_minimal = mbed_printf("hhX: %hhX\r\n", 0); + result_file = mbed_fprintf(stderr, "hhX: %hhX\r\n", 0); + result_baseline = make_test_string("hhX: ", 0, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("hhX: %hhX\r\n", UCHAR_MAX); + result_file = mbed_fprintf(stderr, "hhX: %hhX\r\n", UCHAR_MAX); + result_baseline = make_test_string("hhX: ", UCHAR_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("hX: %hX\r\n", 0); + result_file = mbed_fprintf(stderr, "hX: %hX\r\n", 0); + result_baseline = make_test_string("hX: ", 0, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("hX: %hX\r\n", USHRT_MAX); + result_file = mbed_fprintf(stderr, "hX: %hX\r\n", USHRT_MAX); + result_baseline = make_test_string("hX: ", USHRT_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("X: %X\r\n", 0); + result_file = mbed_fprintf(stderr, "X: %X\r\n", 0); + result_baseline = make_test_string("X: ", 0, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("X: %X\r\n", UINT_MAX); + result_file = mbed_fprintf(stderr, "X: %X\r\n", UINT_MAX); + result_baseline = make_test_string("X: ", UINT_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("lX: %lX\r\n", 0UL); + result_file = mbed_fprintf(stderr, "lX: %lX\r\n", 0UL); + result_baseline = make_test_string("lX: ", 0UL, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("lX: %lX\r\n", ULONG_MAX); + result_file = mbed_fprintf(stderr, "lX: %lX\r\n", ULONG_MAX); + result_baseline = make_test_string("lX: ", ULONG_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("llX: %llX\r\n", 0ULL); + result_file = mbed_fprintf(stderr, "llX: %llX\r\n", 0ULL); + result_baseline = make_test_string("llX: ", 0ULL, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("llX: %llX\r\n", ULLONG_MAX); + result_file = mbed_fprintf(stderr, "llX: %llX\r\n", ULLONG_MAX); + result_baseline = make_test_string("llX: ", ULLONG_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + +#ifdef TARGET_LIKE_MBED + printf("%%jX not supported by mbed\r\n"); +#else + result_minimal = mbed_printf("jX: %jX\r\n", (uintmax_t) 0); + result_file = mbed_fprintf(stderr, "jX: %jX\r\n", (uintmax_t) 0); + result_baseline = make_test_string("jX: ", (uintmax_t) 0, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("jX: %jX\r\n", UINTMAX_MAX); + result_file = mbed_fprintf(stderr, "jX: %jX\r\n", UINTMAX_MAX); + result_baseline = make_test_string("jX: ", UINTMAX_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%zX not supported by mbed\r\n"); +#else + result_minimal = mbed_printf("zX: %zX\r\n", 0); + result_file = mbed_fprintf(stderr, "zX: %zX\r\n", 0); + result_baseline = make_test_string("zX: ", 0, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("zX: %zX\r\n", SIZE_MAX); + result_file = mbed_fprintf(stderr, "zX: %zX\r\n", SIZE_MAX); + result_baseline = make_test_string("zX: ", SIZE_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%tX not supported by mbed\r\n"); +#else + result_minimal = mbed_printf("tX: %tX\r\n", 0); + result_file = mbed_fprintf(stderr, "tX: %tX\r\n", 0); + result_baseline = make_test_string("tX: ", 0, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + result_minimal = mbed_printf("tX: %tX\r\n", UINTPTR_MAX); + result_file = mbed_fprintf(stderr, "tX: %tX\r\n", UINTPTR_MAX); + result_baseline = make_test_string("tX: ", UINTPTR_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); +#endif + + result_minimal = mbed_printf("x: %x\r\n", 11259375); + result_baseline = make_test_string("x: ", 11259375, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + return CaseNext; +} + +static control_t test_printf_percent(const size_t call_count) +{ + int result_baseline; + int result_minimal; + int result_file; + char buffer_baseline[100] = {0}; + + result_minimal = mbed_printf("%% \r\n"); + result_file = mbed_fprintf(stderr, "%% \r\n"); + result_baseline = sprintf(buffer_baseline, "%% \r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_file); + + return CaseNext; +} + +/******************************************************************************/ +/* */ +/* SNPRINTF */ +/* */ +/******************************************************************************/ + +static control_t test_snprintf_d(const size_t call_count) +{ + char buffer_minimal[100]; + int result_baseline; + int result_minimal; + + /*************************************************************************/ + /*************************************************************************/ + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhd: %hhd\r\n", SCHAR_MIN); + result_baseline = make_test_string("hhd: ", SCHAR_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhd: %hhd\r\n", SCHAR_MAX); + result_baseline = make_test_string("hhd: ", SCHAR_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hd: %hd\r\n", SHRT_MIN); + result_baseline = make_test_string("hd: ", SHRT_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hd: %hd\r\n", SHRT_MAX); + result_baseline = make_test_string("hd: ", SHRT_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "d: %d\r\n", INT_MIN); + result_baseline = make_test_string("d: ", INT_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "d: %d\r\n", INT_MAX); + result_baseline = make_test_string("d: ", INT_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ld: %ld\r\n", LONG_MIN); + result_baseline = make_test_string("ld: ", LONG_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ld: %ld\r\n", LONG_MAX); + result_baseline = make_test_string("ld: ", LONG_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lld: %lld\r\n", LLONG_MIN); + result_baseline = make_test_string("lld: ", LLONG_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lld: %lld\r\n", LLONG_MAX); + result_baseline = make_test_string("lld: ", LLONG_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + +#ifdef TARGET_LIKE_MBED + printf("%%jd not supported by mbed\r\n"); +#else + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", (intmax_t) INT32_MIN); + result_baseline = make_test_string("jd: ", (intmax_t) INT32_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", (intmax_t) INT32_MAX); + result_baseline = make_test_string("jd: ", (intmax_t) INT32_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%zd not supported by mbed\r\n"); +#else + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", (ssize_t) INT32_MIN); + result_baseline = make_test_string("zd: ", (ssize_t) INT32_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", (ssize_t) INT32_MAX); + result_baseline = make_test_string("zd: ", (ssize_t) INT32_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%td not supported by mbed\r\n"); +#else + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "td: %td\r\n", PTRDIFF_MIN); + result_baseline = make_test_string("td: ", PTRDIFF_MIN, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "td: %td\r\n", PTRDIFF_MAX); + result_baseline = make_test_string("td: ", PTRDIFF_MAX, BASE_10, "\r\n", true); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + + int a = 2; + int b = 3; + result_minimal = mbed_snprintf(0, 0, "%d + %d = %d\n", a, b, a + b); + TEST_ASSERT_EQUAL_INT(10, result_minimal); + + return CaseNext; +} + +static control_t test_snprintf_u(const size_t call_count) +{ + char buffer_minimal[100]; + int result_baseline; + int result_minimal; + + /*************************************************************************/ + /*************************************************************************/ + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhu: %hhu\r\n", 0); + result_baseline = make_test_string("hhu: ", 0, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhu: %hhu\r\n", UCHAR_MAX); + result_baseline = make_test_string("hhu: ", UCHAR_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hu: %hu\r\n", 0); + result_baseline = make_test_string("hu: ", 0, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hu: %hu\r\n", USHRT_MAX); + result_baseline = make_test_string("hu: ", USHRT_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "u: %u\r\n", 0); + result_baseline = make_test_string("u: ", 0, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "u: %u\r\n", UINT_MAX); + result_baseline = make_test_string("u: ", UINT_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lu: %lu\r\n", 0UL); + result_baseline = make_test_string("lu: ", 0UL, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lu: %lu\r\n", ULONG_MAX); + result_baseline = make_test_string("lu: ", ULONG_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llu: %llu\r\n", 0ULL); + result_baseline = make_test_string("llu: ", 0ULL, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llu: %llu\r\n", ULLONG_MAX); + result_baseline = make_test_string("llu: ", ULLONG_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + +#ifdef TARGET_LIKE_MBED + printf("%%ju not supported by mbed\r\n"); +#else + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ju: %ju\r\n", (uintmax_t) 0); + result_baseline = make_test_string("ju: ", (uintmax_t) 0, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ju: %ju\r\n", UINTMAX_MAX); + result_baseline = make_test_string("ju: ", UINTMAX_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%zu not supported by mbed\r\n"); +#else + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zu: %zu\r\n", 0); + result_baseline = make_test_string("zu: ", 0, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zu: %zu\r\n", SIZE_MAX); + result_baseline = make_test_string("zu: ", SIZE_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%tu not supported by mbed\r\n"); +#else + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tu: %tu\r\n", 0); + result_baseline = make_test_string("tu: ", 0, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tu: %tu\r\n", UINTPTR_MAX); + result_baseline = make_test_string("tu: ", UINTPTR_MAX, BASE_10, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + + return CaseNext; +} + +static control_t test_snprintf_x(const size_t call_count) +{ + char buffer_minimal[100]; + int result_baseline; + int result_minimal; + + /*************************************************************************/ + /*************************************************************************/ + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhX: %hhX\r\n", 0); + result_baseline = make_test_string("hhX: ", 0, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhX: %hhX\r\n", UCHAR_MAX); + result_baseline = make_test_string("hhX: ", UCHAR_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hX: %hX\r\n", 0); + result_baseline = make_test_string("hX: ", 0, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hX: %hX\r\n", USHRT_MAX); + result_baseline = make_test_string("hX: ", USHRT_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "X: %X\r\n", 0); + result_baseline = make_test_string("X: ", 0, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "X: %X\r\n", UINT_MAX); + result_baseline = make_test_string("X: ", UINT_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lX: %lX\r\n", 0UL); + result_baseline = make_test_string("lX: ", 0UL, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lX: %lX\r\n", ULONG_MAX); + result_baseline = make_test_string("lX: ", ULONG_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llX: %llX\r\n", 0ULL); + result_baseline = make_test_string("llX: ", 0ULL, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llX: %llX\r\n", ULLONG_MAX); + result_baseline = make_test_string("llX: ", ULLONG_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + +#ifdef TARGET_LIKE_MBED + printf("%%jX not supported by mbed\r\n"); +#else + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jX: %jX\r\n", (uintmax_t) 0); + result_baseline = make_test_string("jX: ", (uintmax_t) 0, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jX: %jX\r\n", UINTMAX_MAX); + result_baseline = make_test_string("jX: ", UINTMAX_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%xX not supported by mbed\r\n"); +#else + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zX: %zX\r\n", 0); + result_baseline = make_test_string("zX: ", 0, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zX: %zX\r\n", SIZE_MAX); + result_baseline = make_test_string("zX: ", SIZE_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%tX not supported by mbed\r\n"); +#else + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tX: %tX\r\n", 0); + result_baseline = make_test_string("tX: ", 0, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tX: %tX\r\n", UINTPTR_MAX); + result_baseline = make_test_string("tX: ", UINTPTR_MAX, BASE_16, "\r\n"); + TEST_ASSERT_EQUAL_STRING(expected_string, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + + return CaseNext; +} + +static control_t test_snprintf_percent(const size_t call_count) +{ + char buffer_baseline[100]; + char buffer_minimal[100]; + int result_baseline; + int result_minimal; + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "%% \r\n"); + result_baseline = sprintf(buffer_baseline, "%% \r\n"); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + return CaseNext; +} + +static control_t test_snprintf_unsupported_specifier(const size_t call_count) +{ + char buffer_minimal[100]; + + TEST_ASSERT_NOT_EQUAL( + 0, + mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "%a \r\n", 5) + ); + TEST_ASSERT_EQUAL_STRING("%a \r\n", buffer_minimal); + + return CaseNext; +} + +#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT +static control_t test_printf_f(const size_t call_count) +{ + char buffer_baseline[100]; + int result_baseline; + int result_minimal; +#define CLEAN_BUFFER memset(buffer_baseline, 0x00, sizeof(buffer_baseline)) + /*************************************************************************/ + /*************************************************************************/ + double pi = 3.14159265359; + CLEAN_BUFFER; + result_minimal = mbed_printf("f: %f\r\n", 3.0089); + result_baseline = sprintf(buffer_baseline, "f: 3.008900\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + CLEAN_BUFFER; + result_minimal = mbed_printf("f: %f\r\n", 7.0); + result_baseline = sprintf(buffer_baseline, "f: 7.000000\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + CLEAN_BUFFER; + result_minimal = mbed_printf("f: %f\r\n", -1 * pi); + result_baseline = sprintf(buffer_baseline, "f: -3.141593\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + CLEAN_BUFFER; + result_minimal = mbed_printf("f: %f\r\n", 0.0); + result_baseline = sprintf(buffer_baseline, "f: 0.000000\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + CLEAN_BUFFER; + result_minimal = mbed_printf("f: %f\r\n", pi); + result_baseline = sprintf(buffer_baseline, "f: 3.141593\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + CLEAN_BUFFER; + result_minimal = mbed_printf("f: %f\r\n", 2.12345651); + result_baseline = sprintf(buffer_baseline, "f: 2.123457\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + CLEAN_BUFFER; + result_minimal = mbed_printf("f: %f\r\n", 2.12345649); + result_baseline = sprintf(buffer_baseline, "f: 2.123456\r\n"); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + return CaseNext; +} + +static control_t test_snprintf_f(const size_t call_count) +{ + char buffer_baseline[100]; + char buffer_minimal[100]; + int result_baseline; + int result_minimal; +#define CLEAN_BUFFER memset(buffer_baseline, 0x00, sizeof(buffer_baseline)) + /*************************************************************************/ + /*************************************************************************/ + + double pi = 3.14159265359; + CLEAN_BUFFER; + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", 3.0089); + result_baseline = sprintf(buffer_baseline, "f: 3.008900\r\n"); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + CLEAN_BUFFER; + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", 7.0); + result_baseline = sprintf(buffer_baseline, "f: 7.000000\r\n"); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + CLEAN_BUFFER; + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", -1 * pi); + result_baseline = sprintf(buffer_baseline, "f: -3.141593\r\n"); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + CLEAN_BUFFER; + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", 0.0); + result_baseline = sprintf(buffer_baseline, "f: 0.000000\r\n"); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + CLEAN_BUFFER; + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", pi); + result_baseline = sprintf(buffer_baseline, "f: 3.141593\r\n"); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + return CaseNext; +} +#endif + + +/* Generic buffer overflow test function. + * Template parameters: + * 'T' is the type being tested + * 'buf_size' is the buffer size used in tests + * 'base' is used to represent data in BASE_10 or BASE_16 numeral system + * Function parameters: + * 'fmt' is the format to use for sprintf + * 'data' is the data that will be printed + * 'is_negative' is true for negative number, false for positive number +*/ +template +static control_t test_snprintf_buffer_overflow_generic(const char *fmt, T data, bool is_negative = false) +{ + char buffer_baseline[buf_size]; + char buffer_minimal[buf_size]; + int result_baseline; + int result_minimal; + char prefix[buf_size] = { 0 }; + // fmt string has "format specifier: %format specifier" + // Extract the string preceding the first '%' from fmt. + extract_prefix(fmt, &prefix[0]); + result_baseline = make_test_string(prefix, data, base, nullptr, is_negative); + + /* empty buffer test */ + result_minimal = mbed_snprintf(buffer_minimal, 0, fmt, data); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + /* buffer isn't large enough, output needs to be truncated */ + result_minimal = mbed_snprintf(buffer_minimal, buf_size - 2, fmt, data); + snprintf(buffer_baseline, buf_size - 2, "%s", expected_string); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + /* buffer is one byte shorter than needed, string terminator must + be written and output must be truncated */ + result_minimal = mbed_snprintf(buffer_minimal, buf_size - 1, fmt, data); + snprintf(buffer_baseline, buf_size - 1, "%s", expected_string); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + /* buffer is just long enough */ + result_minimal = mbed_snprintf(buffer_minimal, buf_size, fmt, data); + snprintf(buffer_baseline, buf_size, "%s", expected_string); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + return CaseNext; +} + +/* Based on the generic buffer overflow function above, create tests for + each relevant data type. In each case, the buffer for printing will only + be large enough to fit the printed data. */ +static control_t test_snprintf_buffer_overflow_d(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("d: %d", -1024, true); +} + +static control_t test_snprintf_buffer_overflow_ld(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("ld: %ld", -1048576L, true); +} + +static control_t test_snprintf_buffer_overflow_lld(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("lld: %lld", -1099511627776LL, true); +} + +static control_t test_snprintf_buffer_overflow_u(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("u: %u", 1024); +} + +static control_t test_snprintf_buffer_overflow_lu(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("lu: %lu", 1048576UL); +} + +static control_t test_snprintf_buffer_overflow_llu(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("llu: %llu", 1099511627776ULL); +} + +static control_t test_snprintf_buffer_overflow_x(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("x: 0x%x", 0x400); +} + +static control_t test_snprintf_buffer_overflow_lx(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("lx: 0x%lx", 0x100000UL); +} + +static control_t test_snprintf_buffer_overflow_llx(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("llx: 0x%llx", 0x10000000000ULL); +} + +utest::v1::status_t greentea_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(30 * 60, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("printf %d", test_printf_d), + Case("snprintf %d", test_snprintf_d), + Case("printf %u", test_printf_u), + Case("snprintf %u", test_snprintf_u), + Case("printf %x", test_printf_x), + Case("snprintf %x", test_snprintf_x), + Case("printf %%", test_printf_percent), + Case("snprintf %%", test_snprintf_percent), + Case("snprintf unsupported specifier", test_snprintf_unsupported_specifier), +#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT + Case("printf %f", test_printf_f), + Case("snprintf %f", test_snprintf_f), +#endif + Case("snprintf buffer overflow %d", test_snprintf_buffer_overflow_d), + Case("snprintf buffer overflow %ld", test_snprintf_buffer_overflow_ld), + Case("snprintf buffer overflow %lld", test_snprintf_buffer_overflow_lld), + Case("snprintf buffer overflow %u", test_snprintf_buffer_overflow_u), + Case("snprintf buffer overflow %lu", test_snprintf_buffer_overflow_lu), + Case("snprintf buffer overflow %llu", test_snprintf_buffer_overflow_llu), + Case("snprintf buffer overflow %x", test_snprintf_buffer_overflow_x), + Case("snprintf buffer overflow %lx", test_snprintf_buffer_overflow_lx), + Case("snprintf buffer overflow %llx", test_snprintf_buffer_overflow_llx), +}; + +Specification specification(greentea_setup, cases, greentea_test_teardown_handler); + +int main() +{ + return !Harness::run(specification); +} diff --git a/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/mbed_printf.c b/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/mbed_printf.c new file mode 100644 index 0000000..ac39371 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/mbed_printf.c @@ -0,0 +1,66 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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 "mbed_printf_implementation.h" + +#include + + +int mbed_printf(const char *format, ...) +{ + va_list arguments; + va_start(arguments, format); + int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, stdout); + va_end(arguments); + + return result; +} + +int mbed_snprintf(char *buffer, size_t length, const char *format, ...) +{ + va_list arguments; + va_start(arguments, format); + int result = mbed_minimal_formatted_string(buffer, length, format, arguments, NULL); + va_end(arguments); + + return result; +} + +int mbed_vprintf(const char *format, va_list arguments) +{ + return mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, stdout); +} + +int mbed_vsnprintf(char *buffer, size_t length, const char *format, va_list arguments) +{ + return mbed_minimal_formatted_string(buffer, length, format, arguments, NULL); +} + +int mbed_fprintf(FILE *stream, const char *format, ...) +{ + va_list arguments; + va_start(arguments, format); + int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, stream); + va_end(arguments); + + return result; +} + +int mbed_vfprintf(FILE *stream, const char *format, va_list arguments) +{ + return mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, stream); +} diff --git a/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/mbed_printf.h b/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/mbed_printf.h new file mode 100644 index 0000000..7e9a8c7 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/mbed_printf.h @@ -0,0 +1,74 @@ +/* mbed Microcontroller Library + * Copyright (c) 2016 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_PRINTF_H +#define MBED_PRINTF_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Minimal printf + * + * Prints directly to stdio/UART without using malloc. + */ +int mbed_printf(const char *format, ...); + +/** + * Minimal snprintf + * + * Prints directly to buffer without using malloc. + */ +int mbed_snprintf(char *buffer, size_t length, const char *format, ...); + +/** + * Minimal printf + * + * Prints directly to stdio/UART without using malloc. + */ +int mbed_vprintf(const char *format, va_list arguments); + +/** + * Minimal snprintf + * + * Prints directly to buffer without using malloc. + */ +int mbed_vsnprintf(char *buffer, size_t length, const char *format, va_list arguments); + +/** + * Minimal fprintf + * + * Prints directly to file stream without using malloc. + */ +int mbed_fprintf(FILE *stream, const char *format, ...); + +/** + * Minimal vfprintf + * + * Prints directly to file stream without using malloc. + */ +int mbed_vfprintf(FILE *stream, const char *format, va_list arguments); + +#ifdef __cplusplus +} +#endif + +#endif // MBED_PRINTF_H diff --git a/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/test_config.json b/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/test_config.json new file mode 100644 index 0000000..084d441 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/minimal-printf/compliance/test_config.json @@ -0,0 +1,7 @@ +{ + "target_overrides": { + "*": { + "platform.minimal-printf-enable-floating-point": true + } + } +} diff --git a/platform/tests/TESTS/mbed_platform/stats_cpu/main.cpp b/platform/tests/TESTS/mbed_platform/stats_cpu/main.cpp new file mode 100644 index 0000000..85c2a4a --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/stats_cpu/main.cpp @@ -0,0 +1,121 @@ + +/* mbed Microcontroller Library + * 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 "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest/utest.h" + +#include "mbed.h" + +#if !defined(MBED_CPU_STATS_ENABLED) || !DEVICE_LPTICKER || !DEVICE_SLEEP +#error [NOT_SUPPORTED] test not supported +#else + +using namespace utest::v1; + +DigitalOut led1(LED1); + +// Targets with these cores have their RAM enough size to create threads with bigger stacks +#if defined(__CORTEX_A9) || defined(__CORTEX_M23) || defined(__CORTEX_M33) || defined(__CORTEX_M7) +#define MAX_THREAD_STACK 512 +#else +#define MAX_THREAD_STACK 384 +#endif + +#define SAMPLE_TIME 1000 // msec +#define LOOP_TIME 2000 // msec + +static int32_t wait_time = 5000; + +static void busy_thread() +{ + volatile uint64_t i = ~0; + + while (i--) { + led1 = !led1; + wait_us(wait_time); + } +} + +void get_cpu_usage() +{ + static uint64_t prev_idle_time = 0; + mbed_stats_cpu_t stats; + + while (1) { + mbed_stats_cpu_get(&stats); + uint64_t diff = (stats.idle_time - prev_idle_time); + uint8_t usage = 100 - ((diff * 100) / (SAMPLE_TIME * 1000)); + prev_idle_time = stats.idle_time; + TEST_ASSERT_NOT_EQUAL(0, usage); + ThisThread::sleep_for(SAMPLE_TIME); + } +} + +void test_cpu_info(void) +{ + mbed_stats_cpu_t stats; + // Additional read to make sure timer is initialized + mbed_stats_cpu_get(&stats); + ThisThread::sleep_for(3); + mbed_stats_cpu_get(&stats); + TEST_ASSERT_NOT_EQUAL(0, stats.uptime); + TEST_ASSERT_NOT_EQUAL(0, stats.idle_time); + return; +} + +void test_cpu_load(void) +{ + + Thread thread(osPriorityNormal, MAX_THREAD_STACK); + Thread thread_stats(osPriorityNormal, MAX_THREAD_STACK); + + thread.start(busy_thread); + thread_stats.start(get_cpu_usage); + + // Steadily increase the system load + for (int count = 1; ; count++) { + ThisThread::sleep_for(LOOP_TIME); + if (wait_time <= 0) { + break; + } + wait_time -= 1000; // usec + } + thread.terminate(); + thread_stats.terminate(); +} + +Case cases[] = { + Case("Test CPU Info", test_cpu_info), + Case("Test CPU load", test_cpu_load) +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(20, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + Harness::run(specification); +} + +#endif // !defined(MBED_CPU_STATS_ENABLED) || !DEVICE_LPTICKER || !DEVICE_SLEEP diff --git a/platform/tests/TESTS/mbed_platform/stats_heap/main.cpp b/platform/tests/TESTS/mbed_platform/stats_heap/main.cpp new file mode 100644 index 0000000..2e7dc98 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/stats_heap/main.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2013-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 + * + * 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 "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest/utest.h" +#include "mbed_stats.h" +#include +#include + +#if !defined(MBED_HEAP_STATS_ENABLED) +#error [NOT_SUPPORTED] test not supported +#else + +using namespace utest::v1; + +#define ALLOCATION_SIZE_DEFAULT 564 +#define ALLOCATION_SIZE_SMALL 124 +#define ALLOCATION_SIZE_LARGE 700 +#define ALLOCATION_SIZE_FAIL (1024 * 1024 *1024) + +typedef void *(*malloc_cb_t)(uint32_t size); + +static void *thunk_malloc(uint32_t size); +static void *thunk_calloc_1(uint32_t size); +static void *thunk_calloc_4(uint32_t size); +static void *thunk_realloc(uint32_t size); + +malloc_cb_t malloc_thunk_array[] = { + thunk_malloc, + thunk_calloc_1, + thunk_calloc_4, + thunk_realloc, +}; + +void test_case_malloc_free_size() +{ + mbed_stats_heap_t stats_start; + mbed_stats_heap_t stats_current; + void *data; + + mbed_stats_heap_get(&stats_start); + + for (uint32_t i = 0; i < sizeof(malloc_thunk_array) / sizeof(malloc_cb_t); i++) { + + // Allocate memory and assert size change + data = malloc_thunk_array[i](ALLOCATION_SIZE_DEFAULT); + TEST_ASSERT(data != NULL); + mbed_stats_heap_get(&stats_current); + uint32_t increase = stats_current.current_size - stats_start.current_size; + TEST_ASSERT_EQUAL_UINT32(ALLOCATION_SIZE_DEFAULT, increase); + 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); + } +} + +void test_case_allocate_zero() +{ + mbed_stats_heap_t stats_start; + mbed_stats_heap_t stats_current; + void *data; + + mbed_stats_heap_get(&stats_start); + + for (uint32_t i = 0; i < sizeof(malloc_thunk_array) / sizeof(malloc_cb_t); i++) { + + // Allocate memory and assert size change + data = malloc_thunk_array[i](0); + // Return can be NULL + mbed_stats_heap_get(&stats_current); + 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); + } +} + +void test_case_allocate_fail() +{ + mbed_stats_heap_t stats_start; + mbed_stats_heap_t stats_current; + void *data; + + mbed_stats_heap_get(&stats_start); + + for (uint32_t i = 0; i < sizeof(malloc_thunk_array) / sizeof(malloc_cb_t); i++) { + + // Trigger a failure by trying to allocate a buffer that won't fit + data = malloc_thunk_array[i](ALLOCATION_SIZE_FAIL); + TEST_ASSERT(data == NULL); + mbed_stats_heap_get(&stats_current); + 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_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); + } +} + +static void *thunk_malloc(uint32_t size) +{ + return malloc(size); +} + +static void *thunk_calloc_1(uint32_t size) +{ + return calloc(size / 1, 1); +} + +static void *thunk_calloc_4(uint32_t size) +{ + return calloc(size / 4, 4); +} + + +static void *thunk_realloc(uint32_t size) +{ + return realloc(NULL, size); +} + +void test_case_realloc_size() +{ + mbed_stats_heap_t stats_start; + mbed_stats_heap_t stats_current; + uint32_t increase; + void *data; + + mbed_stats_heap_get(&stats_start); + + // Allocate memory and assert size change + data = realloc(NULL, ALLOCATION_SIZE_DEFAULT); + TEST_ASSERT(data != NULL); + mbed_stats_heap_get(&stats_current); + increase = stats_current.current_size - stats_start.current_size; + TEST_ASSERT_EQUAL_UINT32(increase, ALLOCATION_SIZE_DEFAULT); + + // Decrease size and assert size change + data = realloc(data, ALLOCATION_SIZE_SMALL); + TEST_ASSERT(data != NULL); + mbed_stats_heap_get(&stats_current); + increase = stats_current.current_size - stats_start.current_size; + TEST_ASSERT_EQUAL_UINT32(increase, ALLOCATION_SIZE_SMALL); + + // Increase size and assert size change + data = realloc(data, ALLOCATION_SIZE_LARGE); + TEST_ASSERT(data != NULL); + mbed_stats_heap_get(&stats_current); + increase = stats_current.current_size - stats_start.current_size; + TEST_ASSERT_EQUAL_UINT32(increase, ALLOCATION_SIZE_LARGE); + + // 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); +} + +Case cases[] = { + Case("malloc and free size", test_case_malloc_free_size), + Case("allocate size zero", test_case_allocate_zero), + Case("allocation failure", test_case_allocate_fail), + Case("realloc size", test_case_realloc_size), +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(20, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + Harness::run(specification); +} + +#endif // !defined(MBED_HEAP_STATS_ENABLED) diff --git a/platform/tests/TESTS/mbed_platform/stats_sys/main.cpp b/platform/tests/TESTS/mbed_platform/stats_sys/main.cpp new file mode 100644 index 0000000..2ed7424 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/stats_sys/main.cpp @@ -0,0 +1,110 @@ + +/* mbed Microcontroller Library + * 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 "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest/utest.h" + +#include "mbed.h" + +#if !defined(MBED_SYS_STATS_ENABLED) +#error [NOT_SUPPORTED] test not supported +#else + +using namespace utest::v1; + +void test_sys_info() +{ + mbed_stats_sys_t stats; + mbed_stats_sys_get(&stats); + + TEST_ASSERT_NOT_EQUAL(0, stats.os_version); +#if defined(__CORTEX_M) + TEST_ASSERT_NOT_EQUAL(0, stats.cpu_id); +#endif + +#if defined(__IAR_SYSTEMS_ICC__) + TEST_ASSERT_EQUAL(IAR, stats.compiler_id); +#elif defined(__ARMCC_VERSION) + TEST_ASSERT_EQUAL(ARM, stats.compiler_id); +#elif defined(__GNUC__) + TEST_ASSERT_EQUAL(GCC_ARM, stats.compiler_id); +#endif + TEST_ASSERT_NOT_EQUAL(0, stats.compiler_version); + + // RAM / ROM sizes should not be zero and should match the define +#if defined(MBED_ROM_START) && defined(MBED_ROM_SIZE) + TEST_ASSERT_NOT_EQUAL(0, stats.rom_size[0]); + TEST_ASSERT_EQUAL(MBED_ROM_SIZE, stats.rom_size[0]); + TEST_ASSERT_EQUAL(MBED_ROM_START, stats.rom_start[0]); +#endif +#if defined(MBED_RAM_START) && defined(MBED_RAM_SIZE) + TEST_ASSERT_NOT_EQUAL(0, stats.ram_size[0]); + TEST_ASSERT_EQUAL(MBED_RAM_START, stats.ram_start[0]); + TEST_ASSERT_EQUAL(MBED_RAM_SIZE, stats.ram_size[0]); +#endif +#if defined(MBED_RAM1_START) && defined(MBED_RAM1_SIZE) + TEST_ASSERT_NOT_EQUAL(0, stats.ram_size[1]); + TEST_ASSERT_EQUAL(MBED_RAM1_SIZE, stats.ram_size[1]); + TEST_ASSERT_EQUAL(MBED_RAM1_START, stats.ram_start[1]); +#endif +#if defined(MBED_RAM2_START) && defined(MBED_RAM2_SIZE) + TEST_ASSERT_NOT_EQUAL(0, stats.ram_size[2]); + TEST_ASSERT_EQUAL(MBED_RAM2_SIZE, stats.ram_size[2]); + TEST_ASSERT_EQUAL(MBED_RAM2_START, stats.ram_start[2]); +#endif +#if defined(MBED_RAM3_START) && defined(MBED_RAM3_SIZE) + TEST_ASSERT_NOT_EQUAL(0, stats.ram_size[3]); + TEST_ASSERT_EQUAL(MBED_RAM3_SIZE, stats.ram_size[3]); + TEST_ASSERT_EQUAL(MBED_RAM3_START, stats.ram_start[3]); +#endif +#if defined(MBED_ROM1_START) && defined(MBED_ROM1_SIZE) + TEST_ASSERT_NOT_EQUAL(0, stats.rom_size[1]); + TEST_ASSERT_EQUAL(MBED_ROM1_SIZE, stats.rom_size[1]); + TEST_ASSERT_EQUAL(MBED_ROM1_START, stats.rom_start[1]); +#endif +#if defined(MBED_ROM2_START) && defined(MBED_ROM2_SIZE) + TEST_ASSERT_NOT_EQUAL(0, stats.rom_size[2]); + TEST_ASSERT_EQUAL(MBED_ROM2_SIZE, stats.rom_size[2]); + TEST_ASSERT_EQUAL(MBED_ROM2_START, stats.rom_start[2]); +#endif +#if defined(MBED_ROM3_START) && defined(MBED_ROM3_SIZE) + TEST_ASSERT_NOT_EQUAL(0, stats.rom_size[3]); + TEST_ASSERT_EQUAL(MBED_ROM3_SIZE, stats.rom_size[3]); + TEST_ASSERT_EQUAL(MBED_ROM3_START, stats.rom_start[3]); +#endif +} + +Case cases[] = { + Case("Test Sys Info", test_sys_info) +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(20, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + Harness::run(specification); +} + +#endif // !defined(MBED_SYS_STATS_ENABLED) diff --git a/platform/tests/TESTS/mbed_platform/stats_thread/main.cpp b/platform/tests/TESTS/mbed_platform/stats_thread/main.cpp new file mode 100644 index 0000000..f1e386a --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/stats_thread/main.cpp @@ -0,0 +1,179 @@ + +/* mbed Microcontroller Library + * 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 "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest/utest.h" + +#include "mbed.h" + +#if !defined(MBED_THREAD_STATS_ENABLED) +#error [NOT_SUPPORTED] test not supported +#else + +using namespace utest::v1; + +static EventFlags ef; +static int32_t counter = 0; + +#define TEST_STACK_SIZE 320 +#define FLAG_SIGNAL_DEC 0x2 +#define MAX_THREAD_STATS 0x8 + +void decrement_on_event() +{ + uint32_t ret = ef.wait_all(FLAG_SIGNAL_DEC); + TEST_ASSERT_FALSE(ret & osFlagsError); + TEST_ASSERT_EQUAL(FLAG_SIGNAL_DEC, ret); + counter--; +} + +void increment_with_delay() +{ + while (1) { + counter++; + ThisThread::sleep_for(500); + } +} + +void test_case_single_thread_stats() +{ + mbed_stats_thread_t *stats = new mbed_stats_thread_t[MAX_THREAD_STATS]; + int old_count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); + Thread t1(osPriorityNormal, TEST_STACK_SIZE, NULL, "Th1"); + t1.start(increment_with_delay); + + // Read stats + int count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); + TEST_ASSERT_EQUAL(1, (count - old_count)); + + for (int i = 0; i < count; i++) { + if (0 == strcmp(stats[i].name, "Th1")) { + TEST_ASSERT_EQUAL(TEST_STACK_SIZE, stats[i].stack_size); + TEST_ASSERT_EQUAL(osPriorityNormal, stats[i].priority); + break; + } + } + + t1.terminate(); + delete[] stats; +} + +#define SINGLE_ELEMENT 1 +void test_case_less_count() +{ + // Default Mbed OS has 3 threads + mbed_stats_thread_t stats; + int count = mbed_stats_thread_get_each(&stats, SINGLE_ELEMENT); + TEST_ASSERT_EQUAL(SINGLE_ELEMENT, count); +} + +void test_case_multi_threads_blocked() +{ + mbed_stats_thread_t *stats = new mbed_stats_thread_t[MAX_THREAD_STATS]; + int old_count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); + + Thread t1(osPriorityNormal, TEST_STACK_SIZE, NULL, "Th1"); + Thread t2(osPriorityNormal1, TEST_STACK_SIZE, NULL, "Th2"); + t1.start(increment_with_delay); + t2.start(decrement_on_event); + + // Read stats + + int count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); + TEST_ASSERT_EQUAL(2, (count - old_count)); + for (int i = 0; i < count; i++) { + if (0 == strcmp(stats[i].name, "Th2")) { + TEST_ASSERT_EQUAL(TEST_STACK_SIZE, stats[i].stack_size); + TEST_ASSERT_EQUAL(osPriorityNormal1, stats[i].priority); + TEST_ASSERT_EQUAL(osThreadBlocked, stats[i].state); + } else if (0 == strcmp(stats[i].name, "Th1")) { + TEST_ASSERT_EQUAL(TEST_STACK_SIZE, stats[i].stack_size); + TEST_ASSERT_EQUAL(osPriorityNormal, stats[i].priority); + } + } + + // Signal blocked thread + uint32_t ret = ef.set(FLAG_SIGNAL_DEC); + TEST_ASSERT_FALSE(ret & osFlagsError); + + ThisThread::sleep_for(100); + + count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); + TEST_ASSERT_EQUAL(1, (count - old_count)); + + t1.terminate(); + delete[] stats; +} + +void test_case_multi_threads_terminate() +{ + mbed_stats_thread_t *stats = new mbed_stats_thread_t[MAX_THREAD_STATS]; + int old_count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); + + Thread t1(osPriorityNormal1, TEST_STACK_SIZE, NULL, "Th1"); + Thread t2(osPriorityNormal2, TEST_STACK_SIZE, NULL, "Th2"); + t2.start(increment_with_delay); + t1.start(decrement_on_event); + + // Read stats + + int count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); + TEST_ASSERT_EQUAL(2, (count - old_count)); + + for (int i = 0; i < count; i++) { + if (0 == strcmp(stats[i].name, "Th2")) { + TEST_ASSERT_EQUAL(TEST_STACK_SIZE, stats[i].stack_size); + TEST_ASSERT_EQUAL(osPriorityNormal2, stats[i].priority); + } else if (0 == strcmp(stats[i].name, "Th1")) { + TEST_ASSERT_EQUAL(TEST_STACK_SIZE, stats[i].stack_size); + TEST_ASSERT_EQUAL(osPriorityNormal1, stats[i].priority); + TEST_ASSERT_EQUAL(osThreadBlocked, stats[i].state); + } + } + + t1.terminate(); + t2.terminate(); + + count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS); + TEST_ASSERT_EQUAL(count, old_count); + + delete[] stats; +} + +Case cases[] = { + Case("Single Thread Stats", test_case_single_thread_stats), + Case("Less count value", test_case_less_count), + Case("Multiple Threads blocked", test_case_multi_threads_blocked), + Case("Multiple Threads terminate", test_case_multi_threads_terminate), +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(20, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + Harness::run(specification); +} + +#endif // !defined(MBED_THREAD_STATS_ENABLED) diff --git a/platform/tests/TESTS/mbed_platform/system_reset/main.cpp b/platform/tests/TESTS/mbed_platform/system_reset/main.cpp new file mode 100644 index 0000000..f1f00e7 --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/system_reset/main.cpp @@ -0,0 +1,52 @@ +/* mbed Microcontroller Library + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" + +#define MSG_VALUE_DUMMY "0" +#define MSG_VALUE_LEN 16 +#define MSG_KEY_LEN 16 + +#define MSG_KEY_DEVICE_READY "ready" +#define MSG_KEY_DEVICE_RESET "reset" + +void test_system_reset() +{ + // Report readiness + greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_DUMMY); + + static char _key[MSG_KEY_LEN + 1] = { }; + static char _value[MSG_VALUE_LEN + 1] = { }; + + greentea_parse_kv(_key, _value, MSG_KEY_LEN, MSG_VALUE_LEN); + if (strcmp(_key, MSG_KEY_DEVICE_RESET) == 0) { + system_reset(); + TEST_ASSERT_MESSAGE(0, "system_reset() did not reset the device as expected."); + } + + TEST_ASSERT_MESSAGE(0, "Unexpected message key."); +} + +int main(void) +{ + GREENTEA_SETUP(30, "system_reset"); + test_system_reset(); + GREENTEA_TESTSUITE_RESULT(0); // Fail on any error. + + return 0; +} diff --git a/platform/tests/TESTS/mbed_platform/wait_ns/main.cpp b/platform/tests/TESTS/mbed_platform/wait_ns/main.cpp new file mode 100644 index 0000000..9d8743b --- /dev/null +++ b/platform/tests/TESTS/mbed_platform/wait_ns/main.cpp @@ -0,0 +1,103 @@ +/* + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "platform/mbed_wait_api.h" +#include "hal/us_ticker_api.h" +#include "hal/lp_ticker_api.h" + +//FastModels not support timing test +#if defined(TARGET_ARM_FM) +#error [NOT_SUPPORTED] test not supported +#else + +using namespace utest::v1; + +/* This test is created based on the test for Timer class. + * Since low power timer is less accurate than regular + * timer we need to adjust delta. + */ + +/* + * Define tolerance as follows: + * Timer might be +/-5% out; wait_ns is permitted 40% slow, but not fast. + * Therefore minimum measured time should be 95% of requested, maximum should + * be 145%. Unity doesn't let us specify an asymmetric error though. + * + * Would be nice to have tighter upper tolerance, but in practice we've seen + * a few devices unable to sustain theoretical throughput - flash wait states? + */ +#define TOLERANCE_MIN 0.95f +#define TOLERANCE_MAX 1.45f +#define MIDPOINT ((TOLERANCE_MIN+TOLERANCE_MAX)/2) +#define DELTA (MIDPOINT-TOLERANCE_MIN) + +/* This test verifies if wait_ns's wait time + * is accurate, according to a timer. + * + * Given timer is created. + * When timer is used to measure delay. + * Then the results are valid (within acceptable range). + */ +template +void test_wait_ns_time_measurement() +{ + CompareTimer timer; + + float wait_val_s = (float)wait_val_ms / 1000; + + /* Start the timer. */ + timer.start(); + + /* Wait ms - arithmetic inside wait_ns will overflow if + * asked for too large a delay, so break it up. + */ + for (int i = 0; i < wait_val_ms; i++) { + wait_ns(1000000); + } + + /* Stop the timer. */ + timer.stop(); + + /* Check results - wait_val_us us have elapsed. */ + TEST_ASSERT_FLOAT_WITHIN(DELTA * wait_val_s, MIDPOINT * wait_val_s, timer.read()); +} + +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(15, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { +#if DEVICE_LPTICKER + Case("Test: wait_ns - compare with lp_timer 1s", test_wait_ns_time_measurement<1000, LowPowerTimer>), +#endif + Case("Test: wait_ns - compare with us_timer 1s", test_wait_ns_time_measurement<1000, Timer>) +}; + +Specification specification(test_setup, cases); + +int main() +{ + return !Harness::run(specification); +} + +#endif // defined(TARGET_ARM_FM) diff --git a/platform/tests/UNITTESTS/ATCmdParser/test_ATCmdParser.cpp b/platform/tests/UNITTESTS/ATCmdParser/test_ATCmdParser.cpp new file mode 100644 index 0000000..dbe81c5 --- /dev/null +++ b/platform/tests/UNITTESTS/ATCmdParser/test_ATCmdParser.cpp @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2019, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" +#include "ATCmdParser.h" +#include +#include +#include +#include +#include "FileHandle_stub.h" +#include "mbed_poll_stub.h" + +using namespace mbed; + +static bool expected_oob_callback = false; + +void urc_callback() +{ + EXPECT_TRUE(expected_oob_callback); +} + + +// AStyle ignored as the definition is not clear due to preprocessor usage +// *INDENT-OFF* +class test_ATCmdParser : public testing::Test { +protected: + + void SetUp() + { + filehandle_stub_short_value_counter = 0; + } + + void TearDown() + { + } +}; +// *INDENT-ON* + + +TEST_F(test_ATCmdParser, test_ATCmdParser_create) +{ + FileHandle_stub fh1; + + ATCmdParser *at = new ATCmdParser(&fh1, ","); + at->set_delimiter("\r"); + at->set_timeout(5000); + at->debug_on(1); + + delete at; + + at = new ATCmdParser(&fh1, "\r"); + + EXPECT_TRUE(at != NULL); + delete at; +} + +TEST_F(test_ATCmdParser, test_ATCmdParser_set_timeout) +{ + FileHandle_stub fh1; + + ATCmdParser at(&fh1, ","); + at.set_timeout(8); + at.set_timeout(80); +} + + + +TEST_F(test_ATCmdParser, test_ATCmdParser_process_oob) +{ + FileHandle_stub fh1; + + ATCmdParser at(&fh1); + at.set_timeout(10); + + at.process_oob(); + + filehandle_stub_short_value_counter = 1; + fh1.short_value = POLLIN; + at.oob("s", &urc_callback); + at.process_oob(); + + filehandle_stub_short_value_counter = 2; + at.process_oob(); + + char buf[5] = {0}; + char table[] = "ssssssssssssssssssssssssssssssss\0"; + filehandle_stub_table = table; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + at.read(buf, 5); + + filehandle_stub_short_value_counter = 2; + expected_oob_callback = true; + at.process_oob(); + expected_oob_callback = false; + + filehandle_stub_table_pos = 0; + at.read(buf, 5); + + filehandle_stub_short_value_counter = 1; + expected_oob_callback = true; + at.process_oob(); + expected_oob_callback = false; + + char table2[5]; + table2[0] = '\r'; + table2[1] = '\r'; + table2[2] = '\n'; + table2[3] = '\n'; + table2[4] = 0; + filehandle_stub_table = table2; + + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + at.read(buf, 1); + + filehandle_stub_short_value_counter = 1; + at.process_oob(); + + filehandle_stub_table = table; + + filehandle_stub_short_value_counter = 0; + filehandle_stub_table_pos = 0; + filehandle_stub_table = NULL; +} + + + +TEST_F(test_ATCmdParser, test_ATCmdParser_flush) +{ + FileHandle_stub fh1; + + ATCmdParser at(&fh1, ","); + filehandle_stub_short_value_counter = 1; + fh1.short_value = POLLIN; + at.flush(); +} + +TEST_F(test_ATCmdParser, test_ATCmdParser_write) +{ + FileHandle_stub fh1; + + ATCmdParser at(&fh1, ","); + fh1.size_value = -1; + EXPECT_TRUE(-1 == at.write("help", 4)); + + mbed_poll_stub::revents_value = POLLOUT; + mbed_poll_stub::int_value = 1; + fh1.size_value = -1; + EXPECT_TRUE(-1 == at.write("help", 4)); + + mbed_poll_stub::revents_value = POLLOUT; + mbed_poll_stub::int_value = 1; + fh1.size_value = 7; + EXPECT_EQ(4, at.write("help", 4)); +} + +TEST_F(test_ATCmdParser, test_ATCmdParser_set_delimiter) +{ + FileHandle_stub fh1; + + ATCmdParser at(&fh1, ","); + at.set_delimiter("+"); +} + +TEST_F(test_ATCmdParser, test_ATCmdParser_read) +{ + FileHandle_stub fh1; + filehandle_stub_table = NULL; + filehandle_stub_table_pos = 0; + + ATCmdParser at(&fh1, ","); + char buf[8] = {0}; + + + // TEST EMPTY BUFFER + // Shouldn't read any byte since buffer is empty + EXPECT_TRUE(-1 == at.read(buf, 1)); + // Return error due to error set to at handler by the above call on empty buffer + EXPECT_TRUE(-1 == at.read(buf, 1)); + + // TEST DATA IN BUFFER + char table1[] = "1234512345678OK\r\n\0"; + filehandle_stub_table = table1; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + + // Read 5 bytes + EXPECT_EQ(5, at.read(buf, 5)); + EXPECT_TRUE(!memcmp(buf, table1, 5)); + // get_char triggered above should have filled in the whole reading buffer + EXPECT_EQ(filehandle_stub_table_pos, (strlen(buf))); + // Read another 8 bytes + EXPECT_TRUE(8 == at.read(buf, 8) && !memcmp(buf, table1 + 5, 8)); + // Reading more than the 4 bytes left -> ERROR + EXPECT_EQ(-1, at.read(buf, 5)); +} + +TEST_F(test_ATCmdParser, test_ATCmdParser_debug_on) +{ + FileHandle_stub fh1; + + ATCmdParser at(&fh1, ","); + at.debug_on(true); + at.debug_on(false); +} + +TEST_F(test_ATCmdParser, test_ATCmdParser_abort) +{ + FileHandle_stub fh1; + + ATCmdParser at(&fh1, ","); + at.abort(); +} + +TEST_F(test_ATCmdParser, test_ATCmdParser_printf) +{ + FileHandle_stub fh1; + + ATCmdParser at(&fh1); + at.flush(); + at.debug_on(true); + + const char * format = "TEST %d %s %x %c TEST \r\r\n\n"; + mbed_poll_stub::revents_value = POLLOUT; + mbed_poll_stub::int_value = 1; + fh1.size_value = 64; + + EXPECT_EQ(22, at.printf(format, 5, "t", 0x5, 't')); + + fh1.size_value = -1; + EXPECT_EQ(-1, at.printf(format, 5, "t", 0x5, 't')); +} + +TEST_F(test_ATCmdParser, test_ATCmdParser_send) +{ + FileHandle_stub fh1; + + ATCmdParser at(&fh1); + at.flush(); + at.debug_on(true); + + const char * format = "TEST %d %s %x %c TEST \r\r\n\n"; + mbed_poll_stub::revents_value = POLLOUT; + mbed_poll_stub::int_value = 1; + fh1.size_value = 64; + + //VALID printf + EXPECT_TRUE(at.send(format, 5, "t", 0x5, 't')); + EXPECT_TRUE(at.send("")); + + fh1.size_value = -1; + EXPECT_FALSE(at.send(format, 5, "t", 0x5, 't')); + EXPECT_FALSE(at.send("")); +} + +TEST_F(test_ATCmdParser, test_ATCmdParser_recv) +{ + FileHandle_stub fh1; + ATCmdParser at(&fh1, "\r", 8); + + //parse valid char + char table1[] = "s"; + at.flush(); + filehandle_stub_table = table1; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + char c; + EXPECT_TRUE(at.recv("%c", &c)); + EXPECT_EQ(c, 's'); + + //too large response + char table2[] = "1234567890\n"; + at.flush(); + filehandle_stub_table = table2; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + EXPECT_FALSE(at.recv("123456789%c\n", &c)); + + //back to normal buffer + ATCmdParser at1(&fh1); + at1.flush(); + filehandle_stub_table = table2; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + EXPECT_TRUE(at1.recv("123456789%c\n", &c)); + + char table3[] = "s\r\n\0"; + at1.flush(); + filehandle_stub_table = table3; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + EXPECT_TRUE(at.recv("%c", &c)); + EXPECT_EQ(c, 's'); + + char table4[] = "s 1 E test\r\n"; + char text[5]; + int hexval; + int intval; + at1.flush(); + filehandle_stub_table = table4; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + EXPECT_TRUE(at1.recv("%c %d %x %s", &c, &intval, &hexval, &text)); + EXPECT_EQ(c, 's'); + EXPECT_EQ(intval, 1); + EXPECT_EQ(hexval, 0xE); + EXPECT_EQ(!memcmp(text, "test", 4), 0); + + char table5[] = "s 1 E test\r\nt 2 F tes2\r\n"; + char c1; + char text1[5]; + int hexval1; + int intval1; + at1.flush(); + filehandle_stub_table = table5; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + + expected_oob_callback = true; + at1.oob("s", &urc_callback); + EXPECT_TRUE(at1.recv("%c %d %x %s\r\n%c %d %x %s\r\n", &c, &intval, &hexval, &text, &c, &intval, &hexval, &text)); + expected_oob_callback = false; + EXPECT_EQ(c, 't'); + EXPECT_EQ(intval, 2); + EXPECT_EQ(hexval, 0xF); + EXPECT_EQ(memcmp(text, "tes2", 4), 0); + +} + +TEST_F(test_ATCmdParser, test_ATCmdParser_scanf) +{ + FileHandle_stub fh1; + ATCmdParser at(&fh1, "\r"); + + //parse valid char + char table1[] = "s"; + at.flush(); + filehandle_stub_table = table1; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + char c; + EXPECT_TRUE(at.scanf("%c", &c)); + EXPECT_EQ(c, 's'); + + //back to normal buffer + char table2[] = "1234567890\n"; + at.flush(); + filehandle_stub_table = table2; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + EXPECT_TRUE(at.scanf("123456789%c\n", &c)); + + char table3[] = "s\r\n\0"; + at.flush(); + filehandle_stub_table = table3; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + EXPECT_TRUE(at.scanf("%c", &c)); + EXPECT_EQ(c, 's'); + + char table4[] = "s 1 E test\r\n"; + char text[5]; + memset(text, 0, 5); + int hexval; + int intval; + at.flush(); + filehandle_stub_table = table4; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + EXPECT_TRUE(at.scanf("%c %d %x %s", &c, &intval, &hexval, &text)); + EXPECT_EQ(c, 's'); + EXPECT_EQ(intval, 1); + EXPECT_EQ(hexval, 0xE); + EXPECT_EQ(!memcmp(text, "test", 4), 0); + +} + + diff --git a/platform/tests/UNITTESTS/ATCmdParser/unittest.cmake b/platform/tests/UNITTESTS/ATCmdParser/unittest.cmake new file mode 100644 index 0000000..77c8433 --- /dev/null +++ b/platform/tests/UNITTESTS/ATCmdParser/unittest.cmake @@ -0,0 +1,16 @@ +#################### +# UNIT TESTS +#################### + +# Source files +set(unittest-sources + ../platform/source/ATCmdParser.cpp +) + +# Test files +set(unittest-test-sources + ../platform/tests/UNITTESTS/ATCmdParser/test_ATCmdParser.cpp + stubs/FileHandle_stub.cpp + stubs/mbed_assert_stub.cpp + stubs/mbed_poll_stub.cpp +) diff --git a/platform/tests/UNITTESTS/CircularBuffer/test_CircularBuffer.cpp b/platform/tests/UNITTESTS/CircularBuffer/test_CircularBuffer.cpp new file mode 100644 index 0000000..5286701 --- /dev/null +++ b/platform/tests/UNITTESTS/CircularBuffer/test_CircularBuffer.cpp @@ -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. + */ + +#include "gtest/gtest.h" +#include "platform/CircularBuffer.h" + +class TestCircularBuffer : public testing::Test { +protected: + mbed::CircularBuffer *buf; + + virtual void SetUp() + { + buf = new mbed::CircularBuffer; + } + + virtual void TearDown() + { + delete buf; + } +}; + +TEST_F(TestCircularBuffer, constructor) +{ + EXPECT_TRUE(buf); +} diff --git a/platform/tests/UNITTESTS/CircularBuffer/unittest.cmake b/platform/tests/UNITTESTS/CircularBuffer/unittest.cmake new file mode 100644 index 0000000..fce3ae8 --- /dev/null +++ b/platform/tests/UNITTESTS/CircularBuffer/unittest.cmake @@ -0,0 +1,11 @@ + +#################### +# UNIT TESTS +#################### + +set(unittest-sources +) + +set(unittest-test-sources + ../platform/tests/UNITTESTS/CircularBuffer/test_CircularBuffer.cpp +)