mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #11308 from ARMmbed/release-candidate
Release candidate for mbed-os-5.13.4mbed-os-5.13 mbed-os-5.13.4
commit
1bf6b20df9
|
@ -26,7 +26,21 @@
|
|||
#include "mbed.h"
|
||||
|
||||
#define TIMEOUT_MS 100UL
|
||||
#define KICK_ADVANCE_MS 10UL
|
||||
|
||||
/* This value is used to calculate the time to kick the watchdog.
|
||||
* Given the watchdog timeout is set to TIMEOUT_MS, the kick will be performed
|
||||
* with a delay of (TIMEOUT_MS - KICK_ADVANCE_MS), after the init.
|
||||
*
|
||||
* It is common for the watchdog peripheral to use a low precision clock source,
|
||||
* e.g. the LSI RC acts as a clock source for the IWDG on ST targets.
|
||||
* According to the ST spec, the 37 kHz LSI is guaranteed to have a frequency
|
||||
* around 37-38 kHz, but the actual frequency range guaranteed by the production
|
||||
* tests is 26 kHz up to 56 kHz.
|
||||
* Bearing that in mind, a 100 ms timeout value may actually last as long as 142 ms
|
||||
* and as short as 66 ms.
|
||||
* The value of 35 ms is used to cover the worst case scenario (66 ms).
|
||||
*/
|
||||
#define KICK_ADVANCE_MS 35UL
|
||||
|
||||
#define MSG_VALUE_DUMMY "0"
|
||||
#define CASE_DATA_INVALID 0xffffffffUL
|
||||
|
|
|
@ -129,7 +129,7 @@ void overflow_protect()
|
|||
return;
|
||||
}
|
||||
|
||||
while (intf->read() > ticks_now);
|
||||
while (intf->read() >= ticks_now);
|
||||
}
|
||||
|
||||
void ticker_event_handler_stub(const ticker_data_t *const ticker)
|
||||
|
|
|
@ -85,7 +85,7 @@ void overflow_protect()
|
|||
return;
|
||||
}
|
||||
|
||||
while (lp_ticker_read() > ticks_now);
|
||||
while (lp_ticker_read() >= ticks_now);
|
||||
}
|
||||
|
||||
void ticker_event_handler_stub(const ticker_data_t *const ticker)
|
||||
|
|
|
@ -32,7 +32,17 @@ void us_ticker_info_test()
|
|||
const ticker_info_t *p_ticker_info = us_ticker_get_info();
|
||||
|
||||
TEST_ASSERT(p_ticker_info->frequency >= 250000);
|
||||
TEST_ASSERT(p_ticker_info->frequency <= 8000000);
|
||||
|
||||
switch (p_ticker_info->bits) {
|
||||
case 32:
|
||||
TEST_ASSERT(p_ticker_info->frequency <= 100000000);
|
||||
break;
|
||||
|
||||
default:
|
||||
TEST_ASSERT(p_ticker_info->frequency <= 8000000);
|
||||
break;
|
||||
}
|
||||
|
||||
TEST_ASSERT(p_ticker_info->bits >= 16);
|
||||
|
||||
#ifdef US_TICKER_PERIOD_NUM
|
||||
|
|
|
@ -31,7 +31,10 @@ extern "C" {
|
|||
*
|
||||
* Given ticker is available.
|
||||
* When ticker information data is obtained.
|
||||
* Then ticker information indicate that frequency between 250KHz and 8MHz and the counter is at least 16 bits wide.
|
||||
* Then ticker information indicate that:
|
||||
* - counter frequency is between 250KHz and 8MHz for counters which are less than 32 bits wide
|
||||
* - counter frequency is up to 100MHz for counters which are 32 bits wide
|
||||
* - the counter is at least 16 bits wide.
|
||||
*/
|
||||
void us_ticker_info_test(void);
|
||||
|
||||
|
|
|
@ -26,7 +26,21 @@
|
|||
#include "mbed.h"
|
||||
|
||||
#define TIMEOUT_MS 100UL
|
||||
#define KICK_ADVANCE_MS 10UL
|
||||
|
||||
/* This value is used to calculate the time to kick the watchdog.
|
||||
* Given the watchdog timeout is set to TIMEOUT_MS, the kick will be performed
|
||||
* with a delay of (TIMEOUT_MS - KICK_ADVANCE_MS), after the init.
|
||||
*
|
||||
* It is common for the watchdog peripheral to use a low precision clock source,
|
||||
* e.g. the LSI RC acts as a clock source for the IWDG on ST targets.
|
||||
* According to the ST spec, the 37 kHz LSI is guaranteed to have a frequency
|
||||
* around 37-38 kHz, but the actual frequency range guaranteed by the production
|
||||
* tests is 26 kHz up to 56 kHz.
|
||||
* Bearing that in mind, a 100 ms timeout value may actually last as long as 142 ms
|
||||
* and as short as 66 ms.
|
||||
* The value of 35 ms is used to cover the worst case scenario (66 ms).
|
||||
*/
|
||||
#define KICK_ADVANCE_MS 35UL
|
||||
|
||||
#define MSG_VALUE_DUMMY "0"
|
||||
#define CASE_DATA_INVALID 0xffffffffUL
|
||||
|
|
|
@ -145,7 +145,7 @@ void test_atomic_add()
|
|||
|
||||
utest::v1::status_t test_setup(const size_t number_of_cases)
|
||||
{
|
||||
GREENTEA_SETUP(30, "default_auto");
|
||||
GREENTEA_SETUP(60, "default_auto");
|
||||
return utest::v1::verbose_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,15 +62,16 @@ Please refer to the following table for priorities of test cases. Priorities are
|
|||
| 9 | WIFI_CONNECT_PARAMS_CHANNEL | | SHOULD |
|
||||
| 10 | WIFI_CONNECT_PARAMS_CHANNEL_FAIL | | SHOULD |
|
||||
| 11 | WIFI_CONNECT | | MUST |
|
||||
| 12 | WIFI_CONNECT_SECURE | With security type: | |
|
||||
| 12 | WIFI_CONNECT_NONBLOCK | | SHOULD |
|
||||
| 13 | WIFI_CONNECT_SECURE | With security type: | |
|
||||
| | | NSAPI_SECURITY_WEP | SHOULD |
|
||||
| | | NSAPI_SECURITY_WPA | SHOULD |
|
||||
| | | NSAPI_SECURITY_WPA2 | SHOULD |
|
||||
| | | NSAPI_SECURITY_WPA_WPA2 | MUST |
|
||||
| 13 | WIFI_CONNECT_SECURE_FAIL | | MUST |
|
||||
| 14 | WIFI_CONNECT_DISCONNECT_REPEAT | | MUST |
|
||||
| 15 | WIFI_SCAN_NULL | | SHOULD |
|
||||
| 16 | WIFI_SCAN | | SHOULD |
|
||||
| 14 | WIFI_CONNECT_SECURE_FAIL | | MUST |
|
||||
| 15 | WIFI_CONNECT_DISCONNECT_REPEAT | | MUST |
|
||||
| 16 | WIFI_SCAN_NULL | | SHOULD |
|
||||
| 17 | WIFI_SCAN | | SHOULD |
|
||||
|
||||
Building test binaries
|
||||
----------------------
|
||||
|
@ -372,7 +373,7 @@ Test `WiFiInterface::connect()` without parameters. Use `set_credentials()` for
|
|||
2. `Call WiFiInterface::set_credentials( <ssid:unsecure>, NULL)`.
|
||||
3. `Call WiFiInterface::connect()`.
|
||||
4. `disconnect()`.
|
||||
5. `Call WiFiInterface::set_credentials( <ssid:unsecure>, "")`.
|
||||
5. `Call WiFiInterface::set_credentials( <ssid:unsecure>, "")`.
|
||||
6. `Call WiFiInterface::connect()`.
|
||||
7. `disconnect()`.
|
||||
8. Trash the memory storing SSID.
|
||||
|
@ -384,6 +385,33 @@ Test `WiFiInterface::connect()` without parameters. Use `set_credentials()` for
|
|||
|
||||
`connect()` calls return `NSAPI_ERROR_OK`.
|
||||
|
||||
### WIFI_CONNECT_NONBLOCK
|
||||
|
||||
**Description:**
|
||||
|
||||
Test `WiFiInterface::connect()` and `WiFiInterface::disconnect()` in non-blocking mode. It checks that driver can connect and disconnect in nonblocking mode.
|
||||
|
||||
**Preconditions:**
|
||||
|
||||
1. Test enviroment is set up as specified in the "Test Environment" chapter.
|
||||
|
||||
**Test steps:**
|
||||
|
||||
1. Initialize the driver.
|
||||
2. `Call WiFiInterface::set_credentials( <ssid:unsecure>, NULL)`.
|
||||
3. `Call WiFiInterface::connect()`.
|
||||
4. `Call WiFiInterface::set_blocking(false)`
|
||||
5. `Call WiFiInterface::get_connection_status()`
|
||||
6. `disconnect()`
|
||||
7. `Call WiFiInterface::get_connection_status()`
|
||||
8. `Call WiFiInterface::set_blocking(true)`
|
||||
|
||||
**Expected result:**
|
||||
|
||||
In case of drivers which do not support asynchronous mode `set_blocking(false)` call returns `NSAPI_ERROR_UNSUPPORTED` and skips test case, otherwise:
|
||||
`connect()` call returns `NSAPI_ERROR_OK`. To confirm connection `get_connection_status()` calls return `NSAPI_STATUS_GLOBAL_UP` or `NSAPI_STATUS_LOCAL_UP`.
|
||||
`disconnect()` call returns `NSAPI_ERROR_OK`. To confirm disconnection `get_connection_status()` calls return `NSAPI_STATUS_DISCONNECTED`.
|
||||
|
||||
### WIFI_CONNECT_SECURE
|
||||
|
||||
**Description:**
|
||||
|
|
|
@ -74,6 +74,8 @@ Case cases[] = {
|
|||
Case("WIFI-GET-RSSI", wifi_get_rssi),
|
||||
Case("WIFI-CONNECT-PARAMS-VALID-UNSECURE", wifi_connect_params_valid_unsecure),
|
||||
Case("WIFI-CONNECT", wifi_connect),
|
||||
//Most boards are not passing this test, but they should if they support non-blocking API.
|
||||
//Case("WIFI-CONNECT-NONBLOCKING", wifi_connect_nonblock),
|
||||
Case("WIFI-CONNECT-DISCONNECT-REPEAT", wifi_connect_disconnect_repeat),
|
||||
#endif
|
||||
#if defined(MBED_CONF_APP_WIFI_SECURE_SSID)
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
#include "wifi_tests.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
#if defined(MBED_CONF_APP_WIFI_UNSECURE_SSID)
|
||||
|
||||
#define SSID_MAX_LEN 32
|
||||
nsapi_connection_status_t status_connection;
|
||||
Semaphore sem_conn(0, 1);
|
||||
Semaphore sem_disconn(0, 1);
|
||||
void status_callback(nsapi_event_t e, intptr_t d)
|
||||
{
|
||||
if (d == NSAPI_STATUS_LOCAL_UP || d == NSAPI_STATUS_GLOBAL_UP) {
|
||||
status_connection = (nsapi_connection_status_t)d;
|
||||
sem_conn.release();
|
||||
}
|
||||
|
||||
if (d == NSAPI_STATUS_DISCONNECTED) {
|
||||
status_connection = (nsapi_connection_status_t)d;
|
||||
sem_disconn.release();
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_connect_nonblock(void)
|
||||
{
|
||||
WiFiInterface *wifi = get_interface();
|
||||
char ssid[SSID_MAX_LEN + 1] = MBED_CONF_APP_WIFI_UNSECURE_SSID;
|
||||
TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->set_credentials(ssid, NULL));
|
||||
wifi->attach(status_callback);
|
||||
TEST_SKIP_UNLESS(wifi->set_blocking(false) != NSAPI_ERROR_UNSUPPORTED);
|
||||
nsapi_error_t ret = wifi->connect();
|
||||
TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, ret);
|
||||
bool res = sem_conn.try_acquire_for(30000);
|
||||
TEST_ASSERT_TRUE(res == true);
|
||||
TEST_ASSERT_TRUE(status_connection == NSAPI_STATUS_GLOBAL_UP || status_connection == NSAPI_STATUS_LOCAL_UP);
|
||||
ret = wifi->disconnect();
|
||||
TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, ret);
|
||||
res = sem_disconn.try_acquire_for(30000);
|
||||
TEST_ASSERT_TRUE(res == true);
|
||||
TEST_ASSERT_EQUAL_INT(NSAPI_STATUS_DISCONNECTED, status_connection);
|
||||
wifi->set_blocking(true);
|
||||
}
|
||||
|
||||
#endif // defined(MBED_CONF_APP_WIFI_UNSECURE_SSID)
|
|
@ -63,6 +63,9 @@ void wifi_connect_params_channel_fail(void);
|
|||
/** Test WiFiInterface::connect() without parameters. Use set_credentials() for setting parameters. */
|
||||
void wifi_connect(void);
|
||||
|
||||
/** Test WiFiInterface::connect() in nonblocking mode. Use set_credentials() for setting parameters. */
|
||||
void wifi_connect_nonblock(void);
|
||||
|
||||
/** Test WiFiInterface::connect() without parameters. Don't set parameters with set_credentials() */
|
||||
void wifi_connect_nocredentials(void);
|
||||
|
||||
|
|
|
@ -307,6 +307,7 @@ TEST_F(TestTLSSocketWrapper, recv_from)
|
|||
EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
|
||||
SocketAddress b;
|
||||
EXPECT_EQ(wrapper->recvfrom(&b, dataBuf, dataSize), NSAPI_ERROR_OK);
|
||||
EXPECT_EQ(a, b);
|
||||
}
|
||||
|
||||
TEST_F(TestTLSSocketWrapper, recv_from_null)
|
||||
|
|
|
@ -28,8 +28,6 @@ set(unittest-test-sources
|
|||
stubs/mbed_shared_queues_stub.cpp
|
||||
stubs/nsapi_dns_stub.cpp
|
||||
stubs/EventFlags_stub.cpp
|
||||
stubs/stoip4_stub.c
|
||||
stubs/ip4tos_stub.c
|
||||
stubs/SocketStats_Stub.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
test/*
|
|
@ -165,6 +165,12 @@
|
|||
"SPI_MISO": "D12",
|
||||
"SPI_CLK": "D13",
|
||||
"SPI_CS": "D10"
|
||||
},
|
||||
"CC3220SF_LAUNCHXL": {
|
||||
"SPI_MOSI": "D11",
|
||||
"SPI_MISO": "D12",
|
||||
"SPI_CLK": "D13",
|
||||
"SPI_CS": "D10"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,11 @@ public:
|
|||
if (position >= data.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* early termination of packet, no more meaningful octets */
|
||||
if (current_length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (position + current_length() >= data.size()) {
|
||||
return false;
|
||||
|
|
|
@ -152,6 +152,8 @@ struct advertising_type_t : SafeEnum<advertising_type_t, uint8_t> {
|
|||
/**
|
||||
* Device is connectable, scannable and doesn't expect connection from a
|
||||
* specific peer.
|
||||
* @note Cannot carry extended advertising payload, only legacy PDUs.
|
||||
* Use CONNECTABLE_NON_SCANNABLE_UNDIRECTED for non-legacy payload.
|
||||
*
|
||||
* @see Vol 3, Part C, Section 9.3.4 and Vol 6, Part B, Section 2.3.1.1.
|
||||
*/
|
||||
|
@ -183,13 +185,21 @@ struct advertising_type_t : SafeEnum<advertising_type_t, uint8_t> {
|
|||
*/
|
||||
CONNECTABLE_DIRECTED_LOW_DUTY = 0x04,
|
||||
|
||||
/**
|
||||
* Device is connectable, but not scannable and doesn't expect connection from a specific peer.
|
||||
* @note Only for use with extended advertising payload, will not allow legacy PDUs
|
||||
* (use CONNECTABLE_UNDIRECTED for legacy PDU).
|
||||
*/
|
||||
CONNECTABLE_NON_SCANNABLE_UNDIRECTED = 0x05,
|
||||
|
||||
#if !defined(DOXYGEN_ONLY)
|
||||
// used by the PAL; naming in line with the the spec.
|
||||
ADV_IND = 0x00,
|
||||
ADV_DIRECT_IND = 0x01,
|
||||
ADV_SCAN_IND = 0x02,
|
||||
ADV_NONCONN_IND = 0x03,
|
||||
ADV_DIRECT_IND_LOW_DUTY_CYCLE = 0x04
|
||||
ADV_DIRECT_IND_LOW_DUTY_CYCLE = 0x04,
|
||||
ADV_NONSCAN_IND = 0x05
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -446,6 +446,9 @@ struct advertising_event_properties_t {
|
|||
break;
|
||||
case advertising_type_t::ADV_NONCONN_IND:
|
||||
break;
|
||||
case advertising_type_t::ADV_NONSCAN_IND:
|
||||
connectable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -655,7 +655,7 @@ public:
|
|||
periodic_advertising_interval_t periodic_advertising_max,
|
||||
bool advertise_power
|
||||
) {
|
||||
return impl()->set_periodic_advertising_parameters(
|
||||
return impl()->set_periodic_advertising_parameters_(
|
||||
advertising_handle,
|
||||
periodic_advertising_min,
|
||||
periodic_advertising_max,
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* 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 "RM1000_AT.h"
|
||||
|
||||
#include "RM1000_AT_CellularContext.h"
|
||||
#include "RM1000_AT_CellularNetwork.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#ifndef TRACE_GROUP
|
||||
#define TRACE_GROUP "RIOT"
|
||||
#endif // TRACE_GROUP
|
||||
|
||||
using namespace mbed;
|
||||
using namespace events;
|
||||
static const uint16_t retry_timeout[] = {1, 2, 4};
|
||||
static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
|
||||
AT_CellularNetwork::RegistrationModeLAC,// C_EREG
|
||||
AT_CellularNetwork::RegistrationModeDisable,// C_GREG
|
||||
AT_CellularNetwork::RegistrationModeDisable,// C_REG
|
||||
0, // AT_CGSN_WITH_TYPE
|
||||
0, // AT_CGDATA
|
||||
0, // AT_CGAUTH
|
||||
0, // AT_CNMI
|
||||
0, // AT_CSMP
|
||||
0, // AT_CMGF
|
||||
0, // AT_CSDH
|
||||
1, // PROPERTY_IPV4_STACK
|
||||
1, // PROPERTY_IPV6_STACK
|
||||
1, // PROPERTY_IPV4V6_STACK
|
||||
0, // PROPERTY_NON_IP_PDP_TYPE
|
||||
0, // PROPERTY_AT_CGEREP
|
||||
};
|
||||
|
||||
RM1000_AT::RM1000_AT(FileHandle *fh) : AT_CellularDevice(fh)
|
||||
{
|
||||
tr_debug("RM1000_AT::RM1000_AT");
|
||||
AT_CellularBase::set_cellular_properties(cellular_properties);
|
||||
set_retry_timeout_array(retry_timeout, sizeof(retry_timeout) / sizeof(retry_timeout[0]));
|
||||
}
|
||||
|
||||
AT_CellularNetwork *RM1000_AT::open_network_impl(ATHandler &at)
|
||||
{
|
||||
tr_debug("RM1000_AT::open_network_impl");
|
||||
return new RM1000_AT_CellularNetwork(at);
|
||||
}
|
||||
|
||||
AT_CellularContext *RM1000_AT::create_context_impl(ATHandler &at, const char *apn, bool cp_req, bool nonip_req)
|
||||
{
|
||||
tr_debug("RM1000_AT::create_context_impl");
|
||||
return new RM1000_AT_CellularContext(at, this, apn, cp_req, nonip_req);
|
||||
}
|
||||
|
||||
nsapi_error_t RM1000_AT::init()
|
||||
{
|
||||
tr_debug("RM1000_AT::init");
|
||||
|
||||
_at->lock();
|
||||
_at->flush();
|
||||
_at->cmd_start("ATE0"); // echo off
|
||||
_at->cmd_stop_read_resp();
|
||||
|
||||
_at->cmd_start("AT+SIM=physical");
|
||||
_at->cmd_stop_read_resp();
|
||||
|
||||
_at->set_at_timeout(5000);
|
||||
_at->cmd_start("AT+CFUN=1"); // set full functionality
|
||||
_at->cmd_stop_read_resp();
|
||||
|
||||
_at->cmd_start("AT+VERBOSE=0"); // verbose responses
|
||||
_at->cmd_stop_read_resp();
|
||||
|
||||
return _at->unlock_return_error();
|
||||
}
|
||||
|
||||
#if MBED_CONF_RM1000_AT_PROVIDE_DEFAULT
|
||||
#include "UARTSerial.h"
|
||||
CellularDevice *CellularDevice::get_default_instance()
|
||||
{
|
||||
tr_debug("Calling CellularDevice::get_default_instance from RM1000_AT");
|
||||
|
||||
static UARTSerial serial(MBED_CONF_RM1000_AT_TX, MBED_CONF_RM1000_AT_RX, MBED_CONF_RM1000_AT_BAUDRATE);
|
||||
#if defined (MBED_CONF_RM1000_AT_RTS) && defined(MBED_CONF_RM1000_AT_CTS)
|
||||
tr_debug("RM1000_AT flow control: RTS %d CTS %d", MBED_CONF_RM1000_AT_RTS, MBED_CONF_RM1000_AT_CTS);
|
||||
serial.set_flow_control(SerialBase::RTSCTS, MBED_CONF_RM1000_AT_RTS, MBED_CONF_RM1000_AT_CTS);
|
||||
#endif
|
||||
static RM1000_AT device(&serial);
|
||||
return &device;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef RM1000_AT_H_
|
||||
#define RM1000_AT_H_
|
||||
|
||||
#include "AT_CellularDevice.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class RM1000_AT : public AT_CellularDevice {
|
||||
public:
|
||||
RM1000_AT(FileHandle *fh);
|
||||
|
||||
protected: // AT_CellularDevice
|
||||
virtual AT_CellularNetwork *open_network_impl(ATHandler &at);
|
||||
virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, bool cp_req = false, bool nonip_req = false);
|
||||
|
||||
virtual nsapi_error_t init();
|
||||
|
||||
public: // NetworkInterface
|
||||
void handle_urc(FileHandle *fh);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // RM1000_AT_H_
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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 "RM1000_AT_CellularContext.h"
|
||||
|
||||
#include "APN_db.h"
|
||||
#include "RM1000_AT_CellularStack.h"
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#ifndef TRACE_GROUP
|
||||
#define TRACE_GROUP "RIOT"
|
||||
#endif // TRACE_GROUP
|
||||
|
||||
namespace mbed {
|
||||
|
||||
RM1000_AT_CellularContext::RM1000_AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req, bool nonip_req) :
|
||||
AT_CellularContext(at, device, apn, cp_req, nonip_req)
|
||||
{
|
||||
tr_debug("Calling RM1000_AT_CellularContext::RM1000_AT_CellularContext");
|
||||
}
|
||||
|
||||
RM1000_AT_CellularContext::~RM1000_AT_CellularContext()
|
||||
{
|
||||
tr_debug("Calling RM1000_AT_CellularContext::~RM1000_AT_CellularContext");
|
||||
}
|
||||
|
||||
NetworkStack *RM1000_AT_CellularContext::get_stack()
|
||||
{
|
||||
tr_debug("Calling RM1000_AT_CellularContext::get_stack");
|
||||
|
||||
if (_pdp_type == NON_IP_PDP_TYPE || _cp_in_use) {
|
||||
tr_error("Requesting stack for NON-IP context! Should request control plane netif: get_cp_netif()");
|
||||
return NULL;
|
||||
}
|
||||
if (!_stack) {
|
||||
_stack = new RM1000_AT_CellularStack(_at, _cid, (nsapi_ip_stack_t)_pdp_type);
|
||||
}
|
||||
|
||||
return _stack;
|
||||
}
|
||||
|
||||
} /* namespace mbed */
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef RM1000_AT_CELLULARCONTEXT_H_
|
||||
#define RM1000_AT_CELLULARCONTEXT_H_
|
||||
|
||||
#include "AT_CellularContext.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class RM1000_AT_CellularContext: public AT_CellularContext {
|
||||
public:
|
||||
RM1000_AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req = false, bool nonip_req = false);
|
||||
virtual ~RM1000_AT_CellularContext();
|
||||
|
||||
protected:
|
||||
virtual NetworkStack *get_stack();
|
||||
};
|
||||
|
||||
} /* namespace mbed */
|
||||
|
||||
#endif // RM1000_AT_CELLULARCONTEXT_H_
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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 <stdlib.h>
|
||||
#include "rtos.h"
|
||||
#include "CellularCommon.h"
|
||||
#include "RM1000_AT_CellularNetwork.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#ifndef TRACE_GROUP
|
||||
#define TRACE_GROUP "RIOT"
|
||||
#endif // TRACE_GROUP
|
||||
using namespace mbed;
|
||||
|
||||
// Callback for MODEM faults URC.
|
||||
void RM1000_AT_CellularNetwork::MODEM_FAULT_URC()
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularNetwork::ASSERTED_URC");
|
||||
_connect_status = NSAPI_STATUS_DISCONNECTED;
|
||||
if (_connection_status_cb) {
|
||||
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
RM1000_AT_CellularNetwork::RM1000_AT_CellularNetwork(ATHandler &atHandler) : AT_CellularNetwork(atHandler)
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularNetwork::RM1000_B0_CellularNetwork");
|
||||
_op_act = RAT_UNKNOWN;
|
||||
_at.set_urc_handler("ASSERTED!", callback(this, &RM1000_AT_CellularNetwork::MODEM_FAULT_URC));
|
||||
_at.set_urc_handler("ERRCODE:", callback(this, &RM1000_AT_CellularNetwork::MODEM_FAULT_URC));
|
||||
_at.set_urc_handler("Halt the processor", callback(this, &RM1000_AT_CellularNetwork::MODEM_FAULT_URC));
|
||||
}
|
||||
|
||||
RM1000_AT_CellularNetwork::~RM1000_AT_CellularNetwork()
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularNetwork::~RM1000_B0_CellularNetwork");
|
||||
|
||||
_at.set_urc_handler("ASSERTED!", NULL);
|
||||
_at.set_urc_handler("ERRCODE:", NULL);
|
||||
_at.set_urc_handler("Halt the processor", NULL);
|
||||
}
|
||||
|
||||
nsapi_error_t RM1000_AT_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opRat)
|
||||
{
|
||||
nsapi_error_t ret = NSAPI_ERROR_OK;
|
||||
|
||||
tr_debug("RM1000_AT_CellularNetwork::set_access_technology_impl %d", opRat);
|
||||
|
||||
switch (opRat) {
|
||||
case RAT_NB1:
|
||||
break;
|
||||
default: {
|
||||
_op_act = RAT_UNKNOWN;
|
||||
ret = NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
nsapi_error_t RM1000_AT_CellularNetwork::set_registration_urc(RegistrationType type, bool urc_on)
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularNetwork::set_registration_urc");
|
||||
|
||||
int index = (int)type;
|
||||
MBED_ASSERT(index >= 0 && index < C_MAX);
|
||||
|
||||
RegistrationMode mode = (RegistrationMode)get_property((AT_CellularBase::CellularProperty)type);
|
||||
if (mode == RegistrationModeDisable) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
} else {
|
||||
return NSAPI_ERROR_OK; /* FIXME use at commands */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef RM1000_AT_CELLULAR_NETWORK_H_
|
||||
#define RM1000_AT_CELLULAR_NETWORK_H_
|
||||
|
||||
#include "AT_CellularNetwork.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class RM1000_AT_CellularNetwork : public AT_CellularNetwork {
|
||||
public:
|
||||
RM1000_AT_CellularNetwork(ATHandler &atHandler);
|
||||
virtual ~RM1000_AT_CellularNetwork();
|
||||
|
||||
virtual nsapi_error_t set_registration_urc(RegistrationType type, bool on);
|
||||
|
||||
protected:
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat);
|
||||
private:
|
||||
// URC handlers
|
||||
void MODEM_FAULT_URC();
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // RM1000_AT_CELLULAR_NETWORK_H_
|
|
@ -0,0 +1,374 @@
|
|||
/*
|
||||
* 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 "RM1000_AT_CellularStack.h"
|
||||
|
||||
#include "mbed_poll.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#ifndef TRACE_GROUP
|
||||
#define TRACE_GROUP "RIOT"
|
||||
#endif // TRACE_GROUP
|
||||
|
||||
using namespace mbed;
|
||||
using namespace mbed_cellular_util;
|
||||
|
||||
RM1000_AT_CellularStack::RM1000_AT_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type) : AT_CellularStack(atHandler, cid, stack_type)
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularStack::RM1000_AT_CellularStack");
|
||||
|
||||
// URC handlers for sockets
|
||||
_at.set_urc_handler("+RUSORCV:", callback(this, &RM1000_AT_CellularStack::RUSORCV_URC));
|
||||
_at.set_urc_handler("+RUSOCL:", callback(this, &RM1000_AT_CellularStack::RUSOCL_URC));
|
||||
}
|
||||
|
||||
RM1000_AT_CellularStack::~RM1000_AT_CellularStack()
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularStack::~RM1000_AT_CellularStack");
|
||||
|
||||
_at.set_urc_handler("+RUSORCV:", NULL);
|
||||
_at.set_urc_handler("+RUSOCL:", NULL);
|
||||
}
|
||||
|
||||
nsapi_error_t RM1000_AT_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularStack::socket_listen");
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nsapi_error_t RM1000_AT_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularStack::socket_accept");
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
// Callback for Socket Receive URC.
|
||||
void RM1000_AT_CellularStack::RUSORCV_URC()
|
||||
{
|
||||
int a, b;
|
||||
CellularSocket *socket;
|
||||
|
||||
a = _at.read_int();
|
||||
b = _at.read_int();
|
||||
socket = find_socket(a);
|
||||
if (socket != NULL) {
|
||||
socket->pending_bytes = b;
|
||||
// No debug prints here as they can affect timing
|
||||
// and cause data loss in UARTSerial
|
||||
if (socket->_cb != NULL) {
|
||||
socket->_cb(socket->_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Callback for Socket Close URC.
|
||||
void RM1000_AT_CellularStack::RUSOCL_URC()
|
||||
{
|
||||
int a;
|
||||
CellularSocket *socket;
|
||||
|
||||
a = _at.read_int();
|
||||
socket = find_socket(a);
|
||||
clear_socket(socket);
|
||||
}
|
||||
|
||||
int RM1000_AT_CellularStack::get_max_socket_count()
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularStack::get_max_socket_count");
|
||||
return RM1000_MAX_SOCKET;
|
||||
}
|
||||
|
||||
bool RM1000_AT_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
|
||||
{
|
||||
return (protocol == NSAPI_UDP || protocol == NSAPI_TCP);
|
||||
}
|
||||
|
||||
nsapi_error_t RM1000_AT_CellularStack::create_socket_impl(CellularSocket *socket)
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularStack::create_socket_impl");
|
||||
|
||||
int sock_id = SOCKET_UNUSED;
|
||||
|
||||
_at.lock();
|
||||
if (socket->proto == NSAPI_UDP) {
|
||||
_at.cmd_start("AT+RSOCR=0");
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+RSOCR:");
|
||||
sock_id = _at.read_int();
|
||||
_at.resp_stop();
|
||||
} else if (socket->proto == NSAPI_TCP) {
|
||||
_at.cmd_start("AT+RSOCR=1");
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+RSOCR:");
|
||||
sock_id = _at.read_int();
|
||||
_at.resp_stop();
|
||||
} // Unsupported protocol is checked in "is_protocol_supported" function
|
||||
|
||||
if ((_at.get_last_error() != NSAPI_ERROR_OK) || (sock_id == -1)) {
|
||||
_at.unlock();
|
||||
tr_error("RM1000_AT_CellularStack::create_socket_impl error sock_id=%d err=%d", sock_id, _at.get_last_error());
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
_at.unlock();
|
||||
|
||||
// Check for duplicate socket id delivered by modem
|
||||
for (int i = 0; i < RM1000_MAX_SOCKET; i++) {
|
||||
CellularSocket *sock = _socket[i];
|
||||
if (sock && sock != socket && sock->id == sock_id) {
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
socket->id = sock_id;
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t RM1000_AT_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &addr)
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularStack::socket_connect");
|
||||
|
||||
CellularSocket *socket = (CellularSocket *)handle;
|
||||
|
||||
if (socket) {
|
||||
if (socket->id == SOCKET_UNUSED) {
|
||||
nsapi_error_t err = create_socket_impl(socket);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+RSOCO=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_string(addr.get_ip_address(), false);
|
||||
_at.write_int(addr.get_port());
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+RSOCO:");
|
||||
int socket_id = _at.read_int();
|
||||
_at.resp_stop();
|
||||
nsapi_error_t error = _at.get_last_error();
|
||||
_at.unlock();
|
||||
|
||||
if ((error == NSAPI_ERROR_OK) && (socket_id == socket->id)) {
|
||||
socket->remoteAddress = addr;
|
||||
socket->connected = true;
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t RM1000_AT_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size)
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularStack::socket_sendto_impl");
|
||||
|
||||
int sent_len = 0;
|
||||
pollfh fhs;
|
||||
fhs.fh = _at.get_file_handle();
|
||||
fhs.events = POLLIN;
|
||||
|
||||
bool success = true;
|
||||
const char *buf = (const char *) data;
|
||||
nsapi_size_t blk = RM1000_MAX_PACKET_SIZE;
|
||||
nsapi_size_t count = size;
|
||||
|
||||
while ((count > 0) && success) {
|
||||
if (count < blk) {
|
||||
blk = count;
|
||||
}
|
||||
_at.cmd_start("AT+RSOSND=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_int(blk);
|
||||
if (socket->proto == NSAPI_UDP) {
|
||||
_at.write_string(address.get_ip_address(), false);
|
||||
_at.write_int(address.get_port());
|
||||
}
|
||||
_at.cmd_stop();
|
||||
(void)poll(&fhs, 1, 50);
|
||||
_at.write_bytes((uint8_t *)buf, blk);
|
||||
|
||||
_at.resp_start("+RSOSND:");
|
||||
_at.skip_param(); // skip socket id
|
||||
sent_len = _at.read_int();
|
||||
_at.resp_stop();
|
||||
|
||||
if ((sent_len >= (int) blk) &&
|
||||
(_at.get_last_error() == NSAPI_ERROR_OK)) {
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
buf += blk;
|
||||
count -= blk;
|
||||
}
|
||||
|
||||
if (success && _at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
return size - count;
|
||||
}
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t RM1000_AT_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
|
||||
void *buffer, nsapi_size_t size)
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularStack::socket_recvfrom_impl");
|
||||
|
||||
nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR;
|
||||
bool success = true;
|
||||
nsapi_size_t read_blk;
|
||||
nsapi_size_t count = 0;
|
||||
nsapi_size_t rsorcv_sz;
|
||||
char ipAddress[NSAPI_IP_SIZE];
|
||||
int port = 0;
|
||||
Timer timer;
|
||||
|
||||
if (socket->pending_bytes == 0) {
|
||||
_at.process_oob();
|
||||
if (socket->pending_bytes == 0) {
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
timer.start();
|
||||
while (success && (size > 0)) {
|
||||
read_blk = RM1000_MAX_PACKET_SIZE;
|
||||
if (read_blk > size) {
|
||||
read_blk = size;
|
||||
}
|
||||
if (socket->pending_bytes > 0) {
|
||||
_at.cmd_start("AT+RSORCV=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_int(read_blk);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+RSORCV:");
|
||||
_at.skip_param(); // receiving socket id
|
||||
rsorcv_sz = _at.read_int();
|
||||
if (socket->proto == NSAPI_UDP) {
|
||||
_at.read_string(ipAddress, sizeof(ipAddress));
|
||||
port = _at.read_int();
|
||||
}
|
||||
if (rsorcv_sz > size) {
|
||||
rsorcv_sz = size;
|
||||
}
|
||||
_at.read_bytes((uint8_t *)buffer + count, rsorcv_sz);
|
||||
_at.resp_stop();
|
||||
|
||||
// Must use what +RSORCV returns here as it may be less or more than we asked for
|
||||
if (rsorcv_sz > socket->pending_bytes) {
|
||||
socket->pending_bytes = 0;
|
||||
} else {
|
||||
socket->pending_bytes -= rsorcv_sz;
|
||||
}
|
||||
|
||||
if (rsorcv_sz > 0) {
|
||||
count += rsorcv_sz;
|
||||
size -= rsorcv_sz;
|
||||
} else {
|
||||
// read() should not fail
|
||||
success = false;
|
||||
}
|
||||
} else if (timer.read_ms() < SOCKET_TIMEOUT) {
|
||||
// Wait for URCs
|
||||
_at.process_oob();
|
||||
} else {
|
||||
if (count == 0) {
|
||||
// Timeout with nothing received
|
||||
nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK;
|
||||
success = false;
|
||||
}
|
||||
size = 0; // This simply to cause an exit
|
||||
}
|
||||
}
|
||||
timer.stop();
|
||||
|
||||
if (!count || (_at.get_last_error() != NSAPI_ERROR_OK)) {
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
} else {
|
||||
nsapi_error_size = count;
|
||||
}
|
||||
|
||||
if (success && socket->proto == NSAPI_UDP && address) {
|
||||
address->set_ip_address(ipAddress);
|
||||
address->get_ip_address();
|
||||
address->set_port(port);
|
||||
}
|
||||
|
||||
return nsapi_error_size;
|
||||
}
|
||||
|
||||
nsapi_error_t RM1000_AT_CellularStack::socket_close_impl(int sock_id)
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularStack::socket_close_impl");
|
||||
|
||||
_at.cmd_start("AT+RSOCL=");
|
||||
_at.write_int(sock_id);
|
||||
_at.cmd_stop_read_resp();
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
// Clear out the storage for a socket
|
||||
void RM1000_AT_CellularStack::clear_socket(CellularSocket *socket)
|
||||
{
|
||||
if (socket != NULL) {
|
||||
socket->id = SOCKET_UNUSED;
|
||||
socket->pending_bytes = 0;
|
||||
socket->_cb = NULL;
|
||||
socket->_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t RM1000_AT_CellularStack::gethostbyname(const char *host, SocketAddress *address, nsapi_version_t version, const char *interface_name)
|
||||
{
|
||||
tr_debug("RM1000_AT_CellularStack::gethostbyname");
|
||||
|
||||
char ipAddress[NSAPI_IP_SIZE];
|
||||
nsapi_error_t err = NSAPI_ERROR_NO_CONNECTION;
|
||||
|
||||
_at.lock();
|
||||
if (address->set_ip_address(host)) {
|
||||
err = NSAPI_ERROR_OK;
|
||||
} else {
|
||||
// This interrogation can sometimes take longer than the usual 8 seconds
|
||||
_at.cmd_start("AT+RDNS=");
|
||||
_at.write_string(host, false);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.set_at_timeout(70000);
|
||||
_at.resp_start("+RDNS:");
|
||||
if (_at.info_resp()) {
|
||||
_at.read_string(ipAddress, sizeof(ipAddress));
|
||||
if (address->set_ip_address(ipAddress)) {
|
||||
err = NSAPI_ERROR_OK;
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
_at.restore_at_timeout();
|
||||
}
|
||||
_at.unlock();
|
||||
|
||||
return err;
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef RM1000_AT_CELLULARSTACK_H_
|
||||
#define RM1000_AT_CELLULARSTACK_H_
|
||||
|
||||
#include "AT_CellularStack.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "drivers/Timer.h"
|
||||
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class RM1000_AT_CellularStack : public AT_CellularStack {
|
||||
public:
|
||||
RM1000_AT_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type);
|
||||
virtual ~RM1000_AT_CellularStack();
|
||||
|
||||
virtual nsapi_error_t gethostbyname(const char *host,
|
||||
SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC, const char *interface_name = NULL);
|
||||
|
||||
protected:
|
||||
virtual nsapi_error_t socket_listen(nsapi_socket_t handle, int backlog);
|
||||
|
||||
virtual nsapi_error_t socket_accept(nsapi_socket_t server,
|
||||
nsapi_socket_t *handle, SocketAddress *address = 0);
|
||||
|
||||
protected: // AT_CellularStack
|
||||
|
||||
/** The profile to use (on board the modem).
|
||||
*/
|
||||
#define PROFILE "0"
|
||||
|
||||
/** Socket "unused" value.
|
||||
*/
|
||||
static const int SOCKET_UNUSED = -1;
|
||||
|
||||
/** Socket timeout value in milliseconds.
|
||||
* Note: the sockets layer above will retry the
|
||||
* call to the functions here when they return NSAPI_ERROR_WOULD_BLOCK
|
||||
* and the user has set a larger timeout or full blocking.
|
||||
*/
|
||||
static const int SOCKET_TIMEOUT = 1000;
|
||||
|
||||
/** Maximum allowed sockets.
|
||||
*/
|
||||
static const int RM1000_MAX_SOCKET = 7;
|
||||
|
||||
/** The maximum number of bytes in a packet that can be write/read from
|
||||
* the AT interface in one go.
|
||||
*/
|
||||
static const int RM1000_MAX_PACKET_SIZE = 1024;
|
||||
|
||||
virtual int get_max_socket_count();
|
||||
|
||||
virtual bool is_protocol_supported(nsapi_protocol_t protocol);
|
||||
|
||||
virtual nsapi_error_t create_socket_impl(CellularSocket *socket);
|
||||
|
||||
virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address);
|
||||
|
||||
virtual nsapi_size_or_error_t socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size);
|
||||
|
||||
virtual nsapi_size_or_error_t socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
|
||||
void *buffer, nsapi_size_t size);
|
||||
|
||||
virtual nsapi_error_t socket_close_impl(int sock_id);
|
||||
|
||||
private:
|
||||
// URC handlers
|
||||
void RUSORCV_URC();
|
||||
void RUSOCL_URC();
|
||||
|
||||
/** Clear out the storage for a socket.
|
||||
*
|
||||
* @param id Cellular Socket.
|
||||
* @return None
|
||||
*/
|
||||
void clear_socket(CellularSocket *socket);
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif /* RM1000_AT_CELLULARSTACK_H_ */
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "RM1000_AT",
|
||||
"config": {
|
||||
"tx": {
|
||||
"help": "TX pin for serial connection. D1 assumed if Arduino Form Factor, needs to be set/overwritten otherwise.",
|
||||
"value": null
|
||||
},
|
||||
"rx": {
|
||||
"help": "RX pin for serial connection. D0 assumed if Arduino Form Factor, needs to be set/overwritten otherwise.",
|
||||
"value": null
|
||||
},
|
||||
"rts": {
|
||||
"help": "RTS pin for serial connection",
|
||||
"value": null
|
||||
},
|
||||
"cts": {
|
||||
"help": "CTS pin for serial connection",
|
||||
"value": null
|
||||
},
|
||||
"baudrate" : {
|
||||
"help": "Serial connection baud rate",
|
||||
"value": 230400
|
||||
},
|
||||
"provide-default": {
|
||||
"help": "Provide as default CellularDevice [true/false]",
|
||||
"value": false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,14 @@
|
|||
# Change Log
|
||||
|
||||
## [v4.8.1(https://github.com/ARMmbed/mbed-coap/releases/tag/v4.8.1)
|
||||
- Store ACK's also into duplicate info list.
|
||||
- ROM size optimization. Flash size has gone down ~1100 bytes.
|
||||
|
||||
**Closed issues:**
|
||||
- IOTCLT-3592 - Client does not handle Duplicate ACK messages during blockwise registration correctly
|
||||
|
||||
-[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.8.0...v4.8.1)
|
||||
|
||||
## [v4.8.0](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.8.0)
|
||||
- Make `sn_coap_protocol_linked_list_duplication_info_remove` API to public. User might want to delete some messages from the duplicate list.
|
||||
- Enable support for unified client configuration.
|
||||
|
|
|
@ -49,7 +49,7 @@ test: $(TESTDIRS)
|
|||
@rm -f lcov/index.xml
|
||||
@find ./ -name '*.gcno' | xargs cp --backup=numbered -t ./coverage/
|
||||
@find ./ -name '*.gcda' | xargs cp --backup=numbered -t ./coverage/
|
||||
@gcovr --object-directory ./coverage --exclude-unreachable-branches -e '.*/builds/.*' -e '.*/test/.*' -e '.*/stubs/.*' -e '.*/mbed-coap/.*' -x -o ./lcov/gcovr.xml
|
||||
@gcovr --object-directory ./coverage --exclude-unreachable-branches -e '.*/builds/.*' -e '.*/CppUTest/.*' -e '.*/mbed-client-libservice/.*' -e '.*/test/.*' -e '.*/stubs/.*' -e '.*/mbed-coap/.*' -x -o ./lcov/gcovr.xml
|
||||
@lcov -d test/. -c -o $(COVERAGEFILE)
|
||||
@lcov -q -r $(COVERAGEFILE) "/usr*" -o $(COVERAGEFILE)
|
||||
@lcov -q -r $(COVERAGEFILE) "/test*" -o $(COVERAGEFILE)
|
||||
|
|
|
@ -338,7 +338,7 @@ extern void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle,
|
|||
* -1 = Failure in given CoAP header structure\n
|
||||
* -2 = Failure in given pointer (= NULL)
|
||||
*/
|
||||
extern int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
extern int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, const sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
|
||||
/**
|
||||
* \fn uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
|
@ -351,7 +351,7 @@ extern int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_
|
|||
* \return Return value is count of needed memory as bytes for build Packet data
|
||||
* Null if failed
|
||||
*/
|
||||
extern uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
extern uint16_t sn_coap_builder_calc_needed_packet_data_size(const sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
|
||||
/**
|
||||
* \fn int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_size)
|
||||
|
@ -368,7 +368,7 @@ extern uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_
|
|||
* -1 = Failure in given CoAP header structure\n
|
||||
* -2 = Failure in given pointer (= NULL)
|
||||
*/
|
||||
extern int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size);
|
||||
extern int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, const sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size);
|
||||
|
||||
/**
|
||||
* \fn uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size)
|
||||
|
@ -382,7 +382,7 @@ extern int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *sr
|
|||
* \return Return value is count of needed memory as bytes for build Packet data
|
||||
* Null if failed
|
||||
*/
|
||||
extern uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size);
|
||||
extern uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size);
|
||||
|
||||
/**
|
||||
* \fn sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)
|
||||
|
@ -397,7 +397,7 @@ extern uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *sr
|
|||
* NULL Error in parsing the request
|
||||
*
|
||||
*/
|
||||
extern sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code);
|
||||
extern sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, const sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code);
|
||||
|
||||
/**
|
||||
* \brief Initialise a message structure to empty
|
||||
|
@ -436,6 +436,8 @@ extern sn_coap_hdr_s *sn_coap_parser_alloc_message(struct coap_s *handle);
|
|||
*/
|
||||
extern sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_coap_hdr_s *coap_msg_ptr);
|
||||
|
||||
extern sn_coap_hdr_s *sn_coap_parser_alloc_message_with_options(struct coap_s *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -38,7 +38,8 @@ extern "C" {
|
|||
*
|
||||
* \param *used_malloc_func_ptr is function pointer for used memory allocation function.
|
||||
*
|
||||
* \param *used_free_func_ptr is function pointer for used memory free function.
|
||||
* \param *used_free_func_ptr is function pointer for used memory free function. Note: the implementation
|
||||
* must handle NULL parameter and ignore it just as typical libc's free() does.
|
||||
*
|
||||
* \param *used_tx_callback_ptr function callback pointer to tx function for sending coap messages
|
||||
*
|
||||
|
@ -234,7 +235,7 @@ extern int8_t sn_coap_protocol_delete_retransmission(struct coap_s *handle, uint
|
|||
*
|
||||
* \brief If re-transmissions are enabled, this function removes message from retransmission buffer.
|
||||
*/
|
||||
extern int8_t sn_coap_protocol_delete_retransmission_by_token(struct coap_s *handle, uint8_t *token, uint8_t token_len);
|
||||
extern int8_t sn_coap_protocol_delete_retransmission_by_token(struct coap_s *handle, const uint8_t *token, uint8_t token_len);
|
||||
|
||||
/**
|
||||
* \fn int8_t sn_coap_convert_block_size(uint16_t block_size)
|
||||
|
|
|
@ -250,4 +250,14 @@
|
|||
#define SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE UINT16_MAX
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def SN_COAP_BLOCKWISE_INTERNAL_BLOCK_2_HANDLING_ENABLED
|
||||
* \brief A size optimization switch, which removes the blockwise Block2 response if set to 0.
|
||||
* handling code which is typically overridden by a call of "sn_coap_protocol_handle_block2_response_internally(coap, false);".
|
||||
* By default the code is there, so the override can be reversed by "sn_coap_protocol_handle_block2_response_internally(coap, true)".
|
||||
*/
|
||||
#ifndef SN_COAP_BLOCKWISE_INTERNAL_BLOCK_2_HANDLING_ENABLED
|
||||
#define SN_COAP_BLOCKWISE_INTERNAL_BLOCK_2_HANDLING_ENABLED 1
|
||||
#endif
|
||||
|
||||
#endif // SN_CONFIG_H
|
||||
|
|
|
@ -58,7 +58,7 @@ extern "C" {
|
|||
* \brief This structure is returned by sn_coap_exec() for sending
|
||||
*/
|
||||
typedef struct sn_nsdl_transmit_ {
|
||||
sn_nsdl_addr_s *dst_addr_ptr;
|
||||
sn_nsdl_addr_s dst_addr_ptr;
|
||||
|
||||
sn_nsdl_capab_e protocol;
|
||||
|
||||
|
@ -69,7 +69,7 @@ typedef struct sn_nsdl_transmit_ {
|
|||
/* * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* * * * EXTERNAL FUNCTION PROTOTYPES * * * */
|
||||
/* * * * * * * * * * * * * * * * * * * * * * */
|
||||
extern int8_t sn_coap_header_validity_check(sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version);
|
||||
extern int8_t sn_coap_header_validity_check(const sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version);
|
||||
|
||||
#endif /* SN_COAP_HEADER_INTERNAL_H_ */
|
||||
|
||||
|
|
|
@ -48,9 +48,8 @@ typedef struct coap_send_msg_ {
|
|||
uint8_t resending_counter; /* Tells how many times message is still tried to resend */
|
||||
uint32_t resending_time; /* Tells next resending time */
|
||||
|
||||
sn_nsdl_transmit_s *send_msg_ptr;
|
||||
sn_nsdl_transmit_s send_msg_ptr;
|
||||
|
||||
struct coap_s *coap; /* CoAP library handle */
|
||||
void *param; /* Extra parameter that will be passed to TX/RX callback functions */
|
||||
|
||||
ns_list_link_t link;
|
||||
|
@ -64,7 +63,6 @@ typedef struct coap_duplication_info_ {
|
|||
uint16_t msg_id;
|
||||
uint16_t packet_len;
|
||||
uint8_t *packet_ptr;
|
||||
struct coap_s *coap; /* CoAP library handle */
|
||||
sn_nsdl_addr_s *address;
|
||||
void *param;
|
||||
ns_list_link_t link;
|
||||
|
@ -77,7 +75,6 @@ typedef struct coap_blockwise_msg_ {
|
|||
uint32_t timestamp; /* Tells when Blockwise message is stored to Linked list */
|
||||
|
||||
sn_coap_hdr_s *coap_msg_ptr;
|
||||
struct coap_s *coap; /* CoAP library handle */
|
||||
|
||||
void *param;
|
||||
uint16_t msg_id;
|
||||
|
@ -100,7 +97,6 @@ typedef struct coap_blockwise_payload_ {
|
|||
|
||||
uint16_t payload_len;
|
||||
uint8_t *payload_ptr;
|
||||
struct coap_s *coap; /* CoAP library handle */
|
||||
|
||||
ns_list_link_t link;
|
||||
} coap_blockwise_payload_s;
|
||||
|
@ -139,6 +135,12 @@ struct coap_s {
|
|||
uint8_t sn_coap_internal_block2_resp_handling; /* If this is set then coap itself sends a next GET request automatically */
|
||||
};
|
||||
|
||||
/* Utility function which performs a call to sn_coap_protocol_malloc() and memset's the result to zero. */
|
||||
void *sn_coap_protocol_calloc(struct coap_s *handle, uint16_t length);
|
||||
|
||||
/* Utility function which performs a call to sn_coap_protocol_malloc() and memcopy's the source to result buffer. */
|
||||
void *sn_coap_protocol_malloc_copy(struct coap_s *handle, const void *source, uint16_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -37,19 +37,19 @@
|
|||
|
||||
#define TRACE_GROUP "coap"
|
||||
/* * * * LOCAL FUNCTION PROTOTYPES * * * */
|
||||
static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option);
|
||||
static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number);
|
||||
static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option, uint16_t *previous_option_number);
|
||||
static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, const uint8_t *query_ptr, sn_coap_option_numbers_e option);
|
||||
static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, const uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number);
|
||||
static void sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, const uint8_t *src_pptr, uint16_t src_len_ptr, sn_coap_option_numbers_e option, uint16_t *previous_option_number);
|
||||
static uint8_t sn_coap_builder_options_build_add_uint_option(uint8_t **dst_packet_data_pptr, uint32_t value, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number);
|
||||
static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option);
|
||||
static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option);
|
||||
static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option);
|
||||
static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr/*, uint8_t block_option*/);
|
||||
static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, const uint8_t *query_ptr, sn_coap_option_numbers_e option);
|
||||
static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, const uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option);
|
||||
static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, const uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option);
|
||||
static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
static uint8_t sn_coap_builder_options_calculate_jump_need(const sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
|
||||
sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)
|
||||
sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, const sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)
|
||||
{
|
||||
sn_coap_hdr_s *coap_res_ptr;
|
||||
|
||||
|
@ -86,25 +86,24 @@ sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap
|
|||
|
||||
if (coap_packet_ptr->token_ptr) {
|
||||
coap_res_ptr->token_len = coap_packet_ptr->token_len;
|
||||
coap_res_ptr->token_ptr = handle->sn_coap_protocol_malloc(coap_res_ptr->token_len);
|
||||
coap_res_ptr->token_ptr = sn_coap_protocol_malloc_copy(handle, coap_packet_ptr->token_ptr, coap_res_ptr->token_len);
|
||||
if (!coap_res_ptr->token_ptr) {
|
||||
tr_error("sn_coap_build_response - failed to allocate token!");
|
||||
handle->sn_coap_protocol_free(coap_res_ptr);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(coap_res_ptr->token_ptr, coap_packet_ptr->token_ptr, coap_res_ptr->token_len);
|
||||
}
|
||||
return coap_res_ptr;
|
||||
}
|
||||
|
||||
int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, const sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
{
|
||||
return sn_coap_builder_2(dst_packet_data_ptr, src_coap_msg_ptr, SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE);
|
||||
}
|
||||
|
||||
int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size)
|
||||
int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, const sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size)
|
||||
{
|
||||
uint8_t *base_packet_data_ptr = NULL;
|
||||
uint8_t *base_packet_data_ptr;
|
||||
|
||||
/* * * * Check given pointers * * * */
|
||||
if (dst_packet_data_ptr == NULL || src_coap_msg_ptr == NULL) {
|
||||
|
@ -118,6 +117,7 @@ int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_
|
|||
return -1;
|
||||
}
|
||||
|
||||
// XXX: this should not be needed anymore but I have no courage to remove it yet.
|
||||
memset(dst_packet_data_ptr, 0, dst_byte_count_to_be_built);
|
||||
|
||||
/* * * * Store base (= original) destination Packet data pointer for later usage * * * */
|
||||
|
@ -147,12 +147,12 @@ int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_
|
|||
/* * * * Return built Packet data length * * * */
|
||||
return (dst_packet_data_ptr - base_packet_data_ptr);
|
||||
}
|
||||
uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
uint16_t sn_coap_builder_calc_needed_packet_data_size(const sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
{
|
||||
return sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE);
|
||||
}
|
||||
|
||||
uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size)
|
||||
uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size)
|
||||
{
|
||||
(void)blockwise_payload_size;
|
||||
uint16_t returned_byte_count = 0;
|
||||
|
@ -203,30 +203,33 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_
|
|||
}
|
||||
/* If options list pointer exists */
|
||||
if (src_coap_msg_ptr->options_list_ptr != NULL) {
|
||||
|
||||
const sn_coap_options_list_s *src_options_list_ptr = src_coap_msg_ptr->options_list_ptr;
|
||||
|
||||
/* ACCEPT - An integer option, up to 2 bytes */
|
||||
if (src_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE) {
|
||||
if ((uint32_t) src_coap_msg_ptr->options_list_ptr->accept > 0xffff) {
|
||||
if (src_options_list_ptr->accept != COAP_CT_NONE) {
|
||||
if ((uint32_t) src_options_list_ptr->accept > 0xffff) {
|
||||
tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - accept too large!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->accept, COAP_OPTION_ACCEPT, &tempInt);
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->accept, COAP_OPTION_ACCEPT, &tempInt);
|
||||
}
|
||||
/* MAX AGE - An integer option, omitted for default. Up to 4 bytes */
|
||||
if (src_coap_msg_ptr->options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) {
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->max_age, COAP_OPTION_MAX_AGE, &tempInt);
|
||||
if (src_options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) {
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->max_age, COAP_OPTION_MAX_AGE, &tempInt);
|
||||
}
|
||||
/* PROXY URI - Length of this option is 1-1034 bytes */
|
||||
if (src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) {
|
||||
if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 1 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 12) { /* Add option header byte(s) - depending of option length */
|
||||
if (src_options_list_ptr->proxy_uri_ptr != NULL) {
|
||||
if (src_options_list_ptr->proxy_uri_len >= 1 && src_options_list_ptr->proxy_uri_len <= 12) { /* Add option header byte(s) - depending of option length */
|
||||
returned_byte_count++;
|
||||
}
|
||||
|
||||
else if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 13 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 269) {
|
||||
else if (src_options_list_ptr->proxy_uri_len >= 13 && src_options_list_ptr->proxy_uri_len <= 269) {
|
||||
returned_byte_count += 2;
|
||||
}
|
||||
|
||||
else if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 270 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 1034) {
|
||||
else if (src_options_list_ptr->proxy_uri_len >= 270 && src_options_list_ptr->proxy_uri_len <= 1034) {
|
||||
returned_byte_count += 3;
|
||||
}
|
||||
|
||||
|
@ -236,12 +239,12 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_
|
|||
}
|
||||
|
||||
/* Add needed memory for Option value */
|
||||
returned_byte_count += src_coap_msg_ptr->options_list_ptr->proxy_uri_len;
|
||||
returned_byte_count += src_options_list_ptr->proxy_uri_len;
|
||||
}
|
||||
/* ETAG - Repeatable option. Length of this option is 1-8 bytes*/
|
||||
if (src_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) {
|
||||
repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->etag_len,
|
||||
src_coap_msg_ptr->options_list_ptr->etag_ptr, COAP_OPTION_ETAG);
|
||||
if (src_options_list_ptr->etag_ptr != NULL) {
|
||||
repeatable_option_size = sn_coap_builder_options_calc_option_size(src_options_list_ptr->etag_len,
|
||||
src_options_list_ptr->etag_ptr, COAP_OPTION_ETAG);
|
||||
if (repeatable_option_size) {
|
||||
returned_byte_count += repeatable_option_size;
|
||||
} else {
|
||||
|
@ -250,12 +253,12 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_
|
|||
}
|
||||
}
|
||||
/* URI HOST - Length of this option is 1-255 bytes */
|
||||
if (src_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) {
|
||||
if (src_coap_msg_ptr->options_list_ptr->uri_host_len > 0 && src_coap_msg_ptr->options_list_ptr->uri_host_len <= 12) {
|
||||
if (src_options_list_ptr->uri_host_ptr != NULL) {
|
||||
if (src_options_list_ptr->uri_host_len > 0 && src_options_list_ptr->uri_host_len <= 12) {
|
||||
returned_byte_count++;
|
||||
}
|
||||
|
||||
else if (src_coap_msg_ptr->options_list_ptr->uri_host_len >= 13 && src_coap_msg_ptr->options_list_ptr->uri_host_len <= 255) {
|
||||
else if (src_options_list_ptr->uri_host_len >= 13 && src_options_list_ptr->uri_host_len <= 255) {
|
||||
returned_byte_count += 2;
|
||||
}
|
||||
|
||||
|
@ -264,12 +267,12 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_
|
|||
return 0;
|
||||
}
|
||||
|
||||
returned_byte_count += src_coap_msg_ptr->options_list_ptr->uri_host_len;
|
||||
returned_byte_count += src_options_list_ptr->uri_host_len;
|
||||
}
|
||||
/* LOCATION PATH - Repeatable option. Length of this option is 0-255 bytes*/
|
||||
if (src_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) {
|
||||
repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->location_path_len,
|
||||
src_coap_msg_ptr->options_list_ptr->location_path_ptr, COAP_OPTION_LOCATION_PATH);
|
||||
if (src_options_list_ptr->location_path_ptr != NULL) {
|
||||
repeatable_option_size = sn_coap_builder_options_calc_option_size(src_options_list_ptr->location_path_len,
|
||||
src_options_list_ptr->location_path_ptr, COAP_OPTION_LOCATION_PATH);
|
||||
if (repeatable_option_size) {
|
||||
returned_byte_count += repeatable_option_size;
|
||||
} else {
|
||||
|
@ -278,17 +281,17 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_
|
|||
}
|
||||
}
|
||||
/* URI PORT - An integer option, up to 2 bytes */
|
||||
if (src_coap_msg_ptr->options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
|
||||
if ((uint32_t) src_coap_msg_ptr->options_list_ptr->uri_port > 0xffff) {
|
||||
if (src_options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
|
||||
if ((uint32_t) src_options_list_ptr->uri_port > 0xffff) {
|
||||
tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - uri port too large!");
|
||||
return 0;
|
||||
}
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->uri_port, COAP_OPTION_URI_PORT, &tempInt);
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->uri_port, COAP_OPTION_URI_PORT, &tempInt);
|
||||
}
|
||||
/* lOCATION QUERY - Repeatable option. Length of this option is 0-255 bytes */
|
||||
if (src_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) {
|
||||
repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->location_query_len,
|
||||
src_coap_msg_ptr->options_list_ptr->location_query_ptr, COAP_OPTION_LOCATION_QUERY);
|
||||
if (src_options_list_ptr->location_query_ptr != NULL) {
|
||||
repeatable_option_size = sn_coap_builder_options_calc_option_size(src_options_list_ptr->location_query_len,
|
||||
src_options_list_ptr->location_query_ptr, COAP_OPTION_LOCATION_QUERY);
|
||||
if (repeatable_option_size) {
|
||||
returned_byte_count += repeatable_option_size;
|
||||
} else {
|
||||
|
@ -297,16 +300,16 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_
|
|||
}
|
||||
}
|
||||
/* OBSERVE - An integer option, up to 3 bytes */
|
||||
if (src_coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
|
||||
if ((uint32_t) src_coap_msg_ptr->options_list_ptr->observe > 0xffffff) {
|
||||
if (src_options_list_ptr->observe != COAP_OBSERVE_NONE) {
|
||||
if ((uint32_t) src_options_list_ptr->observe > 0xffffff) {
|
||||
return 0;
|
||||
}
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->observe, COAP_OPTION_OBSERVE, &tempInt);
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->observe, COAP_OPTION_OBSERVE, &tempInt);
|
||||
}
|
||||
/* URI QUERY - Repeatable option. Length of this option is 1-255 */
|
||||
if (src_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) {
|
||||
repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->uri_query_len,
|
||||
src_coap_msg_ptr->options_list_ptr->uri_query_ptr, COAP_OPTION_URI_QUERY);
|
||||
if (src_options_list_ptr->uri_query_ptr != NULL) {
|
||||
repeatable_option_size = sn_coap_builder_options_calc_option_size(src_options_list_ptr->uri_query_len,
|
||||
src_options_list_ptr->uri_query_ptr, COAP_OPTION_URI_QUERY);
|
||||
if (repeatable_option_size) {
|
||||
returned_byte_count += repeatable_option_size;
|
||||
} else {
|
||||
|
@ -316,28 +319,28 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_
|
|||
}
|
||||
|
||||
/* BLOCK 1 - An integer option, up to 3 bytes */
|
||||
if (src_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
|
||||
if ((uint32_t) src_coap_msg_ptr->options_list_ptr->block1 > 0xffffff) {
|
||||
if (src_options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
|
||||
if ((uint32_t) src_options_list_ptr->block1 > 0xffffff) {
|
||||
tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - block1 too large!");
|
||||
return 0;
|
||||
}
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->block1, COAP_OPTION_BLOCK1, &tempInt);
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->block1, COAP_OPTION_BLOCK1, &tempInt);
|
||||
}
|
||||
/* SIZE1 - Length of this option is 0-4 bytes */
|
||||
if (src_coap_msg_ptr->options_list_ptr->use_size1) {
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->size1, COAP_OPTION_SIZE1, &tempInt);
|
||||
if (src_options_list_ptr->use_size1) {
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->size1, COAP_OPTION_SIZE1, &tempInt);
|
||||
}
|
||||
/* BLOCK 2 - An integer option, up to 3 bytes */
|
||||
if (src_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
|
||||
if ((uint32_t) src_coap_msg_ptr->options_list_ptr->block2 > 0xffffff) {
|
||||
if (src_options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
|
||||
if ((uint32_t) src_options_list_ptr->block2 > 0xffffff) {
|
||||
tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - block2 too large!");
|
||||
return 0;
|
||||
}
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->block2, COAP_OPTION_BLOCK2, &tempInt);
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->block2, COAP_OPTION_BLOCK2, &tempInt);
|
||||
}
|
||||
/* SIZE2 - Length of this option is 0-4 bytes */
|
||||
if (src_coap_msg_ptr->options_list_ptr->use_size2) {
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->size2, COAP_OPTION_SIZE2, &tempInt);
|
||||
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->size2, COAP_OPTION_SIZE2, &tempInt);
|
||||
}
|
||||
}
|
||||
#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
|
||||
|
@ -354,12 +357,12 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_
|
|||
if (src_coap_msg_ptr->payload_len) {
|
||||
returned_byte_count ++; /* For payload marker */
|
||||
}
|
||||
returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr/*, 0*/);
|
||||
returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr);
|
||||
}
|
||||
return returned_byte_count;
|
||||
}
|
||||
/**
|
||||
* \fn static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr, uint8_t block_option)
|
||||
* \fn static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
*
|
||||
* \brief Checks if there is need for option jump
|
||||
*
|
||||
|
@ -370,43 +373,47 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_
|
|||
* \return Returns bytes needed for jumping
|
||||
*/
|
||||
|
||||
static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr/*, uint8_t block_option*/)
|
||||
static uint8_t sn_coap_builder_options_calculate_jump_need(const sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
{
|
||||
uint8_t previous_option_number = 0;
|
||||
uint8_t needed_space = 0;
|
||||
|
||||
if (src_coap_msg_ptr->options_list_ptr != NULL) {
|
||||
const sn_coap_options_list_s* options_list_ptr = src_coap_msg_ptr->options_list_ptr;
|
||||
|
||||
if (options_list_ptr != NULL) {
|
||||
|
||||
|
||||
/* If option numbers greater than 12 is not used, then jumping is not needed */
|
||||
//TODO: Check if this is really needed! Does it enhance perf? If not -> remove
|
||||
if (!src_coap_msg_ptr->options_list_ptr->uri_query_ptr &&
|
||||
src_coap_msg_ptr->options_list_ptr->accept == COAP_CT_NONE &&
|
||||
!src_coap_msg_ptr->options_list_ptr->location_query_ptr &&
|
||||
src_coap_msg_ptr->options_list_ptr->block2 == COAP_OPTION_BLOCK_NONE &&
|
||||
src_coap_msg_ptr->options_list_ptr->block1 == COAP_OPTION_BLOCK_NONE &&
|
||||
!src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr &&
|
||||
src_coap_msg_ptr->options_list_ptr->max_age == COAP_OPTION_MAX_AGE_DEFAULT &&
|
||||
!src_coap_msg_ptr->options_list_ptr->use_size1 &&
|
||||
!src_coap_msg_ptr->options_list_ptr->use_size2) {
|
||||
if (!options_list_ptr->uri_query_ptr &&
|
||||
options_list_ptr->accept == COAP_CT_NONE &&
|
||||
!options_list_ptr->location_query_ptr &&
|
||||
options_list_ptr->block2 == COAP_OPTION_BLOCK_NONE &&
|
||||
options_list_ptr->block1 == COAP_OPTION_BLOCK_NONE &&
|
||||
!options_list_ptr->proxy_uri_ptr &&
|
||||
options_list_ptr->max_age == COAP_OPTION_MAX_AGE_DEFAULT &&
|
||||
!options_list_ptr->use_size1 &&
|
||||
!options_list_ptr->use_size2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (src_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) {
|
||||
if (options_list_ptr->uri_host_ptr != NULL) {
|
||||
previous_option_number = (COAP_OPTION_URI_HOST);
|
||||
}
|
||||
|
||||
if (src_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) {
|
||||
if (options_list_ptr->etag_ptr != NULL) {
|
||||
previous_option_number = (COAP_OPTION_ETAG);
|
||||
}
|
||||
|
||||
if (src_coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
|
||||
if (options_list_ptr->observe != COAP_OBSERVE_NONE) {
|
||||
previous_option_number = (COAP_OPTION_OBSERVE);
|
||||
}
|
||||
|
||||
if (src_coap_msg_ptr->options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
|
||||
if (options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
|
||||
previous_option_number = (COAP_OPTION_URI_PORT);
|
||||
}
|
||||
|
||||
if (src_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) {
|
||||
if (options_list_ptr->location_path_ptr != NULL) {
|
||||
previous_option_number = (COAP_OPTION_LOCATION_PATH);
|
||||
}
|
||||
|
||||
|
@ -416,50 +423,51 @@ static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_co
|
|||
if (src_coap_msg_ptr->content_format != COAP_CT_NONE) {
|
||||
previous_option_number = (COAP_OPTION_CONTENT_FORMAT);
|
||||
}
|
||||
if (src_coap_msg_ptr->options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) {
|
||||
|
||||
if (options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) {
|
||||
if ((COAP_OPTION_MAX_AGE - previous_option_number) > 12) {
|
||||
needed_space += 1;
|
||||
}
|
||||
previous_option_number = (COAP_OPTION_MAX_AGE);
|
||||
}
|
||||
|
||||
if (src_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) {
|
||||
if (options_list_ptr->uri_query_ptr != NULL) {
|
||||
if ((COAP_OPTION_URI_QUERY - previous_option_number) > 12) {
|
||||
needed_space += 1;
|
||||
}
|
||||
previous_option_number = (COAP_OPTION_URI_QUERY);
|
||||
}
|
||||
if (src_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE) {
|
||||
if (options_list_ptr->accept != COAP_CT_NONE) {
|
||||
if ((COAP_OPTION_ACCEPT - previous_option_number) > 12) {
|
||||
needed_space += 1;
|
||||
}
|
||||
previous_option_number = (COAP_OPTION_ACCEPT);
|
||||
}
|
||||
if (src_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) {
|
||||
if (options_list_ptr->location_query_ptr != NULL) {
|
||||
if ((COAP_OPTION_LOCATION_QUERY - previous_option_number) > 12) {
|
||||
needed_space += 1;
|
||||
}
|
||||
previous_option_number = (COAP_OPTION_LOCATION_QUERY);
|
||||
}
|
||||
if (src_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
|
||||
if (options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
|
||||
if ((COAP_OPTION_BLOCK2 - previous_option_number) > 12 ){
|
||||
needed_space += 1;
|
||||
}
|
||||
previous_option_number = (COAP_OPTION_BLOCK2);
|
||||
}
|
||||
if (src_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
|
||||
if (options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
|
||||
if ((COAP_OPTION_BLOCK1 - previous_option_number) > 12 ){
|
||||
needed_space += 1;
|
||||
}
|
||||
previous_option_number = (COAP_OPTION_BLOCK1);
|
||||
}
|
||||
if (src_coap_msg_ptr->options_list_ptr->use_size2) {
|
||||
if (options_list_ptr->use_size2) {
|
||||
if ((COAP_OPTION_SIZE2 - previous_option_number) > 12) {
|
||||
needed_space += 1;
|
||||
}
|
||||
previous_option_number = (COAP_OPTION_SIZE2);
|
||||
}
|
||||
if (src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) {
|
||||
if (options_list_ptr->proxy_uri_ptr != NULL) {
|
||||
if ((COAP_OPTION_PROXY_URI - previous_option_number) > 12) {
|
||||
needed_space += 1;
|
||||
}
|
||||
|
@ -468,7 +476,7 @@ static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_co
|
|||
}
|
||||
previous_option_number = (COAP_OPTION_PROXY_URI);
|
||||
}
|
||||
if (src_coap_msg_ptr->options_list_ptr->use_size1 ) {
|
||||
if (options_list_ptr->use_size1) {
|
||||
if ((COAP_OPTION_SIZE1 - previous_option_number) > 12) {
|
||||
needed_space += 1;
|
||||
}
|
||||
|
@ -499,7 +507,7 @@ static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_co
|
|||
*
|
||||
* \return Return value is 0 in ok case and -1 in failure case
|
||||
**************************************************************************** */
|
||||
static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
{
|
||||
/* * * * Check validity of Header values * * * */
|
||||
if (sn_coap_header_validity_check(src_coap_msg_ptr, COAP_VERSION) != 0) {
|
||||
|
@ -507,25 +515,19 @@ static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_co
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* * * Add CoAP Version * * */
|
||||
**dst_packet_data_pptr += COAP_VERSION;
|
||||
uint8_t* dest_packet = *dst_packet_data_pptr;
|
||||
|
||||
/* * * Add Message type * * */
|
||||
**dst_packet_data_pptr += src_coap_msg_ptr->msg_type;
|
||||
/* Set CoAP Version, Message type and Token length */
|
||||
dest_packet[0] = COAP_VERSION | src_coap_msg_ptr->msg_type | src_coap_msg_ptr->token_len;
|
||||
|
||||
/* * * Add Token length * * */
|
||||
**dst_packet_data_pptr += (src_coap_msg_ptr->token_len);
|
||||
|
||||
(*dst_packet_data_pptr) ++;
|
||||
/* * * Add Message code * * */
|
||||
**dst_packet_data_pptr = src_coap_msg_ptr->msg_code;
|
||||
(*dst_packet_data_pptr) ++;
|
||||
dest_packet[1] = src_coap_msg_ptr->msg_code;
|
||||
|
||||
/* * * Add Message ID * * */
|
||||
**dst_packet_data_pptr = (uint8_t)(src_coap_msg_ptr->msg_id >> COAP_HEADER_MSG_ID_MSB_SHIFT); /* MSB part */
|
||||
(*dst_packet_data_pptr) ++;
|
||||
**dst_packet_data_pptr = (uint8_t)src_coap_msg_ptr->msg_id; /* LSB part */
|
||||
(*dst_packet_data_pptr) ++;
|
||||
dest_packet[2] = (uint8_t)(src_coap_msg_ptr->msg_id >> COAP_HEADER_MSG_ID_MSB_SHIFT); /* MSB part */
|
||||
dest_packet[3] = (uint8_t)src_coap_msg_ptr->msg_id; /* LSB part */
|
||||
|
||||
*dst_packet_data_pptr = dest_packet + 4;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
|
@ -542,7 +544,7 @@ static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_co
|
|||
*
|
||||
* \return Return value is 0 in every case
|
||||
*/
|
||||
static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
{
|
||||
/* * * * Check if Options are used at all * * * */
|
||||
if (src_coap_msg_ptr->uri_path_ptr == NULL && src_coap_msg_ptr->token_ptr == NULL &&
|
||||
|
@ -567,35 +569,37 @@ static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_c
|
|||
|
||||
//missing: COAP_OPTION_IF_MATCH, COAP_OPTION_IF_NONE_MATCH, COAP_OPTION_SIZE
|
||||
|
||||
const sn_coap_options_list_s *src_options_list_ptr = src_coap_msg_ptr->options_list_ptr;
|
||||
|
||||
/* Check if less used options are used at all */
|
||||
if (src_coap_msg_ptr->options_list_ptr != NULL) {
|
||||
if (src_options_list_ptr != NULL) {
|
||||
/* * * * Build Uri-Host option * * * */
|
||||
sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->uri_host_len,
|
||||
src_coap_msg_ptr->options_list_ptr->uri_host_ptr, COAP_OPTION_URI_HOST, &previous_option_number);
|
||||
sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_options_list_ptr->uri_host_len,
|
||||
src_options_list_ptr->uri_host_ptr, COAP_OPTION_URI_HOST, &previous_option_number);
|
||||
|
||||
/* * * * Build ETag option * * * */
|
||||
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->etag_ptr,
|
||||
(uint16_t *)&src_coap_msg_ptr->options_list_ptr->etag_len, COAP_OPTION_ETAG, &previous_option_number);
|
||||
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, src_options_list_ptr->etag_ptr,
|
||||
src_options_list_ptr->etag_len, COAP_OPTION_ETAG, &previous_option_number);
|
||||
|
||||
/* * * * Build Observe option * * * * */
|
||||
if (src_coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->observe,
|
||||
if (src_options_list_ptr->observe != COAP_OBSERVE_NONE) {
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->observe,
|
||||
COAP_OPTION_OBSERVE, &previous_option_number);
|
||||
}
|
||||
|
||||
/* * * * Build Uri-Port option * * * */
|
||||
if (src_coap_msg_ptr->options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->uri_port,
|
||||
if (src_options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->uri_port,
|
||||
COAP_OPTION_URI_PORT, &previous_option_number);
|
||||
}
|
||||
|
||||
/* * * * Build Location-Path option * * * */
|
||||
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->location_path_ptr,
|
||||
&src_coap_msg_ptr->options_list_ptr->location_path_len, COAP_OPTION_LOCATION_PATH, &previous_option_number);
|
||||
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, src_options_list_ptr->location_path_ptr,
|
||||
src_options_list_ptr->location_path_len, COAP_OPTION_LOCATION_PATH, &previous_option_number);
|
||||
}
|
||||
/* * * * Build Uri-Path option * * * */
|
||||
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->uri_path_ptr,
|
||||
&src_coap_msg_ptr->uri_path_len, COAP_OPTION_URI_PATH, &previous_option_number);
|
||||
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, src_coap_msg_ptr->uri_path_ptr,
|
||||
src_coap_msg_ptr->uri_path_len, COAP_OPTION_URI_PATH, &previous_option_number);
|
||||
|
||||
/* * * * Build Content-Type option * * * */
|
||||
if (src_coap_msg_ptr->content_format != COAP_CT_NONE) {
|
||||
|
@ -603,55 +607,53 @@ static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_c
|
|||
COAP_OPTION_CONTENT_FORMAT, &previous_option_number);
|
||||
}
|
||||
|
||||
if (src_coap_msg_ptr->options_list_ptr != NULL) {
|
||||
if (src_options_list_ptr != NULL) {
|
||||
/* * * * Build Max-Age option * * * */
|
||||
if (src_coap_msg_ptr->options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) {
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->max_age,
|
||||
if (src_options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) {
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->max_age,
|
||||
COAP_OPTION_MAX_AGE, &previous_option_number);
|
||||
}
|
||||
|
||||
/* * * * Build Uri-Query option * * * * */
|
||||
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->uri_query_ptr,
|
||||
&src_coap_msg_ptr->options_list_ptr->uri_query_len, COAP_OPTION_URI_QUERY, &previous_option_number);
|
||||
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, src_options_list_ptr->uri_query_ptr,
|
||||
src_options_list_ptr->uri_query_len, COAP_OPTION_URI_QUERY, &previous_option_number);
|
||||
|
||||
/* * * * Build Accept option * * * * */
|
||||
if (src_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE) {
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->accept,
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->accept,
|
||||
COAP_OPTION_ACCEPT, &previous_option_number);
|
||||
}
|
||||
}
|
||||
|
||||
if (src_coap_msg_ptr->options_list_ptr != NULL) {
|
||||
/* * * * Build Location-Query option * * * */
|
||||
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->location_query_ptr,
|
||||
&src_coap_msg_ptr->options_list_ptr->location_query_len, COAP_OPTION_LOCATION_QUERY, &previous_option_number);
|
||||
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, src_options_list_ptr->location_query_ptr,
|
||||
src_options_list_ptr->location_query_len, COAP_OPTION_LOCATION_QUERY, &previous_option_number);
|
||||
|
||||
/* * * * Build Block2 option * * * * */
|
||||
if (src_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->block2,
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->block2,
|
||||
COAP_OPTION_BLOCK2, &previous_option_number);
|
||||
}
|
||||
|
||||
/* * * * Build Block1 option * * * * */
|
||||
if (src_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->block1,
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->block1,
|
||||
COAP_OPTION_BLOCK1, &previous_option_number);
|
||||
}
|
||||
|
||||
/* * * * Build Size2 option * * * */
|
||||
if (src_coap_msg_ptr->options_list_ptr->use_size2) {
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->size2,
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->size2,
|
||||
COAP_OPTION_SIZE2, &previous_option_number);
|
||||
}
|
||||
|
||||
/* * * * Build Proxy-Uri option * * * */
|
||||
sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->proxy_uri_len,
|
||||
src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, COAP_OPTION_PROXY_URI, &previous_option_number);
|
||||
sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_options_list_ptr->proxy_uri_len,
|
||||
src_options_list_ptr->proxy_uri_ptr, COAP_OPTION_PROXY_URI, &previous_option_number);
|
||||
|
||||
|
||||
/* * * * Build Size1 option * * * */
|
||||
if (src_coap_msg_ptr->options_list_ptr->use_size1) {
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->size1,
|
||||
if (src_options_list_ptr->use_size1) {
|
||||
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->size1,
|
||||
COAP_OPTION_SIZE1, &previous_option_number);
|
||||
}
|
||||
}
|
||||
|
@ -676,7 +678,7 @@ static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_c
|
|||
* \return Return value is 0 if option was not added, 1 if added
|
||||
*/
|
||||
static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len,
|
||||
uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number)
|
||||
const uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number)
|
||||
{
|
||||
/* Check if there is option at all */
|
||||
if (option_ptr != NULL) {
|
||||
|
@ -686,61 +688,67 @@ static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet
|
|||
|
||||
/* * * Build option header * * */
|
||||
|
||||
uint8_t first_byte;
|
||||
|
||||
/* First option length without extended part */
|
||||
if (option_len <= 12) {
|
||||
**dst_packet_data_pptr = option_len;
|
||||
first_byte = option_len;
|
||||
}
|
||||
|
||||
else if (option_len > 12 && option_len < 269) {
|
||||
**dst_packet_data_pptr = 0x0D;
|
||||
first_byte = 0x0D;
|
||||
}
|
||||
|
||||
else if (option_len >= 269) {
|
||||
**dst_packet_data_pptr = 0x0E;
|
||||
else /*if (option_len >= 269)*/ {
|
||||
first_byte = 0x0E;
|
||||
}
|
||||
|
||||
uint8_t *dest_packet = *dst_packet_data_pptr;
|
||||
|
||||
/* Then option delta with extensions, and move pointer */
|
||||
if (option_delta <= 12) {
|
||||
**dst_packet_data_pptr += (option_delta << 4);
|
||||
*dst_packet_data_pptr += 1;
|
||||
dest_packet[0] = first_byte + (option_delta << 4);
|
||||
dest_packet += 1;
|
||||
}
|
||||
|
||||
else if (option_delta > 12 && option_delta < 269) {
|
||||
**dst_packet_data_pptr += 0xD0;
|
||||
dest_packet[0] = first_byte + 0xD0;
|
||||
option_delta -= 13;
|
||||
|
||||
*(*dst_packet_data_pptr + 1) = (uint8_t)option_delta;
|
||||
*dst_packet_data_pptr += 2;
|
||||
dest_packet[1] = (uint8_t)option_delta;
|
||||
dest_packet += 2;
|
||||
}
|
||||
//This is currently dead code (but possibly needed in future)
|
||||
else if (option_delta >= 269) {
|
||||
**dst_packet_data_pptr += 0xE0;
|
||||
else /*if (option_delta >= 269)*/ {
|
||||
dest_packet[0] = first_byte + 0xE0;
|
||||
option_delta -= 269;
|
||||
|
||||
*(*dst_packet_data_pptr + 2) = (uint8_t)option_delta;
|
||||
*(*dst_packet_data_pptr + 1) = (option_delta >> 8);
|
||||
*dst_packet_data_pptr += 3;
|
||||
dest_packet[1] = (option_delta >> 8);
|
||||
dest_packet[2] = (uint8_t)option_delta;
|
||||
dest_packet += 3;
|
||||
}
|
||||
|
||||
/* Now option length extensions, if needed */
|
||||
if (option_len > 12 && option_len < 269) {
|
||||
**dst_packet_data_pptr = (uint8_t)(option_len - 13);
|
||||
*dst_packet_data_pptr += 1;
|
||||
dest_packet[0] = (uint8_t)(option_len - 13);
|
||||
dest_packet += 1;
|
||||
}
|
||||
|
||||
else if (option_len >= 269) {
|
||||
*(*dst_packet_data_pptr + 1) = (uint8_t)(option_len - 269);
|
||||
**dst_packet_data_pptr = ((option_len - 269) >> 8);
|
||||
*dst_packet_data_pptr += 2;
|
||||
dest_packet[0] = ((option_len - 269) >> 8);
|
||||
dest_packet[1] = (uint8_t)(option_len - 269);
|
||||
dest_packet += 2;
|
||||
}
|
||||
|
||||
*previous_option_number = option_number;
|
||||
|
||||
/* Write Option value */
|
||||
memcpy(*dst_packet_data_pptr, option_ptr, option_len);
|
||||
memcpy(dest_packet, option_ptr, option_len);
|
||||
|
||||
/* Increase destination Packet data pointer */
|
||||
(*dst_packet_data_pptr) += option_len;
|
||||
dest_packet += option_len;
|
||||
|
||||
*dst_packet_data_pptr = dest_packet;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -775,11 +783,9 @@ static uint8_t sn_coap_builder_options_build_add_uint_option(uint8_t **dst_packe
|
|||
|
||||
/* If output pointer isn't NULL, write it out */
|
||||
if (dst_packet_data_pptr) {
|
||||
int16_t ret = sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, len, payload, option_number, previous_option_number);
|
||||
/* Allow for failure returns when writing (why even permit failure returns?) */
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
// No need to check & handle return value, as the function returns failure only if the option pointer is zero
|
||||
// and it is pointing to a local variable here.
|
||||
sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, len, payload, option_number, previous_option_number);
|
||||
}
|
||||
|
||||
/* Return the total option size */
|
||||
|
@ -793,21 +799,21 @@ static uint8_t sn_coap_builder_options_build_add_uint_option(uint8_t **dst_packe
|
|||
*
|
||||
* \param **dst_packet_data_pptr is destination for built Packet data
|
||||
*
|
||||
* \param uint8_t **src_pptr
|
||||
* \param uint8_t **src_ptr
|
||||
*
|
||||
* \param uint16_t *src_len_ptr
|
||||
* \param uint16_t src_len
|
||||
*
|
||||
* \paramsn_coap_option_numbers_e option option to be added
|
||||
*
|
||||
* \return Return value is 0 always
|
||||
*/
|
||||
static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option, uint16_t *previous_option_number)
|
||||
static void sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, const uint8_t *src_pptr, uint16_t src_len, sn_coap_option_numbers_e option, uint16_t *previous_option_number)
|
||||
{
|
||||
/* Check if there is option at all */
|
||||
if (*src_pptr != NULL) {
|
||||
uint8_t *query_ptr = *src_pptr;
|
||||
if (src_pptr != NULL) {
|
||||
const uint8_t *query_ptr = src_pptr;
|
||||
uint8_t query_part_count = 0;
|
||||
uint16_t query_len = *src_len_ptr;
|
||||
uint16_t query_len = src_len;
|
||||
uint8_t i = 0;
|
||||
uint16_t query_part_offset = 0;
|
||||
|
||||
|
@ -823,11 +829,10 @@ static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_p
|
|||
query_part_offset = sn_coap_builder_options_get_option_part_position(query_len, query_ptr, i, option);
|
||||
|
||||
/* Add Uri-query's one part to Options */
|
||||
sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, one_query_part_len, *src_pptr + query_part_offset, option, previous_option_number);
|
||||
sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, one_query_part_len, src_pptr + query_part_offset, option, previous_option_number);
|
||||
}
|
||||
}
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -842,7 +847,7 @@ static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_p
|
|||
*
|
||||
* \return Return value is count of needed memory as bytes for Uri-query option
|
||||
*/
|
||||
static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option)
|
||||
static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, const uint8_t *query_ptr, sn_coap_option_numbers_e option)
|
||||
{
|
||||
uint8_t query_part_count = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option);
|
||||
uint8_t i = 0;
|
||||
|
@ -923,7 +928,7 @@ static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uin
|
|||
*
|
||||
* \return Return value is count of query parts
|
||||
*/
|
||||
static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option)
|
||||
static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, const uint8_t *query_ptr, sn_coap_option_numbers_e option)
|
||||
{
|
||||
uint8_t returned_query_count = 0;
|
||||
uint16_t query_len_index = 0;
|
||||
|
@ -963,7 +968,7 @@ static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len,
|
|||
*
|
||||
* \return Return value is length of query part
|
||||
*/
|
||||
static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, uint8_t *query_ptr,
|
||||
static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, const uint8_t *query_ptr,
|
||||
uint8_t query_index, sn_coap_option_numbers_e option)
|
||||
{
|
||||
uint16_t returned_query_part_len = 0;
|
||||
|
@ -1021,7 +1026,7 @@ static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option
|
|||
* \return Return value is position (= offset) of query part in whole query. In
|
||||
* fail cases -1 is returned.
|
||||
*/
|
||||
static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, uint8_t *query_ptr,
|
||||
static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, const uint8_t *query_ptr,
|
||||
uint8_t query_index, sn_coap_option_numbers_e option)
|
||||
{
|
||||
uint16_t returned_query_part_offset = 0;
|
||||
|
@ -1076,7 +1081,7 @@ static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_l
|
|||
*
|
||||
* \param *src_coap_msg_ptr is source for building Packet data
|
||||
*/
|
||||
static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
{
|
||||
/* Check if Payload is used at all */
|
||||
if (src_coap_msg_ptr->payload_len && src_coap_msg_ptr->payload_ptr != NULL) {
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
* \return Return value is status of validity check. In ok cases 0 and in
|
||||
* failure cases -1
|
||||
*/
|
||||
int8_t sn_coap_header_validity_check(sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version)
|
||||
int8_t sn_coap_header_validity_check(const sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version)
|
||||
{
|
||||
/* * Check validity of CoAP Version * */
|
||||
if (coap_version != COAP_VERSION_1) {
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr);
|
||||
static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len);
|
||||
static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len, uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len);
|
||||
static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len);
|
||||
static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(const uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len);
|
||||
static int8_t sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr);
|
||||
|
||||
sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr)
|
||||
|
@ -64,6 +64,29 @@ sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr)
|
|||
return coap_msg_ptr;
|
||||
}
|
||||
|
||||
sn_coap_hdr_s *sn_coap_parser_alloc_message_with_options(struct coap_s *handle)
|
||||
{
|
||||
// check the handle just as in any other place
|
||||
if (handle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sn_coap_hdr_s *coap_msg_ptr = sn_coap_parser_alloc_message(handle);
|
||||
|
||||
sn_coap_options_list_s *options_list_ptr = sn_coap_parser_alloc_options(handle, coap_msg_ptr);
|
||||
|
||||
if ((coap_msg_ptr == NULL) || (options_list_ptr == NULL)) {
|
||||
|
||||
// oops, out of memory free if got already any
|
||||
handle->sn_coap_protocol_free(coap_msg_ptr);
|
||||
handle->sn_coap_protocol_free(options_list_ptr);
|
||||
|
||||
coap_msg_ptr = NULL;
|
||||
}
|
||||
|
||||
return coap_msg_ptr;
|
||||
}
|
||||
|
||||
sn_coap_hdr_s *sn_coap_parser_alloc_message(struct coap_s *handle)
|
||||
{
|
||||
sn_coap_hdr_s *returned_coap_msg_ptr;
|
||||
|
@ -81,6 +104,8 @@ sn_coap_hdr_s *sn_coap_parser_alloc_message(struct coap_s *handle)
|
|||
|
||||
sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_coap_hdr_s *coap_msg_ptr)
|
||||
{
|
||||
sn_coap_options_list_s *options_list_ptr;
|
||||
|
||||
/* * * * Check given pointers * * * */
|
||||
if (handle == NULL || coap_msg_ptr == NULL) {
|
||||
return NULL;
|
||||
|
@ -92,24 +117,23 @@ sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_c
|
|||
}
|
||||
|
||||
/* * * * Allocate memory for options and initialize allocated memory with with default values * * * */
|
||||
coap_msg_ptr->options_list_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_options_list_s));
|
||||
/* XXX not technically legal to memset pointers to 0 */
|
||||
options_list_ptr = sn_coap_protocol_calloc(handle, sizeof(sn_coap_options_list_s));
|
||||
|
||||
if (coap_msg_ptr->options_list_ptr == NULL) {
|
||||
if (options_list_ptr == NULL) {
|
||||
tr_error("sn_coap_parser_alloc_options - failed to allocate options list!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* XXX not technically legal to memset pointers to 0 */
|
||||
memset(coap_msg_ptr->options_list_ptr, 0x00, sizeof(sn_coap_options_list_s));
|
||||
coap_msg_ptr->options_list_ptr = options_list_ptr;
|
||||
|
||||
coap_msg_ptr->options_list_ptr->max_age = 0;
|
||||
coap_msg_ptr->options_list_ptr->uri_port = COAP_OPTION_URI_PORT_NONE;
|
||||
coap_msg_ptr->options_list_ptr->observe = COAP_OBSERVE_NONE;
|
||||
coap_msg_ptr->options_list_ptr->accept = COAP_CT_NONE;
|
||||
coap_msg_ptr->options_list_ptr->block2 = COAP_OPTION_BLOCK_NONE;
|
||||
coap_msg_ptr->options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE;
|
||||
options_list_ptr->uri_port = COAP_OPTION_URI_PORT_NONE;
|
||||
options_list_ptr->observe = COAP_OBSERVE_NONE;
|
||||
options_list_ptr->accept = COAP_CT_NONE;
|
||||
options_list_ptr->block2 = COAP_OPTION_BLOCK_NONE;
|
||||
options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE;
|
||||
|
||||
return coap_msg_ptr->options_list_ptr;
|
||||
return options_list_ptr;
|
||||
}
|
||||
|
||||
sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr)
|
||||
|
@ -156,43 +180,35 @@ void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coa
|
|||
}
|
||||
|
||||
if (freed_coap_msg_ptr != NULL) {
|
||||
if (freed_coap_msg_ptr->uri_path_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->uri_path_ptr);
|
||||
|
||||
// As there are multiple sequential calls to the protocol_free, caching pointer to it
|
||||
// saves one instruction per call.
|
||||
void (*local_free)(void *) = handle->sn_coap_protocol_free;
|
||||
|
||||
local_free(freed_coap_msg_ptr->uri_path_ptr);
|
||||
local_free(freed_coap_msg_ptr->token_ptr);
|
||||
|
||||
// same here, caching the struct start saves a bit.
|
||||
sn_coap_options_list_s *options_list_ptr = freed_coap_msg_ptr->options_list_ptr;
|
||||
|
||||
if (options_list_ptr != NULL) {
|
||||
|
||||
local_free(options_list_ptr->proxy_uri_ptr);
|
||||
|
||||
local_free(options_list_ptr->etag_ptr);
|
||||
|
||||
local_free(options_list_ptr->uri_host_ptr);
|
||||
|
||||
local_free(options_list_ptr->location_path_ptr);
|
||||
|
||||
local_free(options_list_ptr->location_query_ptr);
|
||||
|
||||
local_free(options_list_ptr->uri_query_ptr);
|
||||
|
||||
local_free(options_list_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->token_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->token_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->options_list_ptr != NULL) {
|
||||
if (freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->etag_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_host_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->location_path_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->location_query_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_query_ptr);
|
||||
}
|
||||
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr);
|
||||
}
|
||||
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr);
|
||||
local_free(freed_coap_msg_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,14 +285,13 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack
|
|||
return -1;
|
||||
}
|
||||
|
||||
dst_coap_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(dst_coap_msg_ptr->token_len);
|
||||
dst_coap_msg_ptr->token_ptr = sn_coap_protocol_malloc_copy(handle, *packet_data_pptr, dst_coap_msg_ptr->token_len);
|
||||
|
||||
if (dst_coap_msg_ptr->token_ptr == NULL) {
|
||||
tr_error("sn_coap_parser_options_parse - failed to allocate token!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(dst_coap_msg_ptr->token_ptr, *packet_data_pptr, dst_coap_msg_ptr->token_len);
|
||||
(*packet_data_pptr) += dst_coap_msg_ptr->token_len;
|
||||
}
|
||||
|
||||
|
@ -379,14 +394,13 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack
|
|||
dst_coap_msg_ptr->options_list_ptr->proxy_uri_len = option_len;
|
||||
(*packet_data_pptr)++;
|
||||
|
||||
dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr = handle->sn_coap_protocol_malloc(option_len);
|
||||
dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr = sn_coap_protocol_malloc_copy(handle, *packet_data_pptr, option_len);
|
||||
|
||||
if (dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr == NULL) {
|
||||
tr_error("sn_coap_parser_options_parse - COAP_OPTION_PROXY_URI allocation failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, *packet_data_pptr, option_len);
|
||||
(*packet_data_pptr) += option_len;
|
||||
|
||||
break;
|
||||
|
@ -415,13 +429,12 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack
|
|||
dst_coap_msg_ptr->options_list_ptr->uri_host_len = option_len;
|
||||
(*packet_data_pptr)++;
|
||||
|
||||
dst_coap_msg_ptr->options_list_ptr->uri_host_ptr = handle->sn_coap_protocol_malloc(option_len);
|
||||
dst_coap_msg_ptr->options_list_ptr->uri_host_ptr = sn_coap_protocol_malloc_copy(handle, *packet_data_pptr, option_len);
|
||||
|
||||
if (dst_coap_msg_ptr->options_list_ptr->uri_host_ptr == NULL) {
|
||||
tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_HOST allocation failed!");
|
||||
return -1;
|
||||
}
|
||||
memcpy(dst_coap_msg_ptr->options_list_ptr->uri_host_ptr, *packet_data_pptr, option_len);
|
||||
(*packet_data_pptr) += option_len;
|
||||
|
||||
break;
|
||||
|
@ -623,9 +636,9 @@ static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handl
|
|||
/* Uri-Query is modified to following format: temp1'\0'temp2'\0'temp3 i.e. */
|
||||
/* Uri-Path is modified to following format: temp1\temp2\temp3 i.e. */
|
||||
if (option == COAP_OPTION_URI_QUERY || option == COAP_OPTION_LOCATION_QUERY || option == COAP_OPTION_ETAG || option == COAP_OPTION_ACCEPT) {
|
||||
memset(temp_parsed_uri_query_ptr, '&', 1);
|
||||
*temp_parsed_uri_query_ptr = '&';
|
||||
} else if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
|
||||
memset(temp_parsed_uri_query_ptr, '/', 1);
|
||||
*temp_parsed_uri_query_ptr = '/';
|
||||
}
|
||||
|
||||
temp_parsed_uri_query_ptr++;
|
||||
|
@ -680,7 +693,7 @@ static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handl
|
|||
*
|
||||
* \param uint16_t option_number_len length of the first option part
|
||||
*/
|
||||
static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len)
|
||||
static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(const uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len)
|
||||
{
|
||||
uint16_t ret_value = 0;
|
||||
uint16_t i = 1;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -738,6 +738,15 @@ void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size,
|
|||
break;
|
||||
|
||||
default:
|
||||
// This can happen e.g. if we happen to receive uplink of another device
|
||||
// during the receive window. Block RX2 window since it can overlap with
|
||||
// QOS TX and cause a mess.
|
||||
tr_debug("RX unexpected mtype %u", mac_hdr.bits.mtype);
|
||||
if (get_current_slot() == RX_SLOT_WIN_1) {
|
||||
_lora_time.stop(_params.timers.rx_window2_timer);
|
||||
}
|
||||
_mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL;
|
||||
_mcps_indication.pending = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,12 @@
|
|||
# else
|
||||
# define ETHMEM_SECTION __attribute__((section("AHBSRAM0"),aligned))
|
||||
# endif
|
||||
#elif defined(TARGET_STM32H7)
|
||||
# if defined (__ICCARM__)
|
||||
# define ETHMEM_SECTION
|
||||
# else
|
||||
# define ETHMEM_SECTION __attribute__((section(".ethusbram")))
|
||||
# endif
|
||||
#else
|
||||
#define ETHMEM_SECTION
|
||||
#endif
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#define NUMBER_OF_SIMULTANEOUS_TIMEOUTS 2
|
||||
#endif //NUMBER_OF_SIMULTANEOUS_TIMEOUTS
|
||||
|
||||
namespace {
|
||||
using namespace mbed;
|
||||
using namespace events;
|
||||
|
||||
|
@ -71,7 +72,6 @@ static fhss_timeout_s *allocate_timeout(void)
|
|||
{
|
||||
for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) {
|
||||
if (fhss_timeout[i].fhss_timer_callback == NULL) {
|
||||
memset(&fhss_timeout[i], 0, sizeof(fhss_timeout_s));
|
||||
return &fhss_timeout[i];
|
||||
}
|
||||
}
|
||||
|
@ -163,6 +163,7 @@ static uint32_t platform_fhss_timestamp_read(const fhss_api_t *api)
|
|||
(void)api;
|
||||
return read_current_time();
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
fhss_timer_t fhss_functions = {
|
||||
.fhss_timer_start = platform_fhss_timer_start,
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed_power_mgmt.h"
|
||||
#include "common_functions.h"
|
||||
#include "platform/arm_hal_interrupt.h"
|
||||
#include "platform/arm_hal_phy.h"
|
||||
|
@ -87,8 +88,9 @@ static uint8_t MAC64_addr[8];
|
|||
|
||||
static xcvrState_t mPhySeqState;
|
||||
static uint8_t rf_mac_handle;
|
||||
volatile uint8_t rf_ed_value = 0;
|
||||
static bool rf_ack_pending_state = false;
|
||||
static volatile uint8_t rf_ed_value = 0;
|
||||
static volatile bool rf_ack_pending_state = false;
|
||||
static volatile bool sleep_blocked = false;
|
||||
|
||||
static NanostackRfPhyKw41z *rf = NULL;
|
||||
|
||||
|
@ -155,6 +157,11 @@ static int8_t rf_device_register(void)
|
|||
static void rf_device_unregister(void)
|
||||
{
|
||||
arm_net_phy_unregister(rf_radio_driver_id);
|
||||
|
||||
if (sleep_blocked) {
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
sleep_blocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -209,16 +216,29 @@ static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_
|
|||
/*Reset PHY driver and set to idle*/
|
||||
case PHY_INTERFACE_RESET:
|
||||
rf_abort();
|
||||
if (sleep_blocked) {
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
sleep_blocked = false;
|
||||
}
|
||||
break;
|
||||
/*Disable PHY Interface driver*/
|
||||
case PHY_INTERFACE_DOWN:
|
||||
rf_abort();
|
||||
if (sleep_blocked) {
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
sleep_blocked = false;
|
||||
}
|
||||
break;
|
||||
/*Enable PHY Interface driver*/
|
||||
case PHY_INTERFACE_UP:
|
||||
if (PhyPlmeSetCurrentChannelRequest(rf_channel, 0)) {
|
||||
return 1;
|
||||
}
|
||||
if (!sleep_blocked) {
|
||||
/* Disable enter to deep sleep when transfer active */
|
||||
sleep_manager_lock_deep_sleep();
|
||||
sleep_blocked = true;
|
||||
}
|
||||
rf_receive();
|
||||
break;
|
||||
/*Enable wireless interface ED scan mode*/
|
||||
|
@ -226,6 +246,11 @@ static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_
|
|||
if (PhyPlmeSetCurrentChannelRequest(rf_channel, 0)) {
|
||||
return 1;
|
||||
}
|
||||
if (!sleep_blocked) {
|
||||
/* Disable enter to deep sleep when transfer active */
|
||||
sleep_manager_lock_deep_sleep();
|
||||
sleep_blocked = true;
|
||||
}
|
||||
rf_abort();
|
||||
rf_mac_ed_state_enable();
|
||||
break;
|
||||
|
@ -234,6 +259,11 @@ static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_
|
|||
if (PhyPlmeSetCurrentChannelRequest(rf_channel, 0)) {
|
||||
return 1;
|
||||
}
|
||||
if (!sleep_blocked) {
|
||||
/* Disable enter to deep sleep when transfer active */
|
||||
sleep_manager_lock_deep_sleep();
|
||||
sleep_blocked = true;
|
||||
}
|
||||
rf_receive();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -398,6 +398,9 @@ nsapi_size_or_error_t TLSSocketWrapper::recv(void *data, nsapi_size_t size)
|
|||
|
||||
nsapi_size_or_error_t TLSSocketWrapper::recvfrom(SocketAddress *address, void *data, nsapi_size_t size)
|
||||
{
|
||||
if (address) {
|
||||
getpeername(address);
|
||||
}
|
||||
return recv(data, size);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
#include "kinetis_emac_config.h"
|
||||
#include "kinetis_emac.h"
|
||||
#include "mbed_power_mgmt.h"
|
||||
|
||||
enet_handle_t g_handle;
|
||||
// TX Buffer descriptors
|
||||
|
@ -496,6 +497,9 @@ bool Kinetis_EMAC::power_up()
|
|||
return false;
|
||||
}
|
||||
|
||||
// Can't enter deep sleep as long as Ethernet is active
|
||||
sleep_manager_lock_deep_sleep();
|
||||
|
||||
/* Worker thread */
|
||||
thread = create_new_thread("Kinetis_EMAC_thread", &Kinetis_EMAC::thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb);
|
||||
|
||||
|
@ -580,7 +584,8 @@ void Kinetis_EMAC::set_all_multicast(bool all)
|
|||
|
||||
void Kinetis_EMAC::power_down()
|
||||
{
|
||||
/* No-op at this stage */
|
||||
// Ethernet went down, can enter deep sleep
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
}
|
||||
|
||||
void Kinetis_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr)
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
#include "imx_emac_config.h"
|
||||
#include "imx_emac.h"
|
||||
#include "mbed_power_mgmt.h"
|
||||
|
||||
enet_handle_t g_handle;
|
||||
// RX packet buffer pointers
|
||||
|
@ -500,6 +501,9 @@ bool Kinetis_EMAC::power_up()
|
|||
return false;
|
||||
}
|
||||
|
||||
// Can't enter deep sleep as long as Ethernet is active
|
||||
sleep_manager_lock_deep_sleep();
|
||||
|
||||
/* Worker thread */
|
||||
thread = create_new_thread("Kinetis_EMAC_thread", &Kinetis_EMAC::thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb);
|
||||
|
||||
|
@ -584,7 +588,8 @@ void Kinetis_EMAC::set_all_multicast(bool all)
|
|||
|
||||
void Kinetis_EMAC::power_down()
|
||||
{
|
||||
/* No-op at this stage */
|
||||
// Ethernet went down, can enter deep sleep
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
}
|
||||
|
||||
void Kinetis_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr)
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#ifndef STM32XX_EMAC_CONFIG_H__
|
||||
#define STM32XX_EMAC_CONFIG_H__
|
||||
|
||||
#define ETH_IP_VERSION_V1
|
||||
|
||||
#define THREAD_STACKSIZE 512
|
||||
|
||||
#endif // #define STM32XX_EMAC_CONFIG_H__
|
|
@ -0,0 +1,24 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef STM32XX_EMAC_CONFIG_H__
|
||||
#define STM32XX_EMAC_CONFIG_H__
|
||||
|
||||
#define ETH_IP_VERSION_V1
|
||||
|
||||
#define THREAD_STACKSIZE 512
|
||||
|
||||
#endif // #define STM32XX_EMAC_CONFIG_H__
|
|
@ -0,0 +1,24 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef STM32XX_EMAC_CONFIG_H__
|
||||
#define STM32XX_EMAC_CONFIG_H__
|
||||
|
||||
#define ETH_IP_VERSION_V1
|
||||
|
||||
#define THREAD_STACKSIZE 512
|
||||
|
||||
#endif // #define STM32XX_EMAC_CONFIG_H__
|
|
@ -0,0 +1,681 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file lan8742.c
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 08-March-2017
|
||||
* @brief This file provides a set of functions needed to manage the LAN742
|
||||
* PHY devices.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "lan8742.h"
|
||||
|
||||
/** @addtogroup BSP
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup Component
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742 LAN8742
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup LAN8742_Private_Defines LAN8742 Private Defines
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_SW_RESET_TO ((uint32_t)500U)
|
||||
#define LAN8742_INIT_TO ((uint32_t)2000U)
|
||||
#define LAN8742_MAX_DEV_ADDR ((uint32_t)31U)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @defgroup LAN8742_Private_Functions LAN8742 Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Register IO functions to component object
|
||||
* @param pObj: device object of LAN8742_Object_t.
|
||||
* @param ioctx: holds device IO functions.
|
||||
* @retval LAN8742_STATUS_OK if OK
|
||||
* LAN8742_STATUS_ERROR if missing mandatory function
|
||||
*/
|
||||
int32_t LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx)
|
||||
{
|
||||
if(!pObj || !ioctx->ReadReg || !ioctx->WriteReg || !ioctx->GetTick)
|
||||
{
|
||||
return LAN8742_STATUS_ERROR;
|
||||
}
|
||||
|
||||
pObj->IO.Init = ioctx->Init;
|
||||
pObj->IO.DeInit = ioctx->DeInit;
|
||||
pObj->IO.ReadReg = ioctx->ReadReg;
|
||||
pObj->IO.WriteReg = ioctx->WriteReg;
|
||||
pObj->IO.GetTick = ioctx->GetTick;
|
||||
|
||||
return LAN8742_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the lan8742 and configure the needed hardware resources
|
||||
* @param pObj: device object LAN8742_Object_t.
|
||||
* @retval LAN8742_STATUS_OK if OK
|
||||
* LAN8742_STATUS_ADDRESS_ERROR if cannot find device address
|
||||
* LAN8742_STATUS_READ_ERROR if connot read register
|
||||
* LAN8742_STATUS_WRITE_ERROR if connot write to register
|
||||
* LAN8742_STATUS_RESET_TIMEOUT if cannot perform a software reset
|
||||
*/
|
||||
int32_t LAN8742_Init(lan8742_Object_t *pObj)
|
||||
{
|
||||
uint32_t tickstart = 0, regvalue = 0, addr = 0;
|
||||
int32_t status = LAN8742_STATUS_OK;
|
||||
|
||||
if(pObj->Is_Initialized == 0)
|
||||
{
|
||||
if(pObj->IO.Init != 0)
|
||||
{
|
||||
/* GPIO and Clocks initialization */
|
||||
pObj->IO.Init();
|
||||
}
|
||||
|
||||
/* for later check */
|
||||
pObj->DevAddr = LAN8742_MAX_DEV_ADDR + 1;
|
||||
|
||||
/* Get the device address from special mode register */
|
||||
for(addr = 0; addr <= LAN8742_MAX_DEV_ADDR; addr ++)
|
||||
{
|
||||
if(pObj->IO.ReadReg(addr, LAN8742_SMR, ®value) < 0)
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
/* Can't read from this device address
|
||||
continue with next address */
|
||||
continue;
|
||||
}
|
||||
|
||||
if((regvalue & LAN8742_SMR_PHY_ADDR) == addr)
|
||||
{
|
||||
pObj->DevAddr = addr;
|
||||
status = LAN8742_STATUS_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(pObj->DevAddr > LAN8742_MAX_DEV_ADDR)
|
||||
{
|
||||
status = LAN8742_STATUS_ADDRESS_ERROR;
|
||||
}
|
||||
|
||||
/* if device address is matched */
|
||||
if(status == LAN8742_STATUS_OK)
|
||||
{
|
||||
/* set a software reset */
|
||||
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, LAN8742_BCR_SOFT_RESET) >= 0)
|
||||
{
|
||||
/* get software reset status */
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, ®value) >= 0)
|
||||
{
|
||||
tickstart = pObj->IO.GetTick();
|
||||
|
||||
/* wait until software reset is done or timeout occured */
|
||||
while(regvalue & LAN8742_BCR_SOFT_RESET)
|
||||
{
|
||||
if((pObj->IO.GetTick() - tickstart) <= LAN8742_SW_RESET_TO)
|
||||
{
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, ®value) < 0)
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = LAN8742_STATUS_RESET_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = LAN8742_STATUS_WRITE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(status == LAN8742_STATUS_OK)
|
||||
{
|
||||
tickstart = pObj->IO.GetTick();
|
||||
|
||||
/* Wait for 2s to perform initialization */
|
||||
while((pObj->IO.GetTick() - tickstart) <= LAN8742_INIT_TO)
|
||||
{
|
||||
}
|
||||
pObj->Is_Initialized = 1;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initialize the lan8742 and it's hardware resources
|
||||
* @param pObj: device object LAN8742_Object_t.
|
||||
* @retval None
|
||||
*/
|
||||
int32_t LAN8742_DeInit(lan8742_Object_t *pObj)
|
||||
{
|
||||
if(pObj->Is_Initialized)
|
||||
{
|
||||
if(pObj->IO.DeInit != 0)
|
||||
{
|
||||
if(pObj->IO.DeInit() < 0)
|
||||
{
|
||||
return LAN8742_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
pObj->Is_Initialized = 0;
|
||||
}
|
||||
|
||||
return LAN8742_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the LAN8742 power down mode.
|
||||
* @param pObj: device object LAN8742_Object_t.
|
||||
* @retval LAN8742_STATUS_OK if OK
|
||||
* LAN8742_STATUS_READ_ERROR if connot read register
|
||||
* LAN8742_STATUS_WRITE_ERROR if connot write to register
|
||||
*/
|
||||
int32_t LAN8742_DisablePowerDownMode(lan8742_Object_t *pObj)
|
||||
{
|
||||
uint32_t readval = 0;
|
||||
int32_t status = LAN8742_STATUS_OK;
|
||||
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
|
||||
{
|
||||
readval &= ~LAN8742_BCR_POWER_DOWN;
|
||||
|
||||
/* Apply configuration */
|
||||
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
|
||||
{
|
||||
status = LAN8742_STATUS_WRITE_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the LAN8742 power down mode.
|
||||
* @param pObj: device object LAN8742_Object_t.
|
||||
* @retval LAN8742_STATUS_OK if OK
|
||||
* LAN8742_STATUS_READ_ERROR if connot read register
|
||||
* LAN8742_STATUS_WRITE_ERROR if connot write to register
|
||||
*/
|
||||
int32_t LAN8742_EnablePowerDownMode(lan8742_Object_t *pObj)
|
||||
{
|
||||
uint32_t readval = 0;
|
||||
int32_t status = LAN8742_STATUS_OK;
|
||||
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
|
||||
{
|
||||
readval |= LAN8742_BCR_POWER_DOWN;
|
||||
|
||||
/* Apply configuration */
|
||||
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
|
||||
{
|
||||
status = LAN8742_STATUS_WRITE_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start the auto negotiation process.
|
||||
* @param pObj: device object LAN8742_Object_t.
|
||||
* @retval LAN8742_STATUS_OK if OK
|
||||
* LAN8742_STATUS_READ_ERROR if connot read register
|
||||
* LAN8742_STATUS_WRITE_ERROR if connot write to register
|
||||
*/
|
||||
int32_t LAN8742_StartAutoNego(lan8742_Object_t *pObj)
|
||||
{
|
||||
uint32_t readval = 0;
|
||||
int32_t status = LAN8742_STATUS_OK;
|
||||
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
|
||||
{
|
||||
readval |= LAN8742_BCR_AUTONEGO_EN;
|
||||
|
||||
/* Apply configuration */
|
||||
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
|
||||
{
|
||||
status = LAN8742_STATUS_WRITE_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the link state of LAN8742 device.
|
||||
* @param pObj: Pointer to device object.
|
||||
* @param pLinkState: Pointer to link state
|
||||
* @retval LAN8742_STATUS_LINK_DOWN if link is down
|
||||
* LAN8742_STATUS_AUTONEGO_NOTDONE if Auto nego not completed
|
||||
* LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD
|
||||
* LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD
|
||||
* LAN8742_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD
|
||||
* LAN8742_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD
|
||||
* LAN8742_STATUS_READ_ERROR if connot read register
|
||||
* LAN8742_STATUS_WRITE_ERROR if connot write to register
|
||||
*/
|
||||
int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj)
|
||||
{
|
||||
uint32_t readval = 0;
|
||||
|
||||
/* Read Status register */
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0)
|
||||
{
|
||||
return LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
/* Read Status register again */
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0)
|
||||
{
|
||||
return LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
if((readval & LAN8742_BSR_LINK_STATUS) == 0)
|
||||
{
|
||||
/* Return Link Down status */
|
||||
return LAN8742_STATUS_LINK_DOWN;
|
||||
}
|
||||
|
||||
/* Check Auto negotiaition */
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) < 0)
|
||||
{
|
||||
return LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
if((readval & LAN8742_BCR_AUTONEGO_EN) != LAN8742_BCR_AUTONEGO_EN)
|
||||
{
|
||||
if(((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT) && ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE))
|
||||
{
|
||||
return LAN8742_STATUS_100MBITS_FULLDUPLEX;
|
||||
}
|
||||
else if ((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT)
|
||||
{
|
||||
return LAN8742_STATUS_100MBITS_HALFDUPLEX;
|
||||
}
|
||||
else if ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE)
|
||||
{
|
||||
return LAN8742_STATUS_10MBITS_FULLDUPLEX;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LAN8742_STATUS_10MBITS_HALFDUPLEX;
|
||||
}
|
||||
}
|
||||
else /* Auto Nego enabled */
|
||||
{
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_PHYSCSR, &readval) < 0)
|
||||
{
|
||||
return LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
/* Check if auto nego not done */
|
||||
if((readval & LAN8742_PHYSCSR_AUTONEGO_DONE) == 0)
|
||||
{
|
||||
return LAN8742_STATUS_AUTONEGO_NOTDONE;
|
||||
}
|
||||
|
||||
if((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_FD)
|
||||
{
|
||||
return LAN8742_STATUS_100MBITS_FULLDUPLEX;
|
||||
}
|
||||
else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_HD)
|
||||
{
|
||||
return LAN8742_STATUS_100MBITS_HALFDUPLEX;
|
||||
}
|
||||
else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_10BT_FD)
|
||||
{
|
||||
return LAN8742_STATUS_10MBITS_FULLDUPLEX;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LAN8742_STATUS_10MBITS_HALFDUPLEX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the link state of LAN8742 device.
|
||||
* @param pObj: Pointer to device object.
|
||||
* @param pLinkState: link state can be one of the following
|
||||
* LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD
|
||||
* LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD
|
||||
* LAN8742_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD
|
||||
* LAN8742_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD
|
||||
* @retval LAN8742_STATUS_OK if OK
|
||||
* LAN8742_STATUS_ERROR if parameter error
|
||||
* LAN8742_STATUS_READ_ERROR if connot read register
|
||||
* LAN8742_STATUS_WRITE_ERROR if connot write to register
|
||||
*/
|
||||
int32_t LAN8742_SetLinkState(lan8742_Object_t *pObj, uint32_t LinkState)
|
||||
{
|
||||
uint32_t bcrvalue = 0;
|
||||
int32_t status = LAN8742_STATUS_OK;
|
||||
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &bcrvalue) >= 0)
|
||||
{
|
||||
/* Disable link config (Auto nego, speed and duplex) */
|
||||
bcrvalue &= ~(LAN8742_BCR_AUTONEGO_EN | LAN8742_BCR_SPEED_SELECT | LAN8742_BCR_DUPLEX_MODE);
|
||||
|
||||
if(LinkState == LAN8742_STATUS_100MBITS_FULLDUPLEX)
|
||||
{
|
||||
bcrvalue |= (LAN8742_BCR_SPEED_SELECT | LAN8742_BCR_DUPLEX_MODE);
|
||||
}
|
||||
else if (LinkState == LAN8742_STATUS_100MBITS_HALFDUPLEX)
|
||||
{
|
||||
bcrvalue |= LAN8742_BCR_SPEED_SELECT;
|
||||
}
|
||||
else if (LinkState == LAN8742_STATUS_10MBITS_FULLDUPLEX)
|
||||
{
|
||||
bcrvalue |= LAN8742_BCR_DUPLEX_MODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wrong link status parameter */
|
||||
status = LAN8742_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
if(status == LAN8742_STATUS_OK)
|
||||
{
|
||||
/* Apply configuration */
|
||||
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, bcrvalue) < 0)
|
||||
{
|
||||
status = LAN8742_STATUS_WRITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable loopback mode.
|
||||
* @param pObj: Pointer to device object.
|
||||
* @retval LAN8742_STATUS_OK if OK
|
||||
* LAN8742_STATUS_READ_ERROR if connot read register
|
||||
* LAN8742_STATUS_WRITE_ERROR if connot write to register
|
||||
*/
|
||||
int32_t LAN8742_EnableLoopbackMode(lan8742_Object_t *pObj)
|
||||
{
|
||||
uint32_t readval = 0;
|
||||
int32_t status = LAN8742_STATUS_OK;
|
||||
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
|
||||
{
|
||||
readval |= LAN8742_BCR_LOOPBACK;
|
||||
|
||||
/* Apply configuration */
|
||||
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
|
||||
{
|
||||
status = LAN8742_STATUS_WRITE_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable loopback mode.
|
||||
* @param pObj: Pointer to device object.
|
||||
* @retval LAN8742_STATUS_OK if OK
|
||||
* LAN8742_STATUS_READ_ERROR if connot read register
|
||||
* LAN8742_STATUS_WRITE_ERROR if connot write to register
|
||||
*/
|
||||
int32_t LAN8742_DisableLoopbackMode(lan8742_Object_t *pObj)
|
||||
{
|
||||
uint32_t readval = 0;
|
||||
int32_t status = LAN8742_STATUS_OK;
|
||||
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
|
||||
{
|
||||
readval &= ~LAN8742_BCR_LOOPBACK;
|
||||
|
||||
/* Apply configuration */
|
||||
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
|
||||
{
|
||||
status = LAN8742_STATUS_WRITE_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable IT source.
|
||||
* @param pObj: Pointer to device object.
|
||||
* @param Interrupt: IT source to be enabled
|
||||
* should be a value or a combination of the following:
|
||||
* LAN8742_WOL_IT
|
||||
* LAN8742_ENERGYON_IT
|
||||
* LAN8742_AUTONEGO_COMPLETE_IT
|
||||
* LAN8742_REMOTE_FAULT_IT
|
||||
* LAN8742_LINK_DOWN_IT
|
||||
* LAN8742_AUTONEGO_LP_ACK_IT
|
||||
* LAN8742_PARALLEL_DETECTION_FAULT_IT
|
||||
* LAN8742_AUTONEGO_PAGE_RECEIVED_IT
|
||||
* @retval LAN8742_STATUS_OK if OK
|
||||
* LAN8742_STATUS_READ_ERROR if connot read register
|
||||
* LAN8742_STATUS_WRITE_ERROR if connot write to register
|
||||
*/
|
||||
int32_t LAN8742_EnableIT(lan8742_Object_t *pObj, uint32_t Interrupt)
|
||||
{
|
||||
uint32_t readval = 0;
|
||||
int32_t status = LAN8742_STATUS_OK;
|
||||
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_IMR, &readval) >= 0)
|
||||
{
|
||||
readval |= Interrupt;
|
||||
|
||||
/* Apply configuration */
|
||||
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_IMR, readval) < 0)
|
||||
{
|
||||
status = LAN8742_STATUS_WRITE_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable IT source.
|
||||
* @param pObj: Pointer to device object.
|
||||
* @param Interrupt: IT source to be disabled
|
||||
* should be a value or a combination of the following:
|
||||
* LAN8742_WOL_IT
|
||||
* LAN8742_ENERGYON_IT
|
||||
* LAN8742_AUTONEGO_COMPLETE_IT
|
||||
* LAN8742_REMOTE_FAULT_IT
|
||||
* LAN8742_LINK_DOWN_IT
|
||||
* LAN8742_AUTONEGO_LP_ACK_IT
|
||||
* LAN8742_PARALLEL_DETECTION_FAULT_IT
|
||||
* LAN8742_AUTONEGO_PAGE_RECEIVED_IT
|
||||
* @retval LAN8742_STATUS_OK if OK
|
||||
* LAN8742_STATUS_READ_ERROR if connot read register
|
||||
* LAN8742_STATUS_WRITE_ERROR if connot write to register
|
||||
*/
|
||||
int32_t LAN8742_DisableIT(lan8742_Object_t *pObj, uint32_t Interrupt)
|
||||
{
|
||||
uint32_t readval = 0;
|
||||
int32_t status = LAN8742_STATUS_OK;
|
||||
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_IMR, &readval) >= 0)
|
||||
{
|
||||
readval &= ~Interrupt;
|
||||
|
||||
/* Apply configuration */
|
||||
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_IMR, readval) < 0)
|
||||
{
|
||||
status = LAN8742_STATUS_WRITE_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear IT flag.
|
||||
* @param pObj: Pointer to device object.
|
||||
* @param Interrupt: IT flag to be cleared
|
||||
* should be a value or a combination of the following:
|
||||
* LAN8742_WOL_IT
|
||||
* LAN8742_ENERGYON_IT
|
||||
* LAN8742_AUTONEGO_COMPLETE_IT
|
||||
* LAN8742_REMOTE_FAULT_IT
|
||||
* LAN8742_LINK_DOWN_IT
|
||||
* LAN8742_AUTONEGO_LP_ACK_IT
|
||||
* LAN8742_PARALLEL_DETECTION_FAULT_IT
|
||||
* LAN8742_AUTONEGO_PAGE_RECEIVED_IT
|
||||
* @retval LAN8742_STATUS_OK if OK
|
||||
* LAN8742_STATUS_READ_ERROR if connot read register
|
||||
*/
|
||||
int32_t LAN8742_ClearIT(lan8742_Object_t *pObj, uint32_t Interrupt)
|
||||
{
|
||||
uint32_t readval = 0;
|
||||
int32_t status = LAN8742_STATUS_OK;
|
||||
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_ISFR, &readval) < 0)
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get IT Flag status.
|
||||
* @param pObj: Pointer to device object.
|
||||
* @param Interrupt: IT Flag to be checked,
|
||||
* should be a value or a combination of the following:
|
||||
* LAN8742_WOL_IT
|
||||
* LAN8742_ENERGYON_IT
|
||||
* LAN8742_AUTONEGO_COMPLETE_IT
|
||||
* LAN8742_REMOTE_FAULT_IT
|
||||
* LAN8742_LINK_DOWN_IT
|
||||
* LAN8742_AUTONEGO_LP_ACK_IT
|
||||
* LAN8742_PARALLEL_DETECTION_FAULT_IT
|
||||
* LAN8742_AUTONEGO_PAGE_RECEIVED_IT
|
||||
* @retval 1 IT flag is SET
|
||||
* 0 IT flag is RESET
|
||||
* LAN8742_STATUS_READ_ERROR if connot read register
|
||||
*/
|
||||
int32_t LAN8742_GetITStatus(lan8742_Object_t *pObj, uint32_t Interrupt)
|
||||
{
|
||||
uint32_t readval = 0;
|
||||
int32_t status = 0;
|
||||
|
||||
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_ISFR, &readval) >= 0)
|
||||
{
|
||||
status = ((readval & Interrupt) == Interrupt);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = LAN8742_STATUS_READ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,466 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file lan8742.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.0
|
||||
* @date 08-March-2017
|
||||
* @brief This file contains all the functions prototypes for the
|
||||
* lan8742.c PHY driver.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __LAN8742_H
|
||||
#define __LAN8742_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
|
||||
/** @addtogroup BSP
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup Component
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742
|
||||
* @{
|
||||
*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @defgroup LAN8742_Exported_Constants LAN8742 Exported Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_Registers_Mapping LAN8742 Registers Mapping
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_BCR ((uint16_t)0x0000U)
|
||||
#define LAN8742_BSR ((uint16_t)0x0001U)
|
||||
#define LAN8742_PHYI1R ((uint16_t)0x0002U)
|
||||
#define LAN8742_PHYI2R ((uint16_t)0x0003U)
|
||||
#define LAN8742_ANAR ((uint16_t)0x0004U)
|
||||
#define LAN8742_ANLPAR ((uint16_t)0x0005U)
|
||||
#define LAN8742_ANER ((uint16_t)0x0006U)
|
||||
#define LAN8742_ANNPTR ((uint16_t)0x0007U)
|
||||
#define LAN8742_ANNPRR ((uint16_t)0x0008U)
|
||||
#define LAN8742_MMDACR ((uint16_t)0x000DU)
|
||||
#define LAN8742_MMDAADR ((uint16_t)0x000EU)
|
||||
#define LAN8742_ENCTR ((uint16_t)0x0010U)
|
||||
#define LAN8742_MCSR ((uint16_t)0x0011U)
|
||||
#define LAN8742_SMR ((uint16_t)0x0012U)
|
||||
#define LAN8742_TPDCR ((uint16_t)0x0018U)
|
||||
#define LAN8742_TCSR ((uint16_t)0x0019U)
|
||||
#define LAN8742_SECR ((uint16_t)0x001AU)
|
||||
#define LAN8742_SCSIR ((uint16_t)0x001BU)
|
||||
#define LAN8742_CLR ((uint16_t)0x001CU)
|
||||
#define LAN8742_ISFR ((uint16_t)0x001DU)
|
||||
#define LAN8742_IMR ((uint16_t)0x001EU)
|
||||
#define LAN8742_PHYSCSR ((uint16_t)0x001FU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_BCR_Bit_Definition LAN8742 BCR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_BCR_SOFT_RESET ((uint16_t)0x8000U)
|
||||
#define LAN8742_BCR_LOOPBACK ((uint16_t)0x4000U)
|
||||
#define LAN8742_BCR_SPEED_SELECT ((uint16_t)0x2000U)
|
||||
#define LAN8742_BCR_AUTONEGO_EN ((uint16_t)0x1000U)
|
||||
#define LAN8742_BCR_POWER_DOWN ((uint16_t)0x0800U)
|
||||
#define LAN8742_BCR_ISOLATE ((uint16_t)0x0400U)
|
||||
#define LAN8742_BCR_RESTART_AUTONEGO ((uint16_t)0x0200U)
|
||||
#define LAN8742_BCR_DUPLEX_MODE ((uint16_t)0x0100U)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_BSR_Bit_Definition LAN8742 BSR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_BSR_100BASE_T4 ((uint16_t)0x8000U)
|
||||
#define LAN8742_BSR_100BASE_TX_FD ((uint16_t)0x4000U)
|
||||
#define LAN8742_BSR_100BASE_TX_HD ((uint16_t)0x2000U)
|
||||
#define LAN8742_BSR_10BASE_T_FD ((uint16_t)0x1000U)
|
||||
#define LAN8742_BSR_10BASE_T_HD ((uint16_t)0x0800U)
|
||||
#define LAN8742_BSR_100BASE_T2_FD ((uint16_t)0x0400U)
|
||||
#define LAN8742_BSR_100BASE_T2_HD ((uint16_t)0x0200U)
|
||||
#define LAN8742_BSR_EXTENDED_STATUS ((uint16_t)0x0100U)
|
||||
#define LAN8742_BSR_AUTONEGO_CPLT ((uint16_t)0x0020U)
|
||||
#define LAN8742_BSR_REMOTE_FAULT ((uint16_t)0x0010U)
|
||||
#define LAN8742_BSR_AUTONEGO_ABILITY ((uint16_t)0x0008U)
|
||||
#define LAN8742_BSR_LINK_STATUS ((uint16_t)0x0004U)
|
||||
#define LAN8742_BSR_JABBER_DETECT ((uint16_t)0x0002U)
|
||||
#define LAN8742_BSR_EXTENDED_CAP ((uint16_t)0x0001U)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_PHYI1R_Bit_Definition LAN8742 PHYI1R Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_PHYI1R_OUI_3_18 ((uint16_t)0xFFFFU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_PHYI2R_Bit_Definition LAN8742 PHYI2R Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_PHYI2R_OUI_19_24 ((uint16_t)0xFC00U)
|
||||
#define LAN8742_PHYI2R_MODEL_NBR ((uint16_t)0x03F0U)
|
||||
#define LAN8742_PHYI2R_REVISION_NBR ((uint16_t)0x000FU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_ANAR_Bit_Definition LAN8742 ANAR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_ANAR_NEXT_PAGE ((uint16_t)0x8000U)
|
||||
#define LAN8742_ANAR_REMOTE_FAULT ((uint16_t)0x2000U)
|
||||
#define LAN8742_ANAR_PAUSE_OPERATION ((uint16_t)0x0C00U)
|
||||
#define LAN8742_ANAR_PO_NOPAUSE ((uint16_t)0x0000U)
|
||||
#define LAN8742_ANAR_PO_SYMMETRIC_PAUSE ((uint16_t)0x0400U)
|
||||
#define LAN8742_ANAR_PO_ASYMMETRIC_PAUSE ((uint16_t)0x0800U)
|
||||
#define LAN8742_ANAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U)
|
||||
#define LAN8742_ANAR_100BASE_TX_FD ((uint16_t)0x0100U)
|
||||
#define LAN8742_ANAR_100BASE_TX ((uint16_t)0x0080U)
|
||||
#define LAN8742_ANAR_10BASE_T_FD ((uint16_t)0x0040U)
|
||||
#define LAN8742_ANAR_10BASE_T ((uint16_t)0x0020U)
|
||||
#define LAN8742_ANAR_SELECTOR_FIELD ((uint16_t)0x000FU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_ANLPAR_Bit_Definition LAN8742 ANLPAR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_ANLPAR_NEXT_PAGE ((uint16_t)0x8000U)
|
||||
#define LAN8742_ANLPAR_REMOTE_FAULT ((uint16_t)0x2000U)
|
||||
#define LAN8742_ANLPAR_PAUSE_OPERATION ((uint16_t)0x0C00U)
|
||||
#define LAN8742_ANLPAR_PO_NOPAUSE ((uint16_t)0x0000U)
|
||||
#define LAN8742_ANLPAR_PO_SYMMETRIC_PAUSE ((uint16_t)0x0400U)
|
||||
#define LAN8742_ANLPAR_PO_ASYMMETRIC_PAUSE ((uint16_t)0x0800U)
|
||||
#define LAN8742_ANLPAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U)
|
||||
#define LAN8742_ANLPAR_100BASE_TX_FD ((uint16_t)0x0100U)
|
||||
#define LAN8742_ANLPAR_100BASE_TX ((uint16_t)0x0080U)
|
||||
#define LAN8742_ANLPAR_10BASE_T_FD ((uint16_t)0x0040U)
|
||||
#define LAN8742_ANLPAR_10BASE_T ((uint16_t)0x0020U)
|
||||
#define LAN8742_ANLPAR_SELECTOR_FIELD ((uint16_t)0x000FU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_ANER_Bit_Definition LAN8742 ANER Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_ANER_RX_NP_LOCATION_ABLE ((uint16_t)0x0040U)
|
||||
#define LAN8742_ANER_RX_NP_STORAGE_LOCATION ((uint16_t)0x0020U)
|
||||
#define LAN8742_ANER_PARALLEL_DETECT_FAULT ((uint16_t)0x0010U)
|
||||
#define LAN8742_ANER_LP_NP_ABLE ((uint16_t)0x0008U)
|
||||
#define LAN8742_ANER_NP_ABLE ((uint16_t)0x0004U)
|
||||
#define LAN8742_ANER_PAGE_RECEIVED ((uint16_t)0x0002U)
|
||||
#define LAN8742_ANER_LP_AUTONEG_ABLE ((uint16_t)0x0001U)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_ANNPTR_Bit_Definition LAN8742 ANNPTR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_ANNPTR_NEXT_PAGE ((uint16_t)0x8000U)
|
||||
#define LAN8742_ANNPTR_MESSAGE_PAGE ((uint16_t)0x2000U)
|
||||
#define LAN8742_ANNPTR_ACK2 ((uint16_t)0x1000U)
|
||||
#define LAN8742_ANNPTR_TOGGLE ((uint16_t)0x0800U)
|
||||
#define LAN8742_ANNPTR_MESSAGGE_CODE ((uint16_t)0x07FFU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_ANNPRR_Bit_Definition LAN8742 ANNPRR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_ANNPTR_NEXT_PAGE ((uint16_t)0x8000U)
|
||||
#define LAN8742_ANNPRR_ACK ((uint16_t)0x4000U)
|
||||
#define LAN8742_ANNPRR_MESSAGE_PAGE ((uint16_t)0x2000U)
|
||||
#define LAN8742_ANNPRR_ACK2 ((uint16_t)0x1000U)
|
||||
#define LAN8742_ANNPRR_TOGGLE ((uint16_t)0x0800U)
|
||||
#define LAN8742_ANNPRR_MESSAGGE_CODE ((uint16_t)0x07FFU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_MMDACR_Bit_Definition LAN8742 MMDACR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_MMDACR_MMD_FUNCTION ((uint16_t)0xC000U)
|
||||
#define LAN8742_MMDACR_MMD_FUNCTION_ADDR ((uint16_t)0x0000U)
|
||||
#define LAN8742_MMDACR_MMD_FUNCTION_DATA ((uint16_t)0x4000U)
|
||||
#define LAN8742_MMDACR_MMD_DEV_ADDR ((uint16_t)0x001FU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_ENCTR_Bit_Definition LAN8742 ENCTR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_ENCTR_TX_ENABLE ((uint16_t)0x8000U)
|
||||
#define LAN8742_ENCTR_TX_TIMER ((uint16_t)0x6000U)
|
||||
#define LAN8742_ENCTR_TX_TIMER_1S ((uint16_t)0x0000U)
|
||||
#define LAN8742_ENCTR_TX_TIMER_768MS ((uint16_t)0x2000U)
|
||||
#define LAN8742_ENCTR_TX_TIMER_512MS ((uint16_t)0x4000U)
|
||||
#define LAN8742_ENCTR_TX_TIMER_265MS ((uint16_t)0x6000U)
|
||||
#define LAN8742_ENCTR_RX_ENABLE ((uint16_t)0x1000U)
|
||||
#define LAN8742_ENCTR_RX_MAX_INTERVAL ((uint16_t)0x0C00U)
|
||||
#define LAN8742_ENCTR_RX_MAX_INTERVAL_64MS ((uint16_t)0x0000U)
|
||||
#define LAN8742_ENCTR_RX_MAX_INTERVAL_256MS ((uint16_t)0x0400U)
|
||||
#define LAN8742_ENCTR_RX_MAX_INTERVAL_512MS ((uint16_t)0x0800U)
|
||||
#define LAN8742_ENCTR_RX_MAX_INTERVAL_1S ((uint16_t)0x0C00U)
|
||||
#define LAN8742_ENCTR_EX_CROSS_OVER ((uint16_t)0x0002U)
|
||||
#define LAN8742_ENCTR_EX_MANUAL_CROSS_OVER ((uint16_t)0x0001U)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_MCSR_Bit_Definition LAN8742 MCSR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_MCSR_EDPWRDOWN ((uint16_t)0x2000U)
|
||||
#define LAN8742_MCSR_FARLOOPBACK ((uint16_t)0x0200U)
|
||||
#define LAN8742_MCSR_ALTINT ((uint16_t)0x0040U)
|
||||
#define LAN8742_MCSR_ENERGYON ((uint16_t)0x0002U)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_SMR_Bit_Definition LAN8742 SMR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_SMR_MODE ((uint16_t)0x00E0U)
|
||||
#define LAN8742_SMR_PHY_ADDR ((uint16_t)0x001FU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_TPDCR_Bit_Definition LAN8742 TPDCR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_TPDCR_DELAY_IN ((uint16_t)0x8000U)
|
||||
#define LAN8742_TPDCR_LINE_BREAK_COUNTER ((uint16_t)0x7000U)
|
||||
#define LAN8742_TPDCR_PATTERN_HIGH ((uint16_t)0x0FC0U)
|
||||
#define LAN8742_TPDCR_PATTERN_LOW ((uint16_t)0x003FU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_TCSR_Bit_Definition LAN8742 TCSR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_TCSR_TDR_ENABLE ((uint16_t)0x8000U)
|
||||
#define LAN8742_TCSR_TDR_AD_FILTER_ENABLE ((uint16_t)0x4000U)
|
||||
#define LAN8742_TCSR_TDR_CH_CABLE_TYPE ((uint16_t)0x0600U)
|
||||
#define LAN8742_TCSR_TDR_CH_CABLE_DEFAULT ((uint16_t)0x0000U)
|
||||
#define LAN8742_TCSR_TDR_CH_CABLE_SHORTED ((uint16_t)0x0200U)
|
||||
#define LAN8742_TCSR_TDR_CH_CABLE_OPEN ((uint16_t)0x0400U)
|
||||
#define LAN8742_TCSR_TDR_CH_CABLE_MATCH ((uint16_t)0x0600U)
|
||||
#define LAN8742_TCSR_TDR_CH_STATUS ((uint16_t)0x0100U)
|
||||
#define LAN8742_TCSR_TDR_CH_LENGTH ((uint16_t)0x00FFU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_SCSIR_Bit_Definition LAN8742 SCSIR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_SCSIR_AUTO_MDIX_ENABLE ((uint16_t)0x8000U)
|
||||
#define LAN8742_SCSIR_CHANNEL_SELECT ((uint16_t)0x2000U)
|
||||
#define LAN8742_SCSIR_SQE_DISABLE ((uint16_t)0x0800U)
|
||||
#define LAN8742_SCSIR_XPOLALITY ((uint16_t)0x0010U)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_CLR_Bit_Definition LAN8742 CLR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_CLR_CABLE_LENGTH ((uint16_t)0xF000U)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_IMR_ISFR_Bit_Definition LAN8742 IMR ISFR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_INT_8 ((uint16_t)0x0100U)
|
||||
#define LAN8742_INT_7 ((uint16_t)0x0080U)
|
||||
#define LAN8742_INT_6 ((uint16_t)0x0040U)
|
||||
#define LAN8742_INT_5 ((uint16_t)0x0020U)
|
||||
#define LAN8742_INT_4 ((uint16_t)0x0010U)
|
||||
#define LAN8742_INT_3 ((uint16_t)0x0008U)
|
||||
#define LAN8742_INT_2 ((uint16_t)0x0004U)
|
||||
#define LAN8742_INT_1 ((uint16_t)0x0002U)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_PHYSCSR_Bit_Definition LAN8742 PHYSCSR Bit Definition
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_PHYSCSR_AUTONEGO_DONE ((uint16_t)0x1000U)
|
||||
#define LAN8742_PHYSCSR_HCDSPEEDMASK ((uint16_t)0x001CU)
|
||||
#define LAN8742_PHYSCSR_10BT_HD ((uint16_t)0x0004U)
|
||||
#define LAN8742_PHYSCSR_10BT_FD ((uint16_t)0x0014U)
|
||||
#define LAN8742_PHYSCSR_100BTX_HD ((uint16_t)0x0008U)
|
||||
#define LAN8742_PHYSCSR_100BTX_FD ((uint16_t)0x0018U)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_Status LAN8742 Status
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define LAN8742_STATUS_READ_ERROR ((int32_t)-5)
|
||||
#define LAN8742_STATUS_WRITE_ERROR ((int32_t)-4)
|
||||
#define LAN8742_STATUS_ADDRESS_ERROR ((int32_t)-3)
|
||||
#define LAN8742_STATUS_RESET_TIMEOUT ((int32_t)-2)
|
||||
#define LAN8742_STATUS_ERROR ((int32_t)-1)
|
||||
#define LAN8742_STATUS_OK ((int32_t) 0)
|
||||
#define LAN8742_STATUS_LINK_DOWN ((int32_t) 1)
|
||||
#define LAN8742_STATUS_100MBITS_FULLDUPLEX ((int32_t) 2)
|
||||
#define LAN8742_STATUS_100MBITS_HALFDUPLEX ((int32_t) 3)
|
||||
#define LAN8742_STATUS_10MBITS_FULLDUPLEX ((int32_t) 4)
|
||||
#define LAN8742_STATUS_10MBITS_HALFDUPLEX ((int32_t) 5)
|
||||
#define LAN8742_STATUS_AUTONEGO_NOTDONE ((int32_t) 6)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup LAN8742_IT_Flags LAN8742 IT Flags
|
||||
* @{
|
||||
*/
|
||||
#define LAN8742_WOL_IT LAN8742_INT_8
|
||||
#define LAN8742_ENERGYON_IT LAN8742_INT_7
|
||||
#define LAN8742_AUTONEGO_COMPLETE_IT LAN8742_INT_6
|
||||
#define LAN8742_REMOTE_FAULT_IT LAN8742_INT_5
|
||||
#define LAN8742_LINK_DOWN_IT LAN8742_INT_4
|
||||
#define LAN8742_AUTONEGO_LP_ACK_IT LAN8742_INT_3
|
||||
#define LAN8742_PARALLEL_DETECTION_FAULT_IT LAN8742_INT_2
|
||||
#define LAN8742_AUTONEGO_PAGE_RECEIVED_IT LAN8742_INT_1
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/** @defgroup LAN8742_Exported_Types LAN8742 Exported Types
|
||||
* @{
|
||||
*/
|
||||
typedef int32_t (*lan8742_Init_Func) (void);
|
||||
typedef int32_t (*lan8742_DeInit_Func) (void);
|
||||
typedef int32_t (*lan8742_ReadReg_Func) (uint32_t, uint32_t, uint32_t *);
|
||||
typedef int32_t (*lan8742_WriteReg_Func) (uint32_t, uint32_t, uint32_t);
|
||||
typedef int32_t (*lan8742_GetTick_Func) (void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
lan8742_Init_Func Init;
|
||||
lan8742_DeInit_Func DeInit;
|
||||
lan8742_WriteReg_Func WriteReg;
|
||||
lan8742_ReadReg_Func ReadReg;
|
||||
lan8742_GetTick_Func GetTick;
|
||||
} lan8742_IOCtx_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t DevAddr;
|
||||
uint32_t Is_Initialized;
|
||||
lan8742_IOCtx_t IO;
|
||||
void *pData;
|
||||
}lan8742_Object_t;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup LAN8742_Exported_Functions LAN8742 Exported Functions
|
||||
* @{
|
||||
*/
|
||||
int32_t LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx);
|
||||
int32_t LAN8742_Init(lan8742_Object_t *pObj);
|
||||
int32_t LAN8742_DeInit(lan8742_Object_t *pObj);
|
||||
int32_t LAN8742_DisablePowerDownMode(lan8742_Object_t *pObj);
|
||||
int32_t LAN8742_EnablePowerDownMode(lan8742_Object_t *pObj);
|
||||
int32_t LAN8742_StartAutoNego(lan8742_Object_t *pObj);
|
||||
int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj);
|
||||
int32_t LAN8742_SetLinkState(lan8742_Object_t *pObj, uint32_t LinkState);
|
||||
int32_t LAN8742_EnableLoopbackMode(lan8742_Object_t *pObj);
|
||||
int32_t LAN8742_DisableLoopbackMode(lan8742_Object_t *pObj);
|
||||
int32_t LAN8742_EnableIT(lan8742_Object_t *pObj, uint32_t Interrupt);
|
||||
int32_t LAN8742_DisableIT(lan8742_Object_t *pObj, uint32_t Interrupt);
|
||||
int32_t LAN8742_ClearIT(lan8742_Object_t *pObj, uint32_t Interrupt);
|
||||
int32_t LAN8742_GetITStatus(lan8742_Object_t *pObj, uint32_t Interrupt);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __LAN8742_H */
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,162 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT
|
||||
|
||||
#include "stm32h7xx_hal.h"
|
||||
|
||||
#define MCO_Pin GPIO_PIN_0
|
||||
#define MCO_GPIO_Port GPIOH
|
||||
#define RMII_MDC_Pin GPIO_PIN_1
|
||||
#define RMII_MDC_GPIO_Port GPIOC
|
||||
#define RMII_REF_CLK_Pin GPIO_PIN_1
|
||||
#define RMII_REF_CLK_GPIO_Port GPIOA
|
||||
#define RMII_MDIO_Pin GPIO_PIN_2
|
||||
#define RMII_MDIO_GPIO_Port GPIOA
|
||||
#define RMII_CRS_DV_Pin GPIO_PIN_7
|
||||
#define RMII_CRS_DV_GPIO_Port GPIOA
|
||||
#define RMII_RXD0_Pin GPIO_PIN_4
|
||||
#define RMII_RXD0_GPIO_Port GPIOC
|
||||
#define RMII_RXD1_Pin GPIO_PIN_5
|
||||
#define RMII_RXD1_GPIO_Port GPIOC
|
||||
#define RMII_TXD1_Pin GPIO_PIN_13
|
||||
#define RMII_TXD1_GPIO_Port GPIOB
|
||||
#define TMS_Pin GPIO_PIN_13
|
||||
#define TMS_GPIO_Port GPIOA
|
||||
#define TCK_Pin GPIO_PIN_14
|
||||
#define TCK_GPIO_Port GPIOA
|
||||
#define RMII_TX_EN_Pin GPIO_PIN_11
|
||||
#define RMII_TX_EN_GPIO_Port GPIOG
|
||||
#define RMII_TXD0_Pin GPIO_PIN_13
|
||||
#define RMII_TXD0_GPIO_Port GPIOG
|
||||
|
||||
/**
|
||||
* Override HAL Eth Init function
|
||||
*/
|
||||
void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
if(heth->Instance == ETH)
|
||||
{
|
||||
/* Disable DCache for STM32H7 family */
|
||||
SCB_DisableDCache();
|
||||
|
||||
/* GPIO Ports Clock Enable */
|
||||
__HAL_RCC_GPIOH_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOG_CLK_ENABLE();
|
||||
|
||||
/* Enable Peripheral clock */
|
||||
__HAL_RCC_ETH1MAC_CLK_ENABLE();
|
||||
__HAL_RCC_ETH1TX_CLK_ENABLE();
|
||||
__HAL_RCC_ETH1RX_CLK_ENABLE();
|
||||
|
||||
/**ETH GPIO Configuration
|
||||
PC1 ------> ETH_MDC
|
||||
PA1 ------> ETH_REF_CLK
|
||||
PA2 ------> ETH_MDIO
|
||||
PA7 ------> ETH_CRS_DV
|
||||
PC4 ------> ETH_RXD0
|
||||
PC5 ------> ETH_RXD1
|
||||
PB13 ------> ETH_TXD1
|
||||
PG11 ------> ETH_TX_EN
|
||||
PG13 ------> ETH_TXD0
|
||||
*/
|
||||
GPIO_InitStruct.Pin = RMII_MDC_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
|
||||
HAL_GPIO_Init(RMII_MDC_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = RMII_REF_CLK_Pin|RMII_MDIO_Pin|RMII_CRS_DV_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = RMII_RXD0_Pin|RMII_RXD1_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = RMII_TXD1_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
|
||||
HAL_GPIO_Init(RMII_TXD1_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = RMII_TX_EN_Pin|RMII_TXD0_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
|
||||
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override HAL Eth DeInit function
|
||||
*/
|
||||
void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
if(heth->Instance == ETH)
|
||||
{
|
||||
/* Disable Peripheral clock */
|
||||
__HAL_RCC_ETH1MAC_CLK_DISABLE();
|
||||
__HAL_RCC_ETH1TX_CLK_DISABLE();
|
||||
__HAL_RCC_ETH1RX_CLK_DISABLE();
|
||||
|
||||
/**ETH GPIO Configuration
|
||||
PC1 ------> ETH_MDC
|
||||
PA1 ------> ETH_REF_CLK
|
||||
PA2 ------> ETH_MDIO
|
||||
PA7 ------> ETH_CRS_DV
|
||||
PC4 ------> ETH_RXD0
|
||||
PC5 ------> ETH_RXD1
|
||||
PB13 ------> ETH_TXD1
|
||||
PG11 ------> ETH_TX_EN
|
||||
PG13 ------> ETH_TXD0
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOC, RMII_MDC_Pin|RMII_RXD0_Pin|RMII_RXD1_Pin);
|
||||
|
||||
HAL_GPIO_DeInit(GPIOA, RMII_REF_CLK_Pin|RMII_MDIO_Pin|RMII_CRS_DV_Pin);
|
||||
|
||||
HAL_GPIO_DeInit(RMII_TXD1_GPIO_Port, RMII_TXD1_Pin);
|
||||
|
||||
HAL_GPIO_DeInit(GPIOG, RMII_TX_EN_Pin|RMII_TXD0_Pin);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */
|
|
@ -0,0 +1,24 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef STM32XX_EMAC_CONFIG_H__
|
||||
#define STM32XX_EMAC_CONFIG_H__
|
||||
|
||||
#define ETH_IP_VERSION_V2
|
||||
|
||||
#define THREAD_STACKSIZE 512
|
||||
|
||||
#endif // #define STM32XX_EMAC_CONFIG_H__
|
|
@ -27,6 +27,12 @@
|
|||
#include "stm32xx_emac_config.h"
|
||||
#include "stm32xx_emac.h"
|
||||
|
||||
#if defined(ETH_IP_VERSION_V2)
|
||||
#include "lan8742/lan8742.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/api.h"
|
||||
#endif
|
||||
|
||||
/* \brief Flags for worker thread */
|
||||
#define FLAG_RX 1
|
||||
|
||||
|
@ -40,6 +46,8 @@
|
|||
#define STM_ETH_MTU_SIZE 1500
|
||||
#define STM_ETH_IF_NAME "st"
|
||||
|
||||
#ifndef ETH_IP_VERSION_V2
|
||||
|
||||
#if defined (__ICCARM__) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
|
@ -60,6 +68,52 @@ __ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END; /* Ethe
|
|||
#endif
|
||||
__ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END; /* Ethernet Transmit Buffer */
|
||||
|
||||
#else // ETH_IP_VERSION_V2
|
||||
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
|
||||
#pragma location=0x30040000
|
||||
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
|
||||
#pragma location=0x30040100
|
||||
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
|
||||
#pragma location=0x30040400
|
||||
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE]; /* Ethernet Receive Buffers */
|
||||
|
||||
#elif defined ( __CC_ARM ) /* MDK ARM Compiler */
|
||||
|
||||
__attribute__((section(".RxDecripSection"))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
|
||||
__attribute__((section(".TxDecripSection"))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
|
||||
__attribute__((section(".RxArraySection"))) uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffer */
|
||||
|
||||
#elif defined ( __GNUC__ ) /* GNU Compiler */
|
||||
|
||||
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
|
||||
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */
|
||||
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE] __attribute__((section(".RxArraySection"))); /* Ethernet Receive Buffers */
|
||||
|
||||
#endif
|
||||
|
||||
static lan8742_Object_t LAN8742;
|
||||
|
||||
static int32_t ETH_PHY_IO_Init(void);
|
||||
static int32_t ETH_PHY_IO_DeInit(void);
|
||||
static int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal);
|
||||
static int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
|
||||
static int32_t ETH_PHY_IO_GetTick(void);
|
||||
|
||||
static lan8742_IOCtx_t LAN8742_IOCtx =
|
||||
{
|
||||
ETH_PHY_IO_Init,
|
||||
ETH_PHY_IO_DeInit,
|
||||
ETH_PHY_IO_WriteReg,
|
||||
ETH_PHY_IO_ReadReg,
|
||||
ETH_PHY_IO_GetTick
|
||||
};
|
||||
|
||||
static ETH_TxPacketConfig TxConfig;
|
||||
|
||||
#endif // ETH_IP_VERSION_V2
|
||||
|
||||
__weak uint8_t mbed_otp_mac_address(char *mac);
|
||||
void mbed_default_mac_address(char *mac);
|
||||
|
||||
|
@ -75,6 +129,100 @@ void ETH_IRQHandler(void);
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef ETH_IP_VERSION_V2
|
||||
bool _phy_init()
|
||||
{
|
||||
/* Set PHY IO functions */
|
||||
LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);
|
||||
|
||||
/* Initialize the LAN8742 ETH PHY */
|
||||
return LAN8742_Init(&LAN8742) == LAN8742_STATUS_OK;
|
||||
}
|
||||
|
||||
int32_t _phy_get_state()
|
||||
{
|
||||
return LAN8742_GetLinkState(&LAN8742);
|
||||
}
|
||||
|
||||
bool _phy_get_duplex_and_speed(int32_t phy_state, uint32_t *duplex, uint32_t *speed)
|
||||
{
|
||||
switch (phy_state)
|
||||
{
|
||||
case LAN8742_STATUS_100MBITS_FULLDUPLEX:
|
||||
*duplex = ETH_FULLDUPLEX_MODE;
|
||||
*speed = ETH_SPEED_100M;
|
||||
break;
|
||||
case LAN8742_STATUS_100MBITS_HALFDUPLEX:
|
||||
*duplex = ETH_HALFDUPLEX_MODE;
|
||||
*speed = ETH_SPEED_100M;
|
||||
break;
|
||||
case LAN8742_STATUS_10MBITS_FULLDUPLEX:
|
||||
*duplex = ETH_FULLDUPLEX_MODE;
|
||||
*speed = ETH_SPEED_10M;
|
||||
break;
|
||||
case LAN8742_STATUS_10MBITS_HALFDUPLEX:
|
||||
*duplex = ETH_HALFDUPLEX_MODE;
|
||||
*speed = ETH_SPEED_10M;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _phy_is_up(int32_t phy_state)
|
||||
{
|
||||
return phy_state > LAN8742_STATUS_LINK_DOWN;
|
||||
}
|
||||
|
||||
static void MPU_Config(void)
|
||||
{
|
||||
MPU_Region_InitTypeDef MPU_InitStruct;
|
||||
|
||||
/* Disable the MPU */
|
||||
HAL_MPU_Disable();
|
||||
|
||||
/* Configure the MPU attributes as Device not cacheable
|
||||
for ETH DMA descriptors */
|
||||
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
|
||||
MPU_InitStruct.BaseAddress = 0x30040000;
|
||||
MPU_InitStruct.Size = MPU_REGION_SIZE_1KB;
|
||||
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
|
||||
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
|
||||
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
|
||||
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
|
||||
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
|
||||
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
|
||||
MPU_InitStruct.SubRegionDisable = 0x00;
|
||||
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
|
||||
|
||||
HAL_MPU_ConfigRegion(&MPU_InitStruct);
|
||||
|
||||
/* Configure the MPU attributes as Cacheable write through
|
||||
for LwIP RAM heap which contains the Tx buffers */
|
||||
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
|
||||
MPU_InitStruct.BaseAddress = 0x30044000;
|
||||
MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
|
||||
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
|
||||
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
|
||||
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
|
||||
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
|
||||
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
|
||||
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
|
||||
MPU_InitStruct.SubRegionDisable = 0x00;
|
||||
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
|
||||
|
||||
HAL_MPU_ConfigRegion(&MPU_InitStruct);
|
||||
|
||||
/* Enable the MPU */
|
||||
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Ethernet Rx Transfer completed callback
|
||||
*
|
||||
|
@ -103,6 +251,9 @@ void ETH_IRQHandler(void)
|
|||
|
||||
STM32_EMAC::STM32_EMAC()
|
||||
: thread(0)
|
||||
#ifdef ETH_IP_VERSION_V2
|
||||
, phy_status(0)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -122,6 +273,7 @@ static osThreadId_t create_new_thread(const char *threadName, void (*thread)(voi
|
|||
* In this function, the hardware should be initialized.
|
||||
*/
|
||||
bool STM32_EMAC::low_level_init_successful()
|
||||
#ifndef ETH_IP_VERSION_V2
|
||||
{
|
||||
/* Init ETH */
|
||||
uint8_t MACAddr[6];
|
||||
|
@ -160,6 +312,51 @@ bool STM32_EMAC::low_level_init_successful()
|
|||
|
||||
return true;
|
||||
}
|
||||
#else // ETH_IP_VERSION_V2
|
||||
{
|
||||
uint32_t idx, duplex, speed = 0;
|
||||
int32_t PHYLinkState;
|
||||
ETH_MACConfigTypeDef MACConf;
|
||||
|
||||
MPU_Config();
|
||||
|
||||
/* Init ETH */
|
||||
uint8_t MACAddr[6];
|
||||
EthHandle.Instance = ETH;
|
||||
#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
|
||||
MACAddr[0] = MBED_MAC_ADDR_0;
|
||||
MACAddr[1] = MBED_MAC_ADDR_1;
|
||||
MACAddr[2] = MBED_MAC_ADDR_2;
|
||||
MACAddr[3] = MBED_MAC_ADDR_3;
|
||||
MACAddr[4] = MBED_MAC_ADDR_4;
|
||||
MACAddr[5] = MBED_MAC_ADDR_5;
|
||||
#else
|
||||
mbed_mac_address((char *)MACAddr);
|
||||
#endif
|
||||
EthHandle.Init.MACAddr = &MACAddr[0];
|
||||
EthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE;
|
||||
EthHandle.Init.RxDesc = DMARxDscrTab;
|
||||
EthHandle.Init.TxDesc = DMATxDscrTab;
|
||||
EthHandle.Init.RxBuffLen = 1524;
|
||||
|
||||
if (HAL_ETH_Init(&EthHandle) != HAL_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(&TxConfig, 0, sizeof(ETH_TxPacketConfig));
|
||||
TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
|
||||
TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
|
||||
TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
|
||||
|
||||
for(idx = 0; idx < ETH_RX_DESC_CNT; idx++)
|
||||
{
|
||||
HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL);
|
||||
}
|
||||
|
||||
return _phy_init();
|
||||
}
|
||||
#endif // ETH_IP_VERSION_V2
|
||||
|
||||
/**
|
||||
* This function should do the actual transmission of the packet. The packet is
|
||||
|
@ -175,6 +372,7 @@ bool STM32_EMAC::low_level_init_successful()
|
|||
* dropped because of memory failure (except for the TCP timers).
|
||||
*/
|
||||
bool STM32_EMAC::link_out(emac_mem_buf_t *buf)
|
||||
#ifndef ETH_IP_VERSION_V2
|
||||
{
|
||||
bool success;
|
||||
emac_mem_buf_t *q;
|
||||
|
@ -252,6 +450,68 @@ error:
|
|||
|
||||
return success;
|
||||
}
|
||||
#else // ETH_IP_VERSION_V2
|
||||
{
|
||||
bool success = false;
|
||||
uint32_t i = 0;
|
||||
uint32_t frameLength = 0;
|
||||
struct pbuf *q;
|
||||
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];
|
||||
HAL_StatusTypeDef status;
|
||||
struct pbuf *p = NULL;
|
||||
p = (struct pbuf *)buf;
|
||||
/* Get exclusive access */
|
||||
TXLockMutex.lock();
|
||||
|
||||
memset(Txbuffer, 0 , ETH_TX_DESC_CNT*sizeof(ETH_BufferTypeDef));
|
||||
|
||||
/* copy frame from pbufs to driver buffers */
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
if (i >= ETH_TX_DESC_CNT) {
|
||||
printf("Error : ETH_TX_DESC_CNT not sufficient\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
Txbuffer[i].buffer = (uint8_t *)q->payload;
|
||||
Txbuffer[i].len = q->len;
|
||||
frameLength += q->len;
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
Txbuffer[i - 1].next = &Txbuffer[i];
|
||||
}
|
||||
|
||||
if (q->next == NULL)
|
||||
{
|
||||
Txbuffer[i].next = NULL;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
TxConfig.Length = frameLength;
|
||||
TxConfig.TxBuffer = Txbuffer;
|
||||
|
||||
status = HAL_ETH_Transmit(&EthHandle, &TxConfig, 50);
|
||||
if(status == HAL_OK){
|
||||
success = 1;
|
||||
} else {
|
||||
printf("Error returned by HAL_ETH_Transmit (%d)\n", status);
|
||||
success = 0;
|
||||
}
|
||||
|
||||
error:
|
||||
|
||||
if (p->ref > 1) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
/* Restore access */
|
||||
TXLockMutex.unlock();
|
||||
|
||||
return success;
|
||||
}
|
||||
#endif // ETH_IP_VERSION_V2
|
||||
|
||||
/**
|
||||
* Should allocate a contiguous memory buffer and transfer the bytes of the incoming
|
||||
|
@ -263,6 +523,7 @@ error:
|
|||
* zero when frame is received
|
||||
*/
|
||||
int STM32_EMAC::low_level_input(emac_mem_buf_t **buf)
|
||||
#ifndef ETH_IP_VERSION_V2
|
||||
{
|
||||
uint16_t len = 0;
|
||||
uint8_t *buffer;
|
||||
|
@ -336,7 +597,39 @@ int STM32_EMAC::low_level_input(emac_mem_buf_t **buf)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#else // ETH_IP_VERSION_V2
|
||||
{
|
||||
ETH_BufferTypeDef RxBuff;
|
||||
uint32_t frameLength = 0;
|
||||
|
||||
if (HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff) == HAL_OK)
|
||||
{
|
||||
if (HAL_ETH_GetRxDataLength(&EthHandle, &frameLength) != HAL_OK)
|
||||
{
|
||||
printf("Error: returned by HAL_ETH_GetRxDataLength\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Build Rx descriptor to be ready for next data reception */
|
||||
HAL_ETH_BuildRxDescriptors(&EthHandle);
|
||||
|
||||
/* Invalidate data cache for ETH Rx Buffers */
|
||||
SCB_InvalidateDCache_by_Addr((uint32_t *)RxBuff.buffer, frameLength);
|
||||
|
||||
*buf = pbuf_alloc(PBUF_RAW, frameLength, PBUF_POOL);
|
||||
if (*buf)
|
||||
{
|
||||
pbuf_take((struct pbuf *)*buf, RxBuff.buffer, frameLength);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // ETH_IP_VERSION_V2
|
||||
|
||||
/** \brief Attempt to read a packet from the EMAC interface.
|
||||
*
|
||||
|
@ -346,12 +639,15 @@ void STM32_EMAC::packet_rx()
|
|||
/* move received packet into a new buf */
|
||||
while (1) {
|
||||
emac_mem_buf_t *p = NULL;
|
||||
RXLockMutex.lock();
|
||||
if (low_level_input(&p) < 0) {
|
||||
RXLockMutex.unlock();
|
||||
break;
|
||||
}
|
||||
if (p) {
|
||||
emac_link_input_cb(p);
|
||||
}
|
||||
RXLockMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,6 +674,7 @@ void STM32_EMAC::thread_function(void *pvParameters)
|
|||
* This task checks phy link status and updates net status
|
||||
*/
|
||||
void STM32_EMAC::phy_task()
|
||||
#ifndef ETH_IP_VERSION_V2
|
||||
{
|
||||
uint32_t status;
|
||||
|
||||
|
@ -393,6 +690,51 @@ void STM32_EMAC::phy_task()
|
|||
}
|
||||
|
||||
}
|
||||
#else // ETH_IP_VERSION_V2
|
||||
{
|
||||
const int32_t status = _phy_get_state();
|
||||
const int32_t old_status = (int32_t)phy_status;
|
||||
const bool is_up = _phy_is_up(status);
|
||||
const bool was_up = _phy_is_up(old_status);
|
||||
|
||||
if (is_up && !was_up)
|
||||
{
|
||||
uint32_t duplex, speed;
|
||||
ETH_MACConfigTypeDef MACConf;
|
||||
|
||||
if (!_phy_get_duplex_and_speed(status, &speed, &duplex))
|
||||
{
|
||||
// Default
|
||||
duplex = ETH_FULLDUPLEX_MODE;
|
||||
speed = ETH_SPEED_10M;
|
||||
}
|
||||
|
||||
/* Get MAC Config MAC */
|
||||
HAL_ETH_GetMACConfig(&EthHandle, &MACConf);
|
||||
MACConf.DuplexMode = duplex;
|
||||
MACConf.Speed = speed;
|
||||
HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
|
||||
HAL_ETH_Start_IT(&EthHandle);
|
||||
}
|
||||
else if (was_up && !is_up)
|
||||
{
|
||||
// Stop ETH
|
||||
disable_interrupts();
|
||||
HAL_ETH_Stop(&EthHandle);
|
||||
enable_interrupts();
|
||||
}
|
||||
|
||||
if (emac_link_state_cb) {
|
||||
if (is_up && !was_up) {
|
||||
emac_link_state_cb(true);
|
||||
} else if (!is_up && was_up) {
|
||||
emac_link_state_cb(false);
|
||||
}
|
||||
}
|
||||
|
||||
phy_status = (uint32_t)status;
|
||||
}
|
||||
#endif // ETH_IP_VERSION_V2
|
||||
|
||||
#if defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx)\
|
||||
|| defined (STM32F779xx)
|
||||
|
@ -475,6 +817,8 @@ void mbed_default_mac_address(char *mac)
|
|||
uint32_t word0 = *(uint32_t *)0x1FFF7A10;
|
||||
#elif defined (TARGET_STM32F7)
|
||||
uint32_t word0 = *(uint32_t *)0x1FF0F420;
|
||||
#elif defined (TARGET_STM32H7)
|
||||
uint32_t word0 = *(uint32_t *)0x1FF1E800;
|
||||
#else
|
||||
#error MAC address can not be derived from target unique Id
|
||||
#endif
|
||||
|
@ -594,3 +938,100 @@ MBED_WEAK EMAC &EMAC::get_default_instance()
|
|||
{
|
||||
return STM32_EMAC::get_instance();
|
||||
}
|
||||
|
||||
#if defined(ETH_IP_VERSION_V2)
|
||||
/*******************************************************************************
|
||||
PHI IO Functions
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Initializes the MDIO interface GPIO and clocks.
|
||||
* @param None
|
||||
* @retval 0 if OK, -1 if ERROR
|
||||
*/
|
||||
static int32_t ETH_PHY_IO_Init(void)
|
||||
{
|
||||
/* We assume that MDIO GPIO configuration is already done
|
||||
in the ETH_MspInit() else it should be done here
|
||||
*/
|
||||
STM32_EMAC &emac = STM32_EMAC::get_instance();
|
||||
|
||||
/* Configure the MDIO Clock */
|
||||
HAL_ETH_SetMDIOClockRange(&emac.EthHandle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initializes the MDIO interface .
|
||||
* @param None
|
||||
* @retval 0 if OK, -1 if ERROR
|
||||
*/
|
||||
static int32_t ETH_PHY_IO_DeInit (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a PHY register through the MDIO interface.
|
||||
* @param DevAddr: PHY port address
|
||||
* @param RegAddr: PHY register address
|
||||
* @param pRegVal: pointer to hold the register value
|
||||
* @retval 0 if OK -1 if Error
|
||||
*/
|
||||
static int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal)
|
||||
{
|
||||
STM32_EMAC &emac = STM32_EMAC::get_instance();
|
||||
if(HAL_ETH_ReadPHYRegister(&emac.EthHandle, DevAddr, RegAddr, pRegVal) != HAL_OK)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a value to a PHY register through the MDIO interface.
|
||||
* @param DevAddr: PHY port address
|
||||
* @param RegAddr: PHY register address
|
||||
* @param RegVal: Value to be written
|
||||
* @retval 0 if OK -1 if Error
|
||||
*/
|
||||
static int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal)
|
||||
{
|
||||
STM32_EMAC &emac = STM32_EMAC::get_instance();
|
||||
if(HAL_ETH_WritePHYRegister(&emac.EthHandle, DevAddr, RegAddr, RegVal) != HAL_OK)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the time in millisecons used for internal PHY driver process.
|
||||
* @retval Time value
|
||||
*/
|
||||
static int32_t ETH_PHY_IO_GetTick(void)
|
||||
{
|
||||
return HAL_GetTick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ethernet DMA transfer error callbacks
|
||||
*/
|
||||
void HAL_ETH_DMAErrorCallback(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_ETHERNET, EIO), \
|
||||
"Error from ethernet HAL (HAL_ETH_DMAErrorCallback)\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ethernet MAC transfer error callbacks
|
||||
*/
|
||||
void HAL_ETH_MACErrorCallback(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_ETHERNET, EIO), \
|
||||
"Error from ethernet HAL (HAL_ETH_MACErrorCallback)\n");
|
||||
}
|
||||
#endif // ETH_IP_VERSION_V2
|
||||
|
|
|
@ -167,6 +167,7 @@ private:
|
|||
osThreadId_t rmii_watchdog_thread; /**< Watchdog processing thread */
|
||||
#endif
|
||||
rtos::Mutex TXLockMutex;/**< TX critical section mutex */
|
||||
rtos::Mutex RXLockMutex;/**< RX critical section mutex */
|
||||
emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */
|
||||
emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */
|
||||
EMACMemoryManager *memory_manager; /**< Memory manager */
|
||||
|
|
|
@ -82,6 +82,10 @@ void test_read_write()
|
|||
err = file.close();
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
struct stat st;
|
||||
err = fs.stat("test_read_write.dat", &st);
|
||||
TEST_ASSERT_EQUAL(TEST_SIZE, st.st_size);
|
||||
|
||||
err = file.open(&fs, "test_read_write.dat", O_RDONLY);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
size = file.read(buffer, TEST_SIZE);
|
||||
|
|
|
@ -53,11 +53,12 @@ static inline uint32_t align_down(uint64_t val, uint64_t size)
|
|||
int get_virtual_TDBStore_position(uint32_t conf_start_address, uint32_t conf_size, bool is_conf_tdb_internal,
|
||||
uint32_t *tdb_start_address, uint32_t *tdb_end_address)
|
||||
{
|
||||
uint32_t bd_final_size = conf_size;;
|
||||
uint32_t bd_final_size = conf_size;
|
||||
uint32_t flash_end_address;
|
||||
uint32_t flash_start_address;
|
||||
uint32_t aligned_start_address;
|
||||
FlashIAP flash;
|
||||
static const int STORE_SECTORS = 2;
|
||||
|
||||
int ret = flash.init();
|
||||
if (ret != 0) {
|
||||
|
@ -92,34 +93,19 @@ int get_virtual_TDBStore_position(uint32_t conf_start_address, uint32_t conf_si
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (is_conf_tdb_internal == true) {
|
||||
aligned_start_address = flash_first_writable_sector_address;
|
||||
bd_size_t spare_size_for_app = 0;
|
||||
bd_addr_t curr_addr = aligned_start_address;
|
||||
int spare_sectors_for_app = 2;
|
||||
int min_sectors_for_storage = 2;
|
||||
for (int i = 0; i < spare_sectors_for_app + min_sectors_for_storage - 1; i++) {
|
||||
bd_size_t sector_size = flash.get_sector_size(curr_addr);
|
||||
curr_addr += sector_size;
|
||||
if (curr_addr >= flash_end_address) {
|
||||
spare_size_for_app = 0;
|
||||
break;
|
||||
}
|
||||
// Assumption is that last two sectors are reserved for the TDBStore
|
||||
aligned_start_address = flash.get_flash_start() + flash.get_flash_size();
|
||||
|
||||
if (i < spare_sectors_for_app) {
|
||||
spare_size_for_app += sector_size;
|
||||
}
|
||||
}
|
||||
aligned_start_address += spare_size_for_app;
|
||||
bd_final_size = (flash_end_address - aligned_start_address);
|
||||
} else {
|
||||
aligned_start_address = flash_end_address - (flash.get_sector_size(flash_end_address - 1) * 2);
|
||||
if (aligned_start_address < flash_first_writable_sector_address) {
|
||||
flash.deinit();
|
||||
return -2;
|
||||
}
|
||||
bd_final_size = (flash_end_address - aligned_start_address);
|
||||
for (int i = STORE_SECTORS; i; i--) {
|
||||
bd_size_t sector_size = flash.get_sector_size(aligned_start_address - 1);
|
||||
aligned_start_address -= sector_size;
|
||||
}
|
||||
|
||||
if (aligned_start_address < flash_first_writable_sector_address) {
|
||||
flash.deinit();
|
||||
return -2;
|
||||
}
|
||||
bd_final_size = (flash_end_address - aligned_start_address);
|
||||
}
|
||||
|
||||
(*tdb_start_address) = aligned_start_address;
|
||||
|
|
|
@ -34,7 +34,8 @@ static const size_t buffer_size = 20;
|
|||
static const int num_of_threads = 3;
|
||||
static const char num_of_keys = 3;
|
||||
|
||||
static const int heap_alloc_threshold_size = 4096;
|
||||
/* Forked 3 threads plus misc, so minimum (4 * OS_STACK_SIZE) heap are required. */
|
||||
static const int heap_alloc_threshold_size = 4 * OS_STACK_SIZE;
|
||||
|
||||
static const char *keys[] = {"key1", "key2", "key3"};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2012 ARM Limited
|
||||
* Copyright (c) 2006-2019 ARM Limited
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -280,9 +280,8 @@ extern "C" DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
|
|||
|
||||
// Filesystem implementation (See FATFilySystem.h)
|
||||
FATFileSystem::FATFileSystem(const char *name, BlockDevice *bd)
|
||||
: FileSystem(name), _id(-1)
|
||||
: FileSystem(name), _fs(), _id(-1)
|
||||
{
|
||||
_fs = { 0 };
|
||||
if (bd) {
|
||||
mount(bd);
|
||||
}
|
||||
|
@ -517,15 +516,12 @@ int FATFileSystem::stat(const char *path, struct stat *st)
|
|||
return fat_error_remap(res);
|
||||
}
|
||||
|
||||
/* ARMCC doesnt support stat(), and these symbols are not defined by the toolchain. */
|
||||
#ifdef TOOLCHAIN_GCC
|
||||
st->st_size = f.fsize;
|
||||
st->st_mode = 0;
|
||||
st->st_mode |= (f.fattrib & AM_DIR) ? S_IFDIR : S_IFREG;
|
||||
st->st_mode |= (f.fattrib & AM_RDO) ?
|
||||
(S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) :
|
||||
(S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
#endif /* TOOLCHAIN_GCC */
|
||||
unlock();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -267,51 +267,48 @@ FileSystem *_get_filesystem_default(const char *mount)
|
|||
}
|
||||
|
||||
//Calculates the start address of FLASHIAP block device for TDB_INTERNAL profile.
|
||||
//If possible, the address will start 2 sectors after the end of code sector allowing
|
||||
//some space for an application update.
|
||||
//Last two sectors to have a predictable location for the TDBStore
|
||||
int _get_flashiap_bd_default_addresses_tdb_internal(bd_addr_t *start_address, bd_size_t *size)
|
||||
{
|
||||
int ret = MBED_SUCCESS;
|
||||
|
||||
#if COMPONENT_FLASHIAP
|
||||
|
||||
FlashIAP flash;
|
||||
static const int STORE_SECTORS = 2;
|
||||
|
||||
if (*start_address != 0 || *size != 0) {
|
||||
if (*start_address || *size) {
|
||||
return MBED_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
//If default values are set, we should get the maximum available size of internal bd.
|
||||
if (flash.init() != 0) {
|
||||
return MBED_ERROR_FAILED_OPERATION;
|
||||
}
|
||||
|
||||
*start_address = align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR));
|
||||
// Lets work from end of the flash backwards
|
||||
bd_addr_t curr_addr = flash.get_flash_start() + flash.get_flash_size();
|
||||
|
||||
// Give the application a couple of spare sectors to grow (if there are such)
|
||||
bd_size_t spare_size_for_app = 0;
|
||||
bd_addr_t curr_addr = *start_address;
|
||||
bd_addr_t flash_end_address = flash.get_flash_start() + flash.get_flash_size();
|
||||
|
||||
int spare_sectors_for_app = 2;
|
||||
int min_sectors_for_storage = 2;
|
||||
for (int i = 0; i < spare_sectors_for_app + min_sectors_for_storage - 1; i++) {
|
||||
bd_size_t sector_size = flash.get_sector_size(curr_addr);
|
||||
curr_addr += sector_size;
|
||||
if (curr_addr >= flash_end_address) {
|
||||
spare_size_for_app = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < spare_sectors_for_app) {
|
||||
spare_size_for_app += sector_size;
|
||||
}
|
||||
for (int i = STORE_SECTORS; i; i--) {
|
||||
bd_size_t sector_size = flash.get_sector_size(curr_addr - 1);
|
||||
curr_addr -= sector_size;
|
||||
}
|
||||
|
||||
// Store- and application-sectors mustn't overlap
|
||||
uint32_t first_wrtbl_sector_addr =
|
||||
(uint32_t)(align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR)));
|
||||
|
||||
MBED_ASSERT(curr_addr >= first_wrtbl_sector_addr);
|
||||
if (curr_addr < first_wrtbl_sector_addr) {
|
||||
ret = MBED_ERROR_MEDIA_FULL;
|
||||
} else {
|
||||
*start_address = curr_addr;
|
||||
}
|
||||
*start_address += spare_size_for_app;
|
||||
|
||||
flash.deinit();
|
||||
|
||||
#endif
|
||||
|
||||
return MBED_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//Calculates address and size for FLASHIAP block device in TDB_EXTERNAL and FILESYSTEM profiles.
|
||||
|
@ -697,11 +694,13 @@ int _storage_config_TDB_INTERNAL()
|
|||
#if COMPONENT_FLASHIAP
|
||||
bd_size_t internal_size = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_SIZE;
|
||||
bd_addr_t internal_start_address = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS;
|
||||
int ret;
|
||||
|
||||
if (internal_size == 0 && internal_start_address == 0) {
|
||||
//Calculate the block device size and start address in case default values are used.
|
||||
if (_get_flashiap_bd_default_addresses_tdb_internal(&internal_start_address, &internal_size) != MBED_SUCCESS) {
|
||||
return MBED_ERROR_FAILED_OPERATION;
|
||||
ret = _get_flashiap_bd_default_addresses_tdb_internal(&internal_start_address, &internal_size);
|
||||
if (ret != MBED_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -713,7 +712,7 @@ int _storage_config_TDB_INTERNAL()
|
|||
}
|
||||
|
||||
|
||||
int ret = kvstore_config.internal_bd->init();
|
||||
ret = kvstore_config.internal_bd->init();
|
||||
if (ret != MBED_SUCCESS) {
|
||||
tr_error("KV Config: Fail to init internal BlockDevice.");
|
||||
return MBED_ERROR_FAILED_OPERATION;
|
||||
|
|
|
@ -123,6 +123,9 @@ int get_expected_internal_TDBStore_position(uint32_t *out_tdb_start_offset, uin
|
|||
} else if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_EXTERNAL") == 0) {
|
||||
*out_tdb_start_offset = MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS;
|
||||
tdb_size = MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE;
|
||||
} else if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_INTERNAL") == 0) {
|
||||
*out_tdb_start_offset = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS;
|
||||
tdb_size = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_SIZE;
|
||||
} else if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "default") == 0) {
|
||||
#if COMPONENT_QSPIF || COMPONENT_SPIF || COMPONENT_DATAFLASH
|
||||
*out_tdb_start_offset = MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS;
|
||||
|
|
|
@ -32,7 +32,8 @@ extern "C" {
|
|||
* Low level interface to the microsecond ticker of a target
|
||||
*
|
||||
* # Defined behavior
|
||||
* * Has a reported frequency between 250KHz and 8MHz - Verified by test ::us_ticker_info_test
|
||||
* * Has a reported frequency between 250KHz and 8MHz for counters which are less than 32 bits wide - Verified by test ::us_ticker_info_test
|
||||
* * Has a reported frequency up to 100MHz for counters which are 32 bits wide - Verified by test ::us_ticker_info_test
|
||||
* * Has a counter that is at least 16 bits wide - Verified by test ::us_ticker_info_test
|
||||
* * All behavior defined by the @ref hal_ticker_shared "ticker specification"
|
||||
*
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
*
|
||||
* @note 99 is default value for development version (master branch)
|
||||
*/
|
||||
#define MBED_PATCH_VERSION 2
|
||||
#define MBED_PATCH_VERSION 4
|
||||
|
||||
#define MBED_ENCODE_VERSION(major, minor, patch) ((major)*10000 + (minor)*100 + (patch))
|
||||
|
||||
|
|
|
@ -49,8 +49,9 @@ void Thread::constructor(uint32_t tz_module, osPriority priority,
|
|||
const uint32_t offset = aligned_mem - unaligned_mem;
|
||||
const uint32_t aligned_size = ALIGN_DOWN(stack_size - offset, 8);
|
||||
|
||||
_tid = 0;
|
||||
_dynamic_stack = (stack_mem == NULL);
|
||||
memset(&_obj_mem, 0, sizeof(_obj_mem));
|
||||
_tid = nullptr;
|
||||
_dynamic_stack = (stack_mem == nullptr);
|
||||
_finished = false;
|
||||
memset(&_attr, 0, sizeof(_attr));
|
||||
_attr.priority = priority;
|
||||
|
@ -104,7 +105,6 @@ osStatus Thread::start(mbed::Callback<void()> task)
|
|||
((uint32_t *)_attr.stack_mem)[i] = osRtxStackMagicWord;
|
||||
}
|
||||
|
||||
memset(&_obj_mem, 0, sizeof(_obj_mem));
|
||||
_attr.cb_size = sizeof(_obj_mem);
|
||||
_attr.cb_mem = &_obj_mem;
|
||||
_task = task;
|
||||
|
|
|
@ -19,10 +19,10 @@ extern "C" {
|
|||
* cyw943012csp_ty1LV.TXT
|
||||
*/
|
||||
static const char wifi_nvram_image[] =
|
||||
"NVRAMRev=$Rev: 351687 $" "\x00"
|
||||
"NVRAMRev=$Rev: 721914 $" "\x00"
|
||||
"sromrev=11" "\x00"
|
||||
"cckdigfilttype=4" "\x00"
|
||||
"cckpwroffset0=3" "\x00"
|
||||
"cckpwroffset0=2" "\x00"
|
||||
"bphyscale=0x20" "\x00"
|
||||
"boardflags3=0x40000100" "\x00"
|
||||
"vendid=0x14e4" "\x00"
|
||||
|
@ -32,11 +32,11 @@ static const char wifi_nvram_image[] =
|
|||
NVRAM_GENERATED_MAC_ADDRESS "\x00"
|
||||
"mac_clkgating=1" "\x00"
|
||||
"nocrc=1" "\x00"
|
||||
"boardtype=0x0842" "\x00"
|
||||
"boardrev=0x1100" "\x00"
|
||||
"boardtype=0x0869" "\x00"
|
||||
"boardrev=0x1102" "\x00"
|
||||
"xtalfreq=37400" "\x00"
|
||||
"boardflags2=0xc0000000" "\x00"
|
||||
"boardflags=0x00000000" "\x00"
|
||||
"boardflags=0x00000001" "\x00"
|
||||
"etmode=0x11" "\x00"
|
||||
"extpagain2g=2" "\x00"
|
||||
"extpagain5g=2" "\x00"
|
||||
|
@ -61,17 +61,17 @@ static const char wifi_nvram_image[] =
|
|||
"tssipos2g=0" "\x00"
|
||||
"femctrl=17" "\x00"
|
||||
"subband5gver=4" "\x00"
|
||||
"pa2ga0=-108,5627,-638" "\x00"
|
||||
"pa5ga0=-41,6533,-726,-29,6654,-746,9,6914,-772,12,7008,-806" "\x00"
|
||||
"pa2ga0=-108,6062,-661" "\x00"
|
||||
"pa5ga0=-82,6252,-698,-14,6722,-697,-92,6084,-710,-88,6465,-755" "\x00"
|
||||
"pdoffset40ma0=0" "\x00"
|
||||
"pdoffset80ma0=0" "\x00"
|
||||
"lowpowerrange2g=0" "\x00"
|
||||
"lowpowerrange5g=0" "\x00"
|
||||
"ed_thresh2g=-63" "\x00"
|
||||
"ed_thresh5g=-63" "\x00"
|
||||
"swctrlmap_2g=0x10101010,0x20202020,0x10101010,0x414040,0x3ff" "\x00"
|
||||
"swctrlmapext_2g=0x00000000,0x01000100,0x01000100,0x010000,0x301" "\x00"
|
||||
"swctrlmap_5g=0x80808080,0x00000000,0x80808080,0x404040,0x3ff" "\x00"
|
||||
"swctrlmap_2g=0x10101010,0x20202020,0x10101010,0x442020,0x3ff" "\x00"
|
||||
"swctrlmapext_2g=0x01000100,0x01000100,0x01000100,0x000000,0x301" "\x00"
|
||||
"swctrlmap_5g=0x80808080,0x00000000,0x80808080,0x442020,0x381" "\x00"
|
||||
"swctrlmapext_5g=0x01000100,0x01000100,0x00000000,0x000100,0x303" "\x00"
|
||||
"ulpnap=0" "\x00"
|
||||
"ulpadc=1" "\x00"
|
||||
|
@ -84,14 +84,14 @@ static const char wifi_nvram_image[] =
|
|||
"epacal5g=0" "\x00"
|
||||
"papdcck=0" "\x00"
|
||||
"epacal2g_mask=0x3fff" "\x00"
|
||||
"maxp2ga0=82" "\x00"
|
||||
"ofdmlrbw202gpo=0x0077" "\x00"
|
||||
"dot11agofdmhrbw202gpo=0x8888" "\x00"
|
||||
"mcsbw202gpo=0x99999999" "\x00"
|
||||
"maxp5ga0=82,82,82,82" "\x00"
|
||||
"mcsbw205glpo=0x99999999" "\x00"
|
||||
"mcsbw205gmpo=0x99999999" "\x00"
|
||||
"mcsbw205ghpo=0x99999999" "\x00"
|
||||
"maxp2ga0=74" "\x00"
|
||||
"ofdmlrbw202gpo=0x0020" "\x00"
|
||||
"dot11agofdmhrbw202gpo=0x6442" "\x00"
|
||||
"mcsbw202gpo=0xCC864420" "\x00"
|
||||
"maxp5ga0=70,70,70,70" "\x00"
|
||||
"mcsbw205glpo=0xCC864220" "\x00"
|
||||
"mmcsbw205gmpo=0xCC864220" "\x00"
|
||||
"mcsbw205ghpo=0xCC864220" "\x00"
|
||||
"femctrlwar=0" "\x00"
|
||||
"use5gpllfor2g=1" "\x00"
|
||||
"pt5db_gaintbl=0" "\x00"
|
||||
|
@ -121,6 +121,16 @@ static const char wifi_nvram_image[] =
|
|||
"lpo_select=4" "\x00"
|
||||
"paprrmcsgamma2g=450,500,550,600,675,950,950,950,950,950,950,950" "\x00"
|
||||
"paprrmcsgamma5g20=450,500,550,600,800,950,1100,1100,1100,1100,1100,1100" "\x00"
|
||||
"swdiv_en=0" "\x00"
|
||||
"swdiv_gpio=0" "\x00"
|
||||
"swdiv_swctrl_en=2" "\x00"
|
||||
"swdiv_swctrl_ant0=0" "\x00"
|
||||
"swdiv_swctrl_ant1=1" "\x00"
|
||||
"swdiv_antmap2g_main=1" "\x00"
|
||||
"swdiv_antmap5g_main=1" "\x00"
|
||||
"swdiv_snrlim=10000" "\x00"
|
||||
"swdiv_thresh=3000" "\x00"
|
||||
"swdiv_snrthresh=24" "\x00"
|
||||
"\x00\x00";
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C" */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* Copyright 2016-2019 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_DSPI_H_
|
||||
#define _FSL_DSPI_H_
|
||||
|
@ -43,8 +21,8 @@
|
|||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief DSPI driver version 2.2.0. */
|
||||
#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 0))
|
||||
/*! @brief DSPI driver version 2.2.2. */
|
||||
#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 2))
|
||||
/*@}*/
|
||||
|
||||
#ifndef DSPI_DUMMY_DATA
|
||||
|
@ -55,37 +33,37 @@
|
|||
/*! @brief Status for the DSPI driver.*/
|
||||
enum _dspi_status
|
||||
{
|
||||
kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/
|
||||
kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */
|
||||
kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/
|
||||
kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */
|
||||
kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/
|
||||
kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */
|
||||
kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/
|
||||
kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */
|
||||
};
|
||||
|
||||
/*! @brief DSPI status flags in SPIx_SR register.*/
|
||||
enum _dspi_flags
|
||||
{
|
||||
kDSPI_TxCompleteFlag = SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */
|
||||
kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/
|
||||
kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/
|
||||
kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/
|
||||
kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/
|
||||
kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/
|
||||
kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/
|
||||
kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK |
|
||||
SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All statuses above.*/
|
||||
kDSPI_TxCompleteFlag = (int)SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */
|
||||
kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/
|
||||
kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/
|
||||
kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/
|
||||
kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/
|
||||
kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/
|
||||
kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/
|
||||
kDSPI_AllStatusFlag = (int)(SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK |
|
||||
SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK) /*!< All statuses above.*/
|
||||
};
|
||||
|
||||
/*! @brief DSPI interrupt source.*/
|
||||
enum _dspi_interrupt_enable
|
||||
{
|
||||
kDSPI_TxCompleteInterruptEnable = SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/
|
||||
kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/
|
||||
kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/
|
||||
kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/
|
||||
kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/
|
||||
kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/
|
||||
kDSPI_AllInterruptEnable = SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK |
|
||||
SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK
|
||||
kDSPI_TxCompleteInterruptEnable = (int)SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/
|
||||
kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/
|
||||
kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/
|
||||
kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/
|
||||
kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/
|
||||
kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/
|
||||
kDSPI_AllInterruptEnable = (int)(SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK |
|
||||
SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK)
|
||||
/*!< All above interrupts enable.*/
|
||||
};
|
||||
|
||||
|
@ -102,7 +80,7 @@ enum _dspi_dma_enable
|
|||
typedef enum _dspi_master_slave_mode
|
||||
{
|
||||
kDSPI_Master = 1U, /*!< DSPI peripheral operates in master mode.*/
|
||||
kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/
|
||||
kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/
|
||||
} dspi_master_slave_mode_t;
|
||||
|
||||
/*!
|
||||
|
@ -132,26 +110,26 @@ typedef enum _dspi_which_pcs_config
|
|||
typedef enum _dspi_pcs_polarity_config
|
||||
{
|
||||
kDSPI_PcsActiveHigh = 0U, /*!< Pcs Active High (idles low). */
|
||||
kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */
|
||||
kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */
|
||||
} dspi_pcs_polarity_config_t;
|
||||
|
||||
/*! @brief DSPI Peripheral Chip Select (Pcs) Polarity.*/
|
||||
enum _dspi_pcs_polarity
|
||||
{
|
||||
kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */
|
||||
kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */
|
||||
kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */
|
||||
kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */
|
||||
kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */
|
||||
kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */
|
||||
kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */
|
||||
kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */
|
||||
kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */
|
||||
kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */
|
||||
kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */
|
||||
kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */
|
||||
kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */
|
||||
kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */
|
||||
};
|
||||
|
||||
/*! @brief DSPI clock polarity configuration for a given CTAR.*/
|
||||
typedef enum _dspi_clock_polarity
|
||||
{
|
||||
kDSPI_ClockPolarityActiveHigh = 0U, /*!< CPOL=0. Active-high DSPI clock (idles low).*/
|
||||
kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/
|
||||
kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/
|
||||
} dspi_clock_polarity_t;
|
||||
|
||||
/*! @brief DSPI clock phase configuration for a given CTAR.*/
|
||||
|
@ -216,7 +194,7 @@ enum _dspi_transfer_config_flag_for_master
|
|||
kDSPI_MasterPcs4 = 4U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS4 signal. */
|
||||
kDSPI_MasterPcs5 = 5U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS5 signal. */
|
||||
|
||||
kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */
|
||||
kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */
|
||||
kDSPI_MasterActiveAfterTransfer =
|
||||
1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/
|
||||
};
|
||||
|
@ -241,7 +219,7 @@ enum _dspi_transfer_state
|
|||
/*! @brief DSPI master command date configuration used for the SPIx_PUSHR.*/
|
||||
typedef struct _dspi_command_data_config
|
||||
{
|
||||
bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/
|
||||
bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/
|
||||
dspi_ctar_selection_t whichCtar; /*!< The desired Clock and Transfer Attributes
|
||||
Register (CTAR) to use for CTAS.*/
|
||||
dspi_which_pcs_t whichPcs; /*!< The desired PCS signal to use for the data transfer.*/
|
||||
|
@ -258,10 +236,10 @@ typedef struct _dspi_master_ctar_config
|
|||
dspi_clock_phase_t cpha; /*!< Clock phase. */
|
||||
dspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */
|
||||
|
||||
uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum
|
||||
delay. It also sets the boundary value if out of range.*/
|
||||
uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the
|
||||
minimum delay. It also sets the boundary value if out of range.*/
|
||||
uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum
|
||||
delay. It also sets the boundary value if out of range.*/
|
||||
uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the
|
||||
minimum delay. It also sets the boundary value if out of range.*/
|
||||
|
||||
uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time in nanoseconds; setting to 0 sets the minimum
|
||||
delay. It also sets the boundary value if out of range.*/
|
||||
|
@ -315,13 +293,13 @@ typedef struct _dspi_slave_config
|
|||
} dspi_slave_config_t;
|
||||
|
||||
/*!
|
||||
* @brief Forward declaration of the _dspi_master_handle typedefs.
|
||||
*/
|
||||
* @brief Forward declaration of the _dspi_master_handle typedefs.
|
||||
*/
|
||||
typedef struct _dspi_master_handle dspi_master_handle_t;
|
||||
|
||||
/*!
|
||||
* @brief Forward declaration of the _dspi_slave_handle typedefs.
|
||||
*/
|
||||
* @brief Forward declaration of the _dspi_slave_handle typedefs.
|
||||
*/
|
||||
typedef struct _dspi_slave_handle dspi_slave_handle_t;
|
||||
|
||||
/*!
|
||||
|
@ -356,12 +334,24 @@ typedef struct _dspi_transfer
|
|||
uint8_t *rxData; /*!< Receive buffer. */
|
||||
volatile size_t dataSize; /*!< Transfer bytes. */
|
||||
|
||||
uint32_t
|
||||
configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if the
|
||||
transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer
|
||||
is used for slave.*/
|
||||
uint32_t configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if
|
||||
the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the
|
||||
transfer is used for slave.*/
|
||||
} dspi_transfer_t;
|
||||
|
||||
/*! @brief DSPI half-duplex(master) transfer structure */
|
||||
typedef struct _dspi_half_duplex_transfer
|
||||
{
|
||||
uint8_t *txData; /*!< Send buffer */
|
||||
uint8_t *rxData; /*!< Receive buffer */
|
||||
size_t txDataSize; /*!< Transfer bytes for transmit */
|
||||
size_t rxDataSize; /*!< Transfer bytes */
|
||||
uint32_t configFlags; /*!< Transfer configuration flags; set from _dspi_transfer_config_flag_for_master. */
|
||||
bool isPcsAssertInTransfer; /*!< If Pcs pin keep assert between transmit and receive. true for assert and false for
|
||||
deassert. */
|
||||
bool isTransmitFirst; /*!< True for transmit first and false for receive first. */
|
||||
} dspi_half_duplex_transfer_t;
|
||||
|
||||
/*! @brief DSPI master transfer handle structure used for transactional API. */
|
||||
struct _dspi_master_handle
|
||||
{
|
||||
|
@ -373,7 +363,7 @@ struct _dspi_master_handle
|
|||
|
||||
volatile bool
|
||||
isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/
|
||||
volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/
|
||||
volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/
|
||||
|
||||
uint8_t *volatile txData; /*!< Send buffer. */
|
||||
uint8_t *volatile rxData; /*!< Receive buffer. */
|
||||
|
@ -527,7 +517,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable)
|
|||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @name Status
|
||||
|
@ -565,7 +555,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags)
|
|||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @name Interrupts
|
||||
|
@ -605,7 +595,7 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
|
|||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @name DMA Control
|
||||
|
@ -685,12 +675,18 @@ static inline uint32_t DSPI_GetRxRegisterAddress(SPI_Type *base)
|
|||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @name Bus Operations
|
||||
* @{
|
||||
*/
|
||||
/*!
|
||||
* @brief Get instance number for DSPI module.
|
||||
*
|
||||
* @param base DSPI peripheral base address.
|
||||
*/
|
||||
uint32_t DSPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Configures the DSPI for master or slave.
|
||||
|
@ -711,7 +707,14 @@ static inline void DSPI_SetMasterSlaveMode(SPI_Type *base, dspi_master_slave_mod
|
|||
*/
|
||||
static inline bool DSPI_IsMaster(SPI_Type *base)
|
||||
{
|
||||
return (bool)((base->MCR) & SPI_MCR_MSTR_MASK);
|
||||
if (0U != ((base->MCR) & SPI_MCR_MSTR_MASK))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*!
|
||||
* @brief Starts the DSPI transfers and clears HALT bit in MCR.
|
||||
|
@ -749,8 +752,8 @@ static inline void DSPI_StopTransfer(SPI_Type *base)
|
|||
*/
|
||||
static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo)
|
||||
{
|
||||
base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | SPI_MCR_DIS_TXF(!enableTxFifo) |
|
||||
SPI_MCR_DIS_RXF(!enableRxFifo);
|
||||
base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) |
|
||||
SPI_MCR_DIS_TXF((false == enableTxFifo ? 1U : 0U)) | SPI_MCR_DIS_RXF((false == enableRxFifo ? 1U : 0U));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -762,8 +765,8 @@ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool en
|
|||
*/
|
||||
static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo)
|
||||
{
|
||||
base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | SPI_MCR_CLR_TXF(flushTxFifo) |
|
||||
SPI_MCR_CLR_RXF(flushRxFifo);
|
||||
base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) |
|
||||
SPI_MCR_CLR_TXF((true == flushTxFifo ? 1U : 0U)) | SPI_MCR_CLR_RXF((true == flushRxFifo ? 1U : 0U));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -954,11 +957,11 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t
|
|||
* buffer master mode and waits till complete to return.
|
||||
*
|
||||
* In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total
|
||||
* 32-bit word
|
||||
* 32-bit word
|
||||
* as the data to send.
|
||||
* The command portion provides characteristics of the data, such as the optional continuous chip select operation
|
||||
* between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the
|
||||
* desired PCS
|
||||
* desired PCS
|
||||
* signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the
|
||||
* transfer count (normally needed when sending the first frame of a data packet). The user is responsible for
|
||||
* appending this command with the data to send. This is an example:
|
||||
|
@ -973,20 +976,20 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t
|
|||
*
|
||||
* For a blocking polling transfer, see methods below.
|
||||
* Option 1:
|
||||
* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command);
|
||||
* uint32_t data0 = command_to_send | data_need_to_send_0;
|
||||
* uint32_t data1 = command_to_send | data_need_to_send_1;
|
||||
* uint32_t data2 = command_to_send | data_need_to_send_2;
|
||||
*
|
||||
* DSPI_MasterWriteCommandDataBlocking(base,data0);
|
||||
* DSPI_MasterWriteCommandDataBlocking(base,data1);
|
||||
* DSPI_MasterWriteCommandDataBlocking(base,data2);
|
||||
*
|
||||
* Option 2:
|
||||
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0);
|
||||
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1);
|
||||
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2);
|
||||
*
|
||||
* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command);
|
||||
* uint32_t data0 = command_to_send | data_need_to_send_0;
|
||||
* uint32_t data1 = command_to_send | data_need_to_send_1;
|
||||
* uint32_t data2 = command_to_send | data_need_to_send_2;
|
||||
*
|
||||
* DSPI_MasterWriteCommandDataBlocking(base,data0);
|
||||
* DSPI_MasterWriteCommandDataBlocking(base,data1);
|
||||
* DSPI_MasterWriteCommandDataBlocking(base,data2);
|
||||
*
|
||||
* Option 2:
|
||||
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0);
|
||||
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1);
|
||||
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2);
|
||||
*
|
||||
* @param base DSPI peripheral address.
|
||||
* @param data The data word (command and data combined) to be sent.
|
||||
*/
|
||||
|
@ -1037,7 +1040,7 @@ void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData);
|
|||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @name Transactional
|
||||
|
@ -1086,6 +1089,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer);
|
|||
*/
|
||||
status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer);
|
||||
|
||||
/*!
|
||||
* @brief Transfers a block of data using a polling method.
|
||||
*
|
||||
* This function will do a half-duplex transfer for DSPI master, This is a blocking function,
|
||||
* which does not retuen until all transfer have been completed. And data transfer will be half-duplex,
|
||||
* users can set transmit first or receive first.
|
||||
*
|
||||
* @param base DSPI base pointer
|
||||
* @param xfer pointer to dspi_half_duplex_transfer_t structure
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer);
|
||||
|
||||
/*!
|
||||
* @brief Performs a non-blocking DSPI interrupt transfer.
|
||||
*
|
||||
* This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking
|
||||
* function,
|
||||
* which returns right away. When all data is transferred, the callback function is called.
|
||||
*
|
||||
* @param base DSPI peripheral base address.
|
||||
* @param handle pointer to dspi_master_handle_t structure which stores the transfer state
|
||||
* @param xfer pointer to dspi_half_duplex_transfer_t structure
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base,
|
||||
dspi_master_handle_t *handle,
|
||||
dspi_half_duplex_transfer_t *xfer);
|
||||
|
||||
/*!
|
||||
* @brief Gets the master transfer count.
|
||||
*
|
||||
|
@ -1179,15 +1211,25 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle);
|
|||
*/
|
||||
void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* brief Dummy data for each instance.
|
||||
*
|
||||
* The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of
|
||||
* externally-linked object or function g_dspiDummyData.
|
||||
*
|
||||
* param base DSPI peripheral base address.
|
||||
*/
|
||||
uint8_t DSPI_GetDummyDataInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /*_cplusplus*/
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
#endif /*_FSL_DSPI_H_*/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* Copyright 2016-2018 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_DSPI_EDMA_H_
|
||||
#define _FSL_DSPI_EDMA_H_
|
||||
|
@ -41,14 +19,20 @@
|
|||
* Definitions
|
||||
**********************************************************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief DSPI EDMA driver version 2.2.2. */
|
||||
#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 2))
|
||||
/*@}*/
|
||||
|
||||
/*!
|
||||
* @brief Forward declaration of the DSPI eDMA master handle typedefs.
|
||||
*/
|
||||
* @brief Forward declaration of the DSPI eDMA master handle typedefs.
|
||||
*/
|
||||
typedef struct _dspi_master_edma_handle dspi_master_edma_handle_t;
|
||||
|
||||
/*!
|
||||
* @brief Forward declaration of the DSPI eDMA slave handle typedefs.
|
||||
*/
|
||||
* @brief Forward declaration of the DSPI eDMA slave handle typedefs.
|
||||
*/
|
||||
typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t;
|
||||
|
||||
/*!
|
||||
|
@ -186,6 +170,21 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base,
|
|||
*/
|
||||
status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer);
|
||||
|
||||
/*!
|
||||
* @brief Transfers a block of data using a eDMA method.
|
||||
*
|
||||
* This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function,
|
||||
* which returns right away. When all data is transferred, the callback function is called.
|
||||
*
|
||||
* @param base DSPI base pointer
|
||||
* @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
|
||||
* @param transfer A pointer to the dspi_half_duplex_transfer_t structure.
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base,
|
||||
dspi_master_edma_handle_t *handle,
|
||||
dspi_half_duplex_transfer_t *xfer);
|
||||
|
||||
/*!
|
||||
* @brief DSPI master aborts a transfer which is using eDMA.
|
||||
*
|
||||
|
|
|
@ -1,94 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_smc.h"
|
||||
#include "fsl_flash.h"
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.smc"
|
||||
#endif
|
||||
|
||||
typedef void (*smc_stop_ram_func_t)(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
static void SMC_EnterStopRamFunc(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
static uint32_t g_savedPrimask;
|
||||
|
||||
/*
|
||||
* The ram function code is:
|
||||
*
|
||||
* uint32_t i;
|
||||
* for (i=0; i<0x8; i++)
|
||||
* {
|
||||
* __NOP();
|
||||
* }
|
||||
* __DSB();
|
||||
* __WFI();
|
||||
* __ISB();
|
||||
*
|
||||
* When entring the stop modes, the flash prefetch might be interrupted, thus
|
||||
* the prefetched code or data might be broken. To make sure the flash is idle
|
||||
* when entring the stop modes, the code is moved to ram. And delay for a while
|
||||
* before WFI to make sure previous flash prefetch is finished.
|
||||
*
|
||||
* Only need to do like this when code is in flash, if code is in rom or ram,
|
||||
* this is not necessary.
|
||||
*/
|
||||
static uint16_t s_stopRamFuncArray[] = {
|
||||
0x2000, /* MOVS R0, #0 */
|
||||
0x2808, /* CMP R0, #8 */
|
||||
0xD202, /* BCS.N */
|
||||
0xBF00, /* NOP */
|
||||
0x1C40, /* ADDS R0, R0, #1 */
|
||||
0xE7FA, /* B.N */
|
||||
0xF3BF, 0x8F4F, /* DSB */
|
||||
0xBF30, /* WFI */
|
||||
0xF3BF, 0x8F6F, /* ISB */
|
||||
0x4770, /* BX LR */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static void SMC_EnterStopRamFunc(void)
|
||||
{
|
||||
uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U;
|
||||
smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry;
|
||||
stopRamFunc();
|
||||
}
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM)
|
||||
/*!
|
||||
* brief Gets the SMC parameter.
|
||||
*
|
||||
* This function gets the SMC parameter including the enabled power mdoes.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* param param Pointer to the SMC param structure.
|
||||
*/
|
||||
void SMC_GetParam(SMC_Type *base, smc_param_t *param)
|
||||
{
|
||||
uint32_t reg = base->PARAM;
|
||||
uint32_t reg = base->PARAM;
|
||||
param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK);
|
||||
param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK);
|
||||
param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK);
|
||||
param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK);
|
||||
param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK);
|
||||
param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK);
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_PARAM */
|
||||
|
||||
/*!
|
||||
* brief Prepares to enter stop modes.
|
||||
*
|
||||
* This function should be called before entering STOP/VLPS/LLS/VLLS modes.
|
||||
*/
|
||||
void SMC_PreEnterStopModes(void)
|
||||
{
|
||||
flash_prefetch_speculation_status_t speculationStatus =
|
||||
{
|
||||
kFLASH_prefetchSpeculationOptionDisable, /* Disable instruction speculation.*/
|
||||
kFLASH_prefetchSpeculationOptionDisable, /* Disable data speculation.*/
|
||||
};
|
||||
|
||||
__disable_irq();
|
||||
g_savedPrimask = DisableGlobalIRQ();
|
||||
__ISB();
|
||||
|
||||
/*
|
||||
* Before enter stop modes, the flash cache prefetch should be disabled.
|
||||
* Otherwise the prefetch might be interrupted by stop, then the data and
|
||||
* and instruction from flash are wrong.
|
||||
*/
|
||||
FLASH_PflashSetPrefetchSpeculation(&speculationStatus);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Recovers after wake up from stop modes.
|
||||
*
|
||||
* This function should be called after wake up from STOP/VLPS/LLS/VLLS modes.
|
||||
* It is used with ref SMC_PreEnterStopModes.
|
||||
*/
|
||||
void SMC_PostExitStopModes(void)
|
||||
{
|
||||
flash_prefetch_speculation_status_t speculationStatus =
|
||||
{
|
||||
kFLASH_prefetchSpeculationOptionEnable, /* Enable instruction speculation.*/
|
||||
kFLASH_prefetchSpeculationOptionEnable, /* Enable data speculation.*/
|
||||
};
|
||||
|
||||
FLASH_PflashSetPrefetchSpeculation(&speculationStatus);
|
||||
|
||||
__enable_irq();
|
||||
EnableGlobalIRQ(g_savedPrimask);
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Prepares to enter wait modes.
|
||||
*
|
||||
* This function should be called before entering WAIT/VLPW modes.
|
||||
*/
|
||||
void SMC_PreEnterWaitModes(void)
|
||||
{
|
||||
g_savedPrimask = DisableGlobalIRQ();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Recovers after wake up from stop modes.
|
||||
*
|
||||
* This function should be called after wake up from WAIT/VLPW modes.
|
||||
* It is used with ref SMC_PreEnterWaitModes.
|
||||
*/
|
||||
void SMC_PostExitWaitModes(void)
|
||||
{
|
||||
EnableGlobalIRQ(g_savedPrimask);
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to RUN power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeRun(SMC_Type *base)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
reg = base->PMCTRL;
|
||||
/* configure Normal RUN mode */
|
||||
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
/*!
|
||||
* brief Configures the system to HSRUN power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeHsrun(SMC_Type *base)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
@ -96,13 +170,19 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base)
|
|||
reg = base->PMCTRL;
|
||||
/* configure High Speed RUN mode */
|
||||
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
|
||||
reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
|
||||
/*!
|
||||
* brief Configures the system to WAIT power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeWait(SMC_Type *base)
|
||||
{
|
||||
/* configure Normal Wait mode */
|
||||
|
@ -114,22 +194,29 @@ status_t SMC_SetPowerModeWait(SMC_Type *base)
|
|||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to Stop power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* param option Partial Stop mode option.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO)
|
||||
/* configure the Partial Stop mode in Noraml Stop mode */
|
||||
/* configure the Partial Stop mode in Normal Stop mode */
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_PSTOPO_MASK;
|
||||
reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK;
|
||||
reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#endif
|
||||
|
||||
/* configure Normal Stop mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */
|
||||
|
@ -137,12 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter Stop mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
@ -152,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to VLPR power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlpr(SMC_Type *base
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)
|
||||
,
|
||||
bool wakeupMode
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
|
@ -172,18 +263,24 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base
|
|||
else
|
||||
{
|
||||
/* remains in VLP mode on an interrupt */
|
||||
reg &= ~SMC_PMCTRL_LPWUI_MASK;
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK;
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LPWUI */
|
||||
|
||||
/* configure VLPR mode */
|
||||
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to VLPW power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlpw(SMC_Type *base)
|
||||
{
|
||||
/* configure VLPW mode */
|
||||
|
@ -196,14 +293,20 @@ status_t SMC_SetPowerModeVlpw(SMC_Type *base)
|
|||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to VLPS power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
/* configure VLPS mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* Set the SLEEPDEEP bit to enable deep sleep mode */
|
||||
|
@ -211,12 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter VLPS mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
@ -227,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
|||
}
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
/*!
|
||||
* brief Configures the system to LLS power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeLls(SMC_Type *base
|
||||
#if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \
|
||||
(defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO))
|
||||
,
|
||||
const smc_power_mode_lls_config_t *config
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
/* configure to LLS mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* configure LLS sub-mode*/
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
|
||||
|
||||
|
@ -267,12 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter LLS mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
@ -284,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base
|
|||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
/*!
|
||||
* brief Configures the system to VLLS power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* param config The VLLS power mode configuration structure.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
@ -296,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
#endif
|
||||
{
|
||||
/* configure whether the Por Detect work in Vlls0 mode */
|
||||
if (config->enablePorDetectInVlls0)
|
||||
if (true == config->enablePorDetectInVlls0)
|
||||
{
|
||||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK;
|
||||
#else
|
||||
base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK;
|
||||
base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -319,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
else if (config->subMode == kSMC_StopSub2)
|
||||
{
|
||||
/* configure whether the Por Detect work in Vlls0 mode */
|
||||
if (config->enableRam2InVlls2)
|
||||
if (true == config->enableRam2InVlls2)
|
||||
{
|
||||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK;
|
||||
|
@ -332,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK;
|
||||
#else
|
||||
base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK;
|
||||
base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */
|
||||
|
||||
/* configure to VLLS mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* configure the VLLS sub-mode */
|
||||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
reg = base->VLLSCTRL;
|
||||
reg &= ~SMC_VLLSCTRL_VLLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT);
|
||||
reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT);
|
||||
base->VLLSCTRL = reg;
|
||||
#else
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#else
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_VLLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT);
|
||||
reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
|
||||
#endif
|
||||
|
@ -383,12 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter LLS mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef _FSL_SMC_H_
|
||||
|
@ -36,15 +14,14 @@
|
|||
/*! @addtogroup smc */
|
||||
/*! @{ */
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SMC driver version 2.0.3. */
|
||||
#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 3))
|
||||
/*! @brief SMC driver version 2.0.5. */
|
||||
#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5))
|
||||
/*@}*/
|
||||
|
||||
/*!
|
||||
|
@ -64,18 +41,14 @@ typedef enum _smc_power_mode_protection
|
|||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
kSMC_AllowPowerModeAll = (0U
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
|
|
||||
SMC_PMPROT_AVLLS_MASK
|
||||
| SMC_PMPROT_AVLLS_MASK
|
||||
#endif
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
|
|
||||
SMC_PMPROT_ALLS_MASK
|
||||
| SMC_PMPROT_ALLS_MASK
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
|
|
||||
SMC_PMPROT_AVLP_MASK
|
||||
| SMC_PMPROT_AVLP_MASK
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
|
|
||||
kSMC_AllowPowerModeHsrun
|
||||
| kSMC_AllowPowerModeHsrun
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
) /*!< Allow all power mode. */
|
||||
} smc_power_mode_protection_t;
|
||||
|
@ -85,7 +58,7 @@ typedef enum _smc_power_mode_protection
|
|||
*/
|
||||
typedef enum _smc_power_state
|
||||
{
|
||||
kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */
|
||||
kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */
|
||||
kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */
|
||||
kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */
|
||||
kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */
|
||||
|
@ -107,7 +80,7 @@ typedef enum _smc_power_state
|
|||
typedef enum _smc_run_mode
|
||||
{
|
||||
kSMC_RunNormal = 0U, /*!< Normal RUN mode. */
|
||||
kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */
|
||||
kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
|
@ -119,7 +92,7 @@ typedef enum _smc_run_mode
|
|||
typedef enum _smc_stop_mode
|
||||
{
|
||||
kSMC_StopNormal = 0U, /*!< Normal STOP mode. */
|
||||
kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */
|
||||
kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
|
@ -148,7 +121,7 @@ typedef enum _smc_stop_submode
|
|||
*/
|
||||
typedef enum _smc_partial_stop_mode
|
||||
{
|
||||
kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/
|
||||
kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/
|
||||
kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/
|
||||
kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/
|
||||
} smc_partial_stop_option_t;
|
||||
|
@ -324,11 +297,7 @@ void SMC_PostExitStopModes(void);
|
|||
*
|
||||
* This function should be called before entering WAIT/VLPW modes.
|
||||
*/
|
||||
static inline void SMC_PreEnterWaitModes(void)
|
||||
{
|
||||
__disable_irq();
|
||||
__ISB();
|
||||
}
|
||||
void SMC_PreEnterWaitModes(void);
|
||||
|
||||
/*!
|
||||
* @brief Recovers after wake up from stop modes.
|
||||
|
@ -336,11 +305,7 @@ static inline void SMC_PreEnterWaitModes(void)
|
|||
* This function should be called after wake up from WAIT/VLPW modes.
|
||||
* It is used with @ref SMC_PreEnterWaitModes.
|
||||
*/
|
||||
static inline void SMC_PostExitWaitModes(void)
|
||||
{
|
||||
__enable_irq();
|
||||
__ISB();
|
||||
}
|
||||
void SMC_PostExitWaitModes(void);
|
||||
|
||||
/*!
|
||||
* @brief Configures the system to RUN power mode.
|
||||
|
|
|
@ -340,4 +340,14 @@ const PinMap *serial_rts_pinmap()
|
|||
return PinMap_UART_RTS;
|
||||
}
|
||||
|
||||
void serial_wait_tx_complete(uint32_t uart_index)
|
||||
{
|
||||
UART_Type *base = uart_addrs[uart_index];
|
||||
|
||||
/* Wait till data is flushed out of transmit buffer */
|
||||
while (!(kUART_TransmissionCompleteFlag & UART_GetStatusFlags((UART_Type *)base)))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2019 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_DSPI_H_
|
||||
#define _FSL_DSPI_H_
|
||||
|
@ -37,15 +15,14 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**********************************************************************************************************************
|
||||
* Definitions
|
||||
*********************************************************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief DSPI driver version 2.1.3. */
|
||||
#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 3))
|
||||
/*! @brief DSPI driver version 2.2.2. */
|
||||
#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 2))
|
||||
/*@}*/
|
||||
|
||||
#ifndef DSPI_DUMMY_DATA
|
||||
|
@ -56,37 +33,37 @@
|
|||
/*! @brief Status for the DSPI driver.*/
|
||||
enum _dspi_status
|
||||
{
|
||||
kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/
|
||||
kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */
|
||||
kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/
|
||||
kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */
|
||||
kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/
|
||||
kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */
|
||||
kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/
|
||||
kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */
|
||||
};
|
||||
|
||||
/*! @brief DSPI status flags in SPIx_SR register.*/
|
||||
enum _dspi_flags
|
||||
{
|
||||
kDSPI_TxCompleteFlag = SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */
|
||||
kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/
|
||||
kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/
|
||||
kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/
|
||||
kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/
|
||||
kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/
|
||||
kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/
|
||||
kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK |
|
||||
SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All statuses above.*/
|
||||
kDSPI_TxCompleteFlag = (int)SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */
|
||||
kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/
|
||||
kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/
|
||||
kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/
|
||||
kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/
|
||||
kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/
|
||||
kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/
|
||||
kDSPI_AllStatusFlag = (int)(SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK |
|
||||
SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK) /*!< All statuses above.*/
|
||||
};
|
||||
|
||||
/*! @brief DSPI interrupt source.*/
|
||||
enum _dspi_interrupt_enable
|
||||
{
|
||||
kDSPI_TxCompleteInterruptEnable = SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/
|
||||
kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/
|
||||
kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/
|
||||
kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/
|
||||
kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/
|
||||
kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/
|
||||
kDSPI_AllInterruptEnable = SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK |
|
||||
SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK
|
||||
kDSPI_TxCompleteInterruptEnable = (int)SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/
|
||||
kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/
|
||||
kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/
|
||||
kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/
|
||||
kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/
|
||||
kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/
|
||||
kDSPI_AllInterruptEnable = (int)(SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK |
|
||||
SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK)
|
||||
/*!< All above interrupts enable.*/
|
||||
};
|
||||
|
||||
|
@ -103,11 +80,12 @@ enum _dspi_dma_enable
|
|||
typedef enum _dspi_master_slave_mode
|
||||
{
|
||||
kDSPI_Master = 1U, /*!< DSPI peripheral operates in master mode.*/
|
||||
kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/
|
||||
kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/
|
||||
} dspi_master_slave_mode_t;
|
||||
|
||||
/*!
|
||||
* @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is valid
|
||||
* @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is
|
||||
* valid
|
||||
* only when the CPHA bit in the CTAR register is 0.
|
||||
*/
|
||||
typedef enum _dspi_master_sample_point
|
||||
|
@ -132,26 +110,26 @@ typedef enum _dspi_which_pcs_config
|
|||
typedef enum _dspi_pcs_polarity_config
|
||||
{
|
||||
kDSPI_PcsActiveHigh = 0U, /*!< Pcs Active High (idles low). */
|
||||
kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */
|
||||
kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */
|
||||
} dspi_pcs_polarity_config_t;
|
||||
|
||||
/*! @brief DSPI Peripheral Chip Select (Pcs) Polarity.*/
|
||||
enum _dspi_pcs_polarity
|
||||
{
|
||||
kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */
|
||||
kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */
|
||||
kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */
|
||||
kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */
|
||||
kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */
|
||||
kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */
|
||||
kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */
|
||||
kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */
|
||||
kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */
|
||||
kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */
|
||||
kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */
|
||||
kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */
|
||||
kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */
|
||||
kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */
|
||||
};
|
||||
|
||||
/*! @brief DSPI clock polarity configuration for a given CTAR.*/
|
||||
typedef enum _dspi_clock_polarity
|
||||
{
|
||||
kDSPI_ClockPolarityActiveHigh = 0U, /*!< CPOL=0. Active-high DSPI clock (idles low).*/
|
||||
kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/
|
||||
kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/
|
||||
} dspi_clock_polarity_t;
|
||||
|
||||
/*! @brief DSPI clock phase configuration for a given CTAR.*/
|
||||
|
@ -216,8 +194,9 @@ enum _dspi_transfer_config_flag_for_master
|
|||
kDSPI_MasterPcs4 = 4U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS4 signal. */
|
||||
kDSPI_MasterPcs5 = 5U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS5 signal. */
|
||||
|
||||
kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */
|
||||
kDSPI_MasterActiveAfterTransfer = 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/
|
||||
kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */
|
||||
kDSPI_MasterActiveAfterTransfer =
|
||||
1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/
|
||||
};
|
||||
|
||||
#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro; used internally. */
|
||||
|
@ -240,7 +219,7 @@ enum _dspi_transfer_state
|
|||
/*! @brief DSPI master command date configuration used for the SPIx_PUSHR.*/
|
||||
typedef struct _dspi_command_data_config
|
||||
{
|
||||
bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/
|
||||
bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/
|
||||
dspi_ctar_selection_t whichCtar; /*!< The desired Clock and Transfer Attributes
|
||||
Register (CTAR) to use for CTAS.*/
|
||||
dspi_which_pcs_t whichPcs; /*!< The desired PCS signal to use for the data transfer.*/
|
||||
|
@ -257,10 +236,10 @@ typedef struct _dspi_master_ctar_config
|
|||
dspi_clock_phase_t cpha; /*!< Clock phase. */
|
||||
dspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */
|
||||
|
||||
uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum
|
||||
delay. It also sets the boundary value if out of range.*/
|
||||
uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the
|
||||
minimum delay. It also sets the boundary value if out of range.*/
|
||||
uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum
|
||||
delay. It also sets the boundary value if out of range.*/
|
||||
uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the
|
||||
minimum delay. It also sets the boundary value if out of range.*/
|
||||
|
||||
uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time in nanoseconds; setting to 0 sets the minimum
|
||||
delay. It also sets the boundary value if out of range.*/
|
||||
|
@ -314,13 +293,13 @@ typedef struct _dspi_slave_config
|
|||
} dspi_slave_config_t;
|
||||
|
||||
/*!
|
||||
* @brief Forward declaration of the _dspi_master_handle typedefs.
|
||||
*/
|
||||
* @brief Forward declaration of the _dspi_master_handle typedefs.
|
||||
*/
|
||||
typedef struct _dspi_master_handle dspi_master_handle_t;
|
||||
|
||||
/*!
|
||||
* @brief Forward declaration of the _dspi_slave_handle typedefs.
|
||||
*/
|
||||
* @brief Forward declaration of the _dspi_slave_handle typedefs.
|
||||
*/
|
||||
typedef struct _dspi_slave_handle dspi_slave_handle_t;
|
||||
|
||||
/*!
|
||||
|
@ -355,12 +334,24 @@ typedef struct _dspi_transfer
|
|||
uint8_t *rxData; /*!< Receive buffer. */
|
||||
volatile size_t dataSize; /*!< Transfer bytes. */
|
||||
|
||||
uint32_t
|
||||
configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if the
|
||||
transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer
|
||||
is used for slave.*/
|
||||
uint32_t configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if
|
||||
the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the
|
||||
transfer is used for slave.*/
|
||||
} dspi_transfer_t;
|
||||
|
||||
/*! @brief DSPI half-duplex(master) transfer structure */
|
||||
typedef struct _dspi_half_duplex_transfer
|
||||
{
|
||||
uint8_t *txData; /*!< Send buffer */
|
||||
uint8_t *rxData; /*!< Receive buffer */
|
||||
size_t txDataSize; /*!< Transfer bytes for transmit */
|
||||
size_t rxDataSize; /*!< Transfer bytes */
|
||||
uint32_t configFlags; /*!< Transfer configuration flags; set from _dspi_transfer_config_flag_for_master. */
|
||||
bool isPcsAssertInTransfer; /*!< If Pcs pin keep assert between transmit and receive. true for assert and false for
|
||||
deassert. */
|
||||
bool isTransmitFirst; /*!< True for transmit first and false for receive first. */
|
||||
} dspi_half_duplex_transfer_t;
|
||||
|
||||
/*! @brief DSPI master transfer handle structure used for transactional API. */
|
||||
struct _dspi_master_handle
|
||||
{
|
||||
|
@ -370,8 +361,9 @@ struct _dspi_master_handle
|
|||
|
||||
uint8_t fifoSize; /*!< FIFO dataSize. */
|
||||
|
||||
volatile bool isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/
|
||||
volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/
|
||||
volatile bool
|
||||
isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/
|
||||
volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/
|
||||
|
||||
uint8_t *volatile txData; /*!< Send buffer. */
|
||||
uint8_t *volatile rxData; /*!< Receive buffer. */
|
||||
|
@ -525,7 +517,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable)
|
|||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @name Status
|
||||
|
@ -563,7 +555,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags)
|
|||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @name Interrupts
|
||||
|
@ -575,6 +567,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags)
|
|||
*
|
||||
* This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask.
|
||||
* Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request.
|
||||
* Do not use this API(write to RSER register) while DSPI is in running state.
|
||||
*
|
||||
* @code
|
||||
* DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable );
|
||||
|
@ -602,7 +595,7 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
|
|||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @name DMA Control
|
||||
|
@ -682,12 +675,18 @@ static inline uint32_t DSPI_GetRxRegisterAddress(SPI_Type *base)
|
|||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @name Bus Operations
|
||||
* @{
|
||||
*/
|
||||
/*!
|
||||
* @brief Get instance number for DSPI module.
|
||||
*
|
||||
* @param base DSPI peripheral base address.
|
||||
*/
|
||||
uint32_t DSPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Configures the DSPI for master or slave.
|
||||
|
@ -708,7 +707,14 @@ static inline void DSPI_SetMasterSlaveMode(SPI_Type *base, dspi_master_slave_mod
|
|||
*/
|
||||
static inline bool DSPI_IsMaster(SPI_Type *base)
|
||||
{
|
||||
return (bool)((base->MCR) & SPI_MCR_MSTR_MASK);
|
||||
if (0U != ((base->MCR) & SPI_MCR_MSTR_MASK))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*!
|
||||
* @brief Starts the DSPI transfers and clears HALT bit in MCR.
|
||||
|
@ -746,8 +752,8 @@ static inline void DSPI_StopTransfer(SPI_Type *base)
|
|||
*/
|
||||
static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo)
|
||||
{
|
||||
base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | SPI_MCR_DIS_TXF(!enableTxFifo) |
|
||||
SPI_MCR_DIS_RXF(!enableRxFifo);
|
||||
base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) |
|
||||
SPI_MCR_DIS_TXF((false == enableTxFifo ? 1U : 0U)) | SPI_MCR_DIS_RXF((false == enableRxFifo ? 1U : 0U));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -759,8 +765,8 @@ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool en
|
|||
*/
|
||||
static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo)
|
||||
{
|
||||
base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | SPI_MCR_CLR_TXF(flushTxFifo) |
|
||||
SPI_MCR_CLR_RXF(flushRxFifo);
|
||||
base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) |
|
||||
SPI_MCR_CLR_TXF((true == flushTxFifo ? 1U : 0U)) | SPI_MCR_CLR_RXF((true == flushRxFifo ? 1U : 0U));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -950,10 +956,12 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t
|
|||
* @brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data
|
||||
* buffer master mode and waits till complete to return.
|
||||
*
|
||||
* In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total 32-bit word
|
||||
* In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total
|
||||
* 32-bit word
|
||||
* as the data to send.
|
||||
* The command portion provides characteristics of the data, such as the optional continuous chip select operation
|
||||
* between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the desired PCS
|
||||
* between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the
|
||||
* desired PCS
|
||||
* signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the
|
||||
* transfer count (normally needed when sending the first frame of a data packet). The user is responsible for
|
||||
* appending this command with the data to send. This is an example:
|
||||
|
@ -968,20 +976,20 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t
|
|||
*
|
||||
* For a blocking polling transfer, see methods below.
|
||||
* Option 1:
|
||||
* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command);
|
||||
* uint32_t data0 = command_to_send | data_need_to_send_0;
|
||||
* uint32_t data1 = command_to_send | data_need_to_send_1;
|
||||
* uint32_t data2 = command_to_send | data_need_to_send_2;
|
||||
*
|
||||
* DSPI_MasterWriteCommandDataBlocking(base,data0);
|
||||
* DSPI_MasterWriteCommandDataBlocking(base,data1);
|
||||
* DSPI_MasterWriteCommandDataBlocking(base,data2);
|
||||
*
|
||||
* Option 2:
|
||||
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0);
|
||||
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1);
|
||||
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2);
|
||||
*
|
||||
* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command);
|
||||
* uint32_t data0 = command_to_send | data_need_to_send_0;
|
||||
* uint32_t data1 = command_to_send | data_need_to_send_1;
|
||||
* uint32_t data2 = command_to_send | data_need_to_send_2;
|
||||
*
|
||||
* DSPI_MasterWriteCommandDataBlocking(base,data0);
|
||||
* DSPI_MasterWriteCommandDataBlocking(base,data1);
|
||||
* DSPI_MasterWriteCommandDataBlocking(base,data2);
|
||||
*
|
||||
* Option 2:
|
||||
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0);
|
||||
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1);
|
||||
* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2);
|
||||
*
|
||||
* @param base DSPI peripheral address.
|
||||
* @param data The data word (command and data combined) to be sent.
|
||||
*/
|
||||
|
@ -1022,9 +1030,17 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base)
|
|||
return (base->POPR);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set up the dummy data.
|
||||
*
|
||||
* @param base DSPI peripheral address.
|
||||
* @param dummyData Data to be transferred when tx buffer is NULL.
|
||||
*/
|
||||
void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData);
|
||||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @name Transactional
|
||||
|
@ -1073,6 +1089,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer);
|
|||
*/
|
||||
status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer);
|
||||
|
||||
/*!
|
||||
* @brief Transfers a block of data using a polling method.
|
||||
*
|
||||
* This function will do a half-duplex transfer for DSPI master, This is a blocking function,
|
||||
* which does not retuen until all transfer have been completed. And data transfer will be half-duplex,
|
||||
* users can set transmit first or receive first.
|
||||
*
|
||||
* @param base DSPI base pointer
|
||||
* @param xfer pointer to dspi_half_duplex_transfer_t structure
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer);
|
||||
|
||||
/*!
|
||||
* @brief Performs a non-blocking DSPI interrupt transfer.
|
||||
*
|
||||
* This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking
|
||||
* function,
|
||||
* which returns right away. When all data is transferred, the callback function is called.
|
||||
*
|
||||
* @param base DSPI peripheral base address.
|
||||
* @param handle pointer to dspi_master_handle_t structure which stores the transfer state
|
||||
* @param xfer pointer to dspi_half_duplex_transfer_t structure
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base,
|
||||
dspi_master_handle_t *handle,
|
||||
dspi_half_duplex_transfer_t *xfer);
|
||||
|
||||
/*!
|
||||
* @brief Gets the master transfer count.
|
||||
*
|
||||
|
@ -1166,15 +1211,25 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle);
|
|||
*/
|
||||
void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* brief Dummy data for each instance.
|
||||
*
|
||||
* The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of
|
||||
* externally-linked object or function g_dspiDummyData.
|
||||
*
|
||||
* param base DSPI peripheral base address.
|
||||
*/
|
||||
uint8_t DSPI_GetDummyDataInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /*_cplusplus*/
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
*/
|
||||
|
||||
#endif /*_FSL_DSPI_H_*/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2018 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_DSPI_EDMA_H_
|
||||
#define _FSL_DSPI_EDMA_H_
|
||||
|
@ -41,14 +19,20 @@
|
|||
* Definitions
|
||||
**********************************************************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief DSPI EDMA driver version 2.2.2. */
|
||||
#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 2))
|
||||
/*@}*/
|
||||
|
||||
/*!
|
||||
* @brief Forward declaration of the DSPI eDMA master handle typedefs.
|
||||
*/
|
||||
* @brief Forward declaration of the DSPI eDMA master handle typedefs.
|
||||
*/
|
||||
typedef struct _dspi_master_edma_handle dspi_master_edma_handle_t;
|
||||
|
||||
/*!
|
||||
* @brief Forward declaration of the DSPI eDMA slave handle typedefs.
|
||||
*/
|
||||
* @brief Forward declaration of the DSPI eDMA slave handle typedefs.
|
||||
*/
|
||||
typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t;
|
||||
|
||||
/*!
|
||||
|
@ -186,6 +170,21 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base,
|
|||
*/
|
||||
status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer);
|
||||
|
||||
/*!
|
||||
* @brief Transfers a block of data using a eDMA method.
|
||||
*
|
||||
* This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function,
|
||||
* which returns right away. When all data is transferred, the callback function is called.
|
||||
*
|
||||
* @param base DSPI base pointer
|
||||
* @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
|
||||
* @param transfer A pointer to the dspi_half_duplex_transfer_t structure.
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base,
|
||||
dspi_master_edma_handle_t *handle,
|
||||
dspi_half_duplex_transfer_t *xfer);
|
||||
|
||||
/*!
|
||||
* @brief DSPI master aborts a transfer which is using eDMA.
|
||||
*
|
||||
|
|
|
@ -1,94 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_smc.h"
|
||||
#include "fsl_flash.h"
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.smc"
|
||||
#endif
|
||||
|
||||
typedef void (*smc_stop_ram_func_t)(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
static void SMC_EnterStopRamFunc(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
static uint32_t g_savedPrimask;
|
||||
|
||||
/*
|
||||
* The ram function code is:
|
||||
*
|
||||
* uint32_t i;
|
||||
* for (i=0; i<0x8; i++)
|
||||
* {
|
||||
* __NOP();
|
||||
* }
|
||||
* __DSB();
|
||||
* __WFI();
|
||||
* __ISB();
|
||||
*
|
||||
* When entring the stop modes, the flash prefetch might be interrupted, thus
|
||||
* the prefetched code or data might be broken. To make sure the flash is idle
|
||||
* when entring the stop modes, the code is moved to ram. And delay for a while
|
||||
* before WFI to make sure previous flash prefetch is finished.
|
||||
*
|
||||
* Only need to do like this when code is in flash, if code is in rom or ram,
|
||||
* this is not necessary.
|
||||
*/
|
||||
static uint16_t s_stopRamFuncArray[] = {
|
||||
0x2000, /* MOVS R0, #0 */
|
||||
0x2808, /* CMP R0, #8 */
|
||||
0xD202, /* BCS.N */
|
||||
0xBF00, /* NOP */
|
||||
0x1C40, /* ADDS R0, R0, #1 */
|
||||
0xE7FA, /* B.N */
|
||||
0xF3BF, 0x8F4F, /* DSB */
|
||||
0xBF30, /* WFI */
|
||||
0xF3BF, 0x8F6F, /* ISB */
|
||||
0x4770, /* BX LR */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static void SMC_EnterStopRamFunc(void)
|
||||
{
|
||||
uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U;
|
||||
smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry;
|
||||
stopRamFunc();
|
||||
}
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM)
|
||||
/*!
|
||||
* brief Gets the SMC parameter.
|
||||
*
|
||||
* This function gets the SMC parameter including the enabled power mdoes.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* param param Pointer to the SMC param structure.
|
||||
*/
|
||||
void SMC_GetParam(SMC_Type *base, smc_param_t *param)
|
||||
{
|
||||
uint32_t reg = base->PARAM;
|
||||
uint32_t reg = base->PARAM;
|
||||
param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK);
|
||||
param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK);
|
||||
param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK);
|
||||
param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK);
|
||||
param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK);
|
||||
param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK);
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_PARAM */
|
||||
|
||||
/*!
|
||||
* brief Prepares to enter stop modes.
|
||||
*
|
||||
* This function should be called before entering STOP/VLPS/LLS/VLLS modes.
|
||||
*/
|
||||
void SMC_PreEnterStopModes(void)
|
||||
{
|
||||
flash_prefetch_speculation_status_t speculationStatus =
|
||||
{
|
||||
kFLASH_prefetchSpeculationOptionDisable, /* Disable instruction speculation.*/
|
||||
kFLASH_prefetchSpeculationOptionDisable, /* Disable data speculation.*/
|
||||
};
|
||||
|
||||
__disable_irq();
|
||||
g_savedPrimask = DisableGlobalIRQ();
|
||||
__ISB();
|
||||
|
||||
/*
|
||||
* Before enter stop modes, the flash cache prefetch should be disabled.
|
||||
* Otherwise the prefetch might be interrupted by stop, then the data and
|
||||
* and instruction from flash are wrong.
|
||||
*/
|
||||
FLASH_PflashSetPrefetchSpeculation(&speculationStatus);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Recovers after wake up from stop modes.
|
||||
*
|
||||
* This function should be called after wake up from STOP/VLPS/LLS/VLLS modes.
|
||||
* It is used with ref SMC_PreEnterStopModes.
|
||||
*/
|
||||
void SMC_PostExitStopModes(void)
|
||||
{
|
||||
flash_prefetch_speculation_status_t speculationStatus =
|
||||
{
|
||||
kFLASH_prefetchSpeculationOptionEnable, /* Enable instruction speculation.*/
|
||||
kFLASH_prefetchSpeculationOptionEnable, /* Enable data speculation.*/
|
||||
};
|
||||
|
||||
FLASH_PflashSetPrefetchSpeculation(&speculationStatus);
|
||||
|
||||
__enable_irq();
|
||||
EnableGlobalIRQ(g_savedPrimask);
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Prepares to enter wait modes.
|
||||
*
|
||||
* This function should be called before entering WAIT/VLPW modes.
|
||||
*/
|
||||
void SMC_PreEnterWaitModes(void)
|
||||
{
|
||||
g_savedPrimask = DisableGlobalIRQ();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Recovers after wake up from stop modes.
|
||||
*
|
||||
* This function should be called after wake up from WAIT/VLPW modes.
|
||||
* It is used with ref SMC_PreEnterWaitModes.
|
||||
*/
|
||||
void SMC_PostExitWaitModes(void)
|
||||
{
|
||||
EnableGlobalIRQ(g_savedPrimask);
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to RUN power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeRun(SMC_Type *base)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
reg = base->PMCTRL;
|
||||
/* configure Normal RUN mode */
|
||||
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
/*!
|
||||
* brief Configures the system to HSRUN power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeHsrun(SMC_Type *base)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
@ -96,13 +170,19 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base)
|
|||
reg = base->PMCTRL;
|
||||
/* configure High Speed RUN mode */
|
||||
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
|
||||
reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
|
||||
/*!
|
||||
* brief Configures the system to WAIT power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeWait(SMC_Type *base)
|
||||
{
|
||||
/* configure Normal Wait mode */
|
||||
|
@ -114,22 +194,29 @@ status_t SMC_SetPowerModeWait(SMC_Type *base)
|
|||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to Stop power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* param option Partial Stop mode option.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO)
|
||||
/* configure the Partial Stop mode in Noraml Stop mode */
|
||||
/* configure the Partial Stop mode in Normal Stop mode */
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_PSTOPO_MASK;
|
||||
reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK;
|
||||
reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#endif
|
||||
|
||||
/* configure Normal Stop mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */
|
||||
|
@ -137,12 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter Stop mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
@ -152,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to VLPR power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlpr(SMC_Type *base
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)
|
||||
,
|
||||
bool wakeupMode
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
|
@ -172,18 +263,24 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base
|
|||
else
|
||||
{
|
||||
/* remains in VLP mode on an interrupt */
|
||||
reg &= ~SMC_PMCTRL_LPWUI_MASK;
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK;
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LPWUI */
|
||||
|
||||
/* configure VLPR mode */
|
||||
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to VLPW power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlpw(SMC_Type *base)
|
||||
{
|
||||
/* configure VLPW mode */
|
||||
|
@ -196,14 +293,20 @@ status_t SMC_SetPowerModeVlpw(SMC_Type *base)
|
|||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to VLPS power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
/* configure VLPS mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* Set the SLEEPDEEP bit to enable deep sleep mode */
|
||||
|
@ -211,12 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter VLPS mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
@ -227,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
|||
}
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
/*!
|
||||
* brief Configures the system to LLS power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeLls(SMC_Type *base
|
||||
#if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \
|
||||
(defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO))
|
||||
,
|
||||
const smc_power_mode_lls_config_t *config
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
/* configure to LLS mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* configure LLS sub-mode*/
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
|
||||
|
||||
|
@ -267,12 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter LLS mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
@ -284,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base
|
|||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
/*!
|
||||
* brief Configures the system to VLLS power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* param config The VLLS power mode configuration structure.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
@ -296,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
#endif
|
||||
{
|
||||
/* configure whether the Por Detect work in Vlls0 mode */
|
||||
if (config->enablePorDetectInVlls0)
|
||||
if (true == config->enablePorDetectInVlls0)
|
||||
{
|
||||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK;
|
||||
#else
|
||||
base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK;
|
||||
base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -319,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
else if (config->subMode == kSMC_StopSub2)
|
||||
{
|
||||
/* configure whether the Por Detect work in Vlls0 mode */
|
||||
if (config->enableRam2InVlls2)
|
||||
if (true == config->enableRam2InVlls2)
|
||||
{
|
||||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK;
|
||||
|
@ -332,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK;
|
||||
#else
|
||||
base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK;
|
||||
base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */
|
||||
|
||||
/* configure to VLLS mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* configure the VLLS sub-mode */
|
||||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
reg = base->VLLSCTRL;
|
||||
reg &= ~SMC_VLLSCTRL_VLLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT);
|
||||
reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT);
|
||||
base->VLLSCTRL = reg;
|
||||
#else
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#else
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_VLLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT);
|
||||
reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
|
||||
#endif
|
||||
|
@ -383,12 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter LLS mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef _FSL_SMC_H_
|
||||
|
@ -36,15 +14,14 @@
|
|||
/*! @addtogroup smc */
|
||||
/*! @{ */
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SMC driver version 2.0.3. */
|
||||
#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 3))
|
||||
/*! @brief SMC driver version 2.0.5. */
|
||||
#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5))
|
||||
/*@}*/
|
||||
|
||||
/*!
|
||||
|
@ -64,18 +41,14 @@ typedef enum _smc_power_mode_protection
|
|||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
kSMC_AllowPowerModeAll = (0U
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
|
|
||||
SMC_PMPROT_AVLLS_MASK
|
||||
| SMC_PMPROT_AVLLS_MASK
|
||||
#endif
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
|
|
||||
SMC_PMPROT_ALLS_MASK
|
||||
| SMC_PMPROT_ALLS_MASK
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
|
|
||||
SMC_PMPROT_AVLP_MASK
|
||||
| SMC_PMPROT_AVLP_MASK
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
|
|
||||
kSMC_AllowPowerModeHsrun
|
||||
| kSMC_AllowPowerModeHsrun
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
) /*!< Allow all power mode. */
|
||||
} smc_power_mode_protection_t;
|
||||
|
@ -85,7 +58,7 @@ typedef enum _smc_power_mode_protection
|
|||
*/
|
||||
typedef enum _smc_power_state
|
||||
{
|
||||
kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */
|
||||
kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */
|
||||
kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */
|
||||
kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */
|
||||
kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */
|
||||
|
@ -107,7 +80,7 @@ typedef enum _smc_power_state
|
|||
typedef enum _smc_run_mode
|
||||
{
|
||||
kSMC_RunNormal = 0U, /*!< Normal RUN mode. */
|
||||
kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */
|
||||
kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
|
@ -119,7 +92,7 @@ typedef enum _smc_run_mode
|
|||
typedef enum _smc_stop_mode
|
||||
{
|
||||
kSMC_StopNormal = 0U, /*!< Normal STOP mode. */
|
||||
kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */
|
||||
kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
|
@ -148,7 +121,7 @@ typedef enum _smc_stop_submode
|
|||
*/
|
||||
typedef enum _smc_partial_stop_mode
|
||||
{
|
||||
kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/
|
||||
kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/
|
||||
kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/
|
||||
kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/
|
||||
} smc_partial_stop_option_t;
|
||||
|
@ -324,11 +297,7 @@ void SMC_PostExitStopModes(void);
|
|||
*
|
||||
* This function should be called before entering WAIT/VLPW modes.
|
||||
*/
|
||||
static inline void SMC_PreEnterWaitModes(void)
|
||||
{
|
||||
__disable_irq();
|
||||
__ISB();
|
||||
}
|
||||
void SMC_PreEnterWaitModes(void);
|
||||
|
||||
/*!
|
||||
* @brief Recovers after wake up from stop modes.
|
||||
|
@ -336,11 +305,7 @@ static inline void SMC_PreEnterWaitModes(void)
|
|||
* This function should be called after wake up from WAIT/VLPW modes.
|
||||
* It is used with @ref SMC_PreEnterWaitModes.
|
||||
*/
|
||||
static inline void SMC_PostExitWaitModes(void)
|
||||
{
|
||||
__enable_irq();
|
||||
__ISB();
|
||||
}
|
||||
void SMC_PostExitWaitModes(void);
|
||||
|
||||
/*!
|
||||
* @brief Configures the system to RUN power mode.
|
||||
|
|
|
@ -332,4 +332,14 @@ const PinMap *serial_rts_pinmap()
|
|||
return PinMap_UART_RTS;
|
||||
}
|
||||
|
||||
void serial_wait_tx_complete(uint32_t uart_index)
|
||||
{
|
||||
LPUART_Type *base = uart_addrs[uart_index];
|
||||
|
||||
/* Wait till data is flushed out of transmit buffer */
|
||||
while (!(kLPUART_TransmissionCompleteFlag & LPUART_GetStatusFlags((LPUART_Type *)base)))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -119,16 +119,21 @@ int spi_master_write(spi_t *obj, int value)
|
|||
}
|
||||
|
||||
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
|
||||
char *rx_buffer, int rx_length, char write_fill) {
|
||||
char *rx_buffer, int rx_length, char write_fill)
|
||||
{
|
||||
int total = (tx_length > rx_length) ? tx_length : rx_length;
|
||||
|
||||
for (int i = 0; i < total; i++) {
|
||||
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
|
||||
char in = spi_master_write(obj, out);
|
||||
if (i < rx_length) {
|
||||
rx_buffer[i] = in;
|
||||
}
|
||||
}
|
||||
// Default write is done in each and every call, in future can create HAL API instead
|
||||
DSPI_SetDummyData(spi_address[obj->instance], write_fill);
|
||||
|
||||
DSPI_MasterTransferBlocking(spi_address[obj->instance], &(dspi_transfer_t) {
|
||||
.txData = (uint8_t *)tx_buffer,
|
||||
.rxData = (uint8_t *)rx_buffer,
|
||||
.dataSize = total,
|
||||
.configFlags = kDSPI_MasterCtar0 | kDSPI_MasterPcs0 | kDSPI_MasterPcsContinuous,
|
||||
});
|
||||
|
||||
DSPI_ClearStatusFlags(spi_address[obj->instance], kDSPI_RxFifoDrainRequestFlag | kDSPI_EndOfQueueFlag);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
|
|
@ -1,60 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_smc.h"
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.smc"
|
||||
#endif
|
||||
|
||||
typedef void (*smc_stop_ram_func_t)(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
static void SMC_EnterStopRamFunc(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
static uint32_t g_savedPrimask;
|
||||
|
||||
/*
|
||||
* The ram function code is:
|
||||
*
|
||||
* uint32_t i;
|
||||
* for (i=0; i<0x8; i++)
|
||||
* {
|
||||
* __NOP();
|
||||
* }
|
||||
* __DSB();
|
||||
* __WFI();
|
||||
* __ISB();
|
||||
*
|
||||
* When entring the stop modes, the flash prefetch might be interrupted, thus
|
||||
* the prefetched code or data might be broken. To make sure the flash is idle
|
||||
* when entring the stop modes, the code is moved to ram. And delay for a while
|
||||
* before WFI to make sure previous flash prefetch is finished.
|
||||
*
|
||||
* Only need to do like this when code is in flash, if code is in rom or ram,
|
||||
* this is not necessary.
|
||||
*/
|
||||
static uint16_t s_stopRamFuncArray[] = {
|
||||
0x2000, /* MOVS R0, #0 */
|
||||
0x2808, /* CMP R0, #8 */
|
||||
0xD202, /* BCS.N */
|
||||
0xBF00, /* NOP */
|
||||
0x1C40, /* ADDS R0, R0, #1 */
|
||||
0xE7FA, /* B.N */
|
||||
0xF3BF, 0x8F4F, /* DSB */
|
||||
0xBF30, /* WFI */
|
||||
0xF3BF, 0x8F6F, /* ISB */
|
||||
0x4770, /* BX LR */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static void SMC_EnterStopRamFunc(void)
|
||||
{
|
||||
uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U;
|
||||
smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry;
|
||||
stopRamFunc();
|
||||
}
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM)
|
||||
/*!
|
||||
* brief Gets the SMC parameter.
|
||||
*
|
||||
* This function gets the SMC parameter including the enabled power mdoes.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* param param Pointer to the SMC param structure.
|
||||
*/
|
||||
void SMC_GetParam(SMC_Type *base, smc_param_t *param)
|
||||
{
|
||||
uint32_t reg = base->PARAM;
|
||||
uint32_t reg = base->PARAM;
|
||||
param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK);
|
||||
param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK);
|
||||
param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK);
|
||||
param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK);
|
||||
param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK);
|
||||
param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK);
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_PARAM */
|
||||
|
||||
/*!
|
||||
* brief Prepares to enter stop modes.
|
||||
*
|
||||
* This function should be called before entering STOP/VLPS/LLS/VLLS modes.
|
||||
*/
|
||||
void SMC_PreEnterStopModes(void)
|
||||
{
|
||||
g_savedPrimask = DisableGlobalIRQ();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Recovers after wake up from stop modes.
|
||||
*
|
||||
* This function should be called after wake up from STOP/VLPS/LLS/VLLS modes.
|
||||
* It is used with ref SMC_PreEnterStopModes.
|
||||
*/
|
||||
void SMC_PostExitStopModes(void)
|
||||
{
|
||||
EnableGlobalIRQ(g_savedPrimask);
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Prepares to enter wait modes.
|
||||
*
|
||||
* This function should be called before entering WAIT/VLPW modes.
|
||||
*/
|
||||
void SMC_PreEnterWaitModes(void)
|
||||
{
|
||||
g_savedPrimask = DisableGlobalIRQ();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Recovers after wake up from stop modes.
|
||||
*
|
||||
* This function should be called after wake up from WAIT/VLPW modes.
|
||||
* It is used with ref SMC_PreEnterWaitModes.
|
||||
*/
|
||||
void SMC_PostExitWaitModes(void)
|
||||
{
|
||||
EnableGlobalIRQ(g_savedPrimask);
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to RUN power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeRun(SMC_Type *base)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
reg = base->PMCTRL;
|
||||
/* configure Normal RUN mode */
|
||||
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
/*!
|
||||
* brief Configures the system to HSRUN power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeHsrun(SMC_Type *base)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
@ -62,38 +170,53 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base)
|
|||
reg = base->PMCTRL;
|
||||
/* configure High Speed RUN mode */
|
||||
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
|
||||
reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
|
||||
/*!
|
||||
* brief Configures the system to WAIT power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeWait(SMC_Type *base)
|
||||
{
|
||||
/* configure Normal Wait mode */
|
||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to Stop power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* param option Partial Stop mode option.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO)
|
||||
/* configure the Partial Stop mode in Noraml Stop mode */
|
||||
/* configure the Partial Stop mode in Normal Stop mode */
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_PSTOPO_MASK;
|
||||
reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK;
|
||||
reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#endif
|
||||
|
||||
/* configure Normal Stop mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */
|
||||
|
@ -101,10 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__WFI();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter Stop mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
@ -114,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to VLPR power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlpr(SMC_Type *base
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)
|
||||
,
|
||||
bool wakeupMode
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
|
@ -134,42 +263,50 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base
|
|||
else
|
||||
{
|
||||
/* remains in VLP mode on an interrupt */
|
||||
reg &= ~SMC_PMCTRL_LPWUI_MASK;
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK;
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LPWUI */
|
||||
|
||||
/* configure VLPR mode */
|
||||
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to VLPW power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlpw(SMC_Type *base)
|
||||
{
|
||||
/* Power mode transaction to VLPW can only happen in VLPR mode */
|
||||
if (kSMC_PowerStateVlpr != SMC_GetPowerModeState(base))
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
/* configure VLPW mode */
|
||||
/* Set the SLEEPDEEP bit to enable deep sleep mode */
|
||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to VLPS power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
/* configure VLPS mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* Set the SLEEPDEEP bit to enable deep sleep mode */
|
||||
|
@ -177,10 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__WFI();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter VLPS mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
@ -191,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
|||
}
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
/*!
|
||||
* brief Configures the system to LLS power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeLls(SMC_Type *base
|
||||
#if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \
|
||||
(defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO))
|
||||
,
|
||||
const smc_power_mode_lls_config_t *config
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
/* configure to LLS mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* configure LLS sub-mode*/
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
|
||||
|
||||
|
@ -231,10 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__WFI();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter LLS mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
@ -246,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base
|
|||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
/*!
|
||||
* brief Configures the system to VLLS power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* param config The VLLS power mode configuration structure.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
@ -258,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
#endif
|
||||
{
|
||||
/* configure whether the Por Detect work in Vlls0 mode */
|
||||
if (config->enablePorDetectInVlls0)
|
||||
if (true == config->enablePorDetectInVlls0)
|
||||
{
|
||||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK;
|
||||
#else
|
||||
base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK;
|
||||
base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -281,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
else if (config->subMode == kSMC_StopSub2)
|
||||
{
|
||||
/* configure whether the Por Detect work in Vlls0 mode */
|
||||
if (config->enableRam2InVlls2)
|
||||
if (true == config->enableRam2InVlls2)
|
||||
{
|
||||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK;
|
||||
|
@ -294,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK;
|
||||
#else
|
||||
base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK;
|
||||
base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */
|
||||
|
||||
/* configure to VLLS mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* configure the VLLS sub-mode */
|
||||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
reg = base->VLLSCTRL;
|
||||
reg &= ~SMC_VLLSCTRL_VLLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT);
|
||||
reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT);
|
||||
base->VLLSCTRL = reg;
|
||||
#else
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#else
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_VLLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT);
|
||||
reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
|
||||
#endif
|
||||
|
@ -345,10 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__WFI();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter LLS mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef _FSL_SMC_H_
|
||||
|
@ -36,16 +14,14 @@
|
|||
/*! @addtogroup smc */
|
||||
/*! @{ */
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SMC driver version 2.0.1. */
|
||||
#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
|
||||
/*! @brief SMC driver version 2.0.5. */
|
||||
#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5))
|
||||
/*@}*/
|
||||
|
||||
/*!
|
||||
|
@ -54,29 +30,25 @@
|
|||
typedef enum _smc_power_mode_protection
|
||||
{
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-Low-Leakage Stop Mode. */
|
||||
kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-low-leakage Stop Mode. */
|
||||
#endif
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-Leakage Stop Mode. */
|
||||
kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-leakage Stop Mode. */
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-Power Mode. */
|
||||
kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-power Mode. */
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High Speed Run mode. */
|
||||
kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High-speed Run mode. */
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
kSMC_AllowPowerModeAll = (0U
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
|
|
||||
SMC_PMPROT_AVLLS_MASK
|
||||
| SMC_PMPROT_AVLLS_MASK
|
||||
#endif
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
|
|
||||
SMC_PMPROT_ALLS_MASK
|
||||
| SMC_PMPROT_ALLS_MASK
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
|
|
||||
SMC_PMPROT_AVLP_MASK
|
||||
| SMC_PMPROT_AVLP_MASK
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
|
|
||||
kSMC_AllowPowerModeHsrun
|
||||
| kSMC_AllowPowerModeHsrun
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
) /*!< Allow all power mode. */
|
||||
} smc_power_mode_protection_t;
|
||||
|
@ -86,7 +58,7 @@ typedef enum _smc_power_mode_protection
|
|||
*/
|
||||
typedef enum _smc_power_state
|
||||
{
|
||||
kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */
|
||||
kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */
|
||||
kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */
|
||||
kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */
|
||||
kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */
|
||||
|
@ -107,10 +79,10 @@ typedef enum _smc_power_state
|
|||
*/
|
||||
typedef enum _smc_run_mode
|
||||
{
|
||||
kSMC_RunNormal = 0U, /*!< normal RUN mode. */
|
||||
kSMC_RunVlpr = 2U, /*!< Very-Low-Power RUN mode. */
|
||||
kSMC_RunNormal = 0U, /*!< Normal RUN mode. */
|
||||
kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
kSMC_Hsrun = 3U /*!< High Speed Run mode (HSRUN). */
|
||||
kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
} smc_run_mode_t;
|
||||
|
||||
|
@ -120,12 +92,12 @@ typedef enum _smc_run_mode
|
|||
typedef enum _smc_stop_mode
|
||||
{
|
||||
kSMC_StopNormal = 0U, /*!< Normal STOP mode. */
|
||||
kSMC_StopVlps = 2U, /*!< Very-Low-Power STOP mode. */
|
||||
kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
kSMC_StopLls = 3U, /*!< Low-Leakage Stop mode. */
|
||||
kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
kSMC_StopVlls = 4U /*!< Very-Low-Leakage Stop mode. */
|
||||
kSMC_StopVlls = 4U /*!< Very-low-leakage Stop mode. */
|
||||
#endif
|
||||
} smc_stop_mode_t;
|
||||
|
||||
|
@ -149,13 +121,13 @@ typedef enum _smc_stop_submode
|
|||
*/
|
||||
typedef enum _smc_partial_stop_mode
|
||||
{
|
||||
kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/
|
||||
kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/
|
||||
kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/
|
||||
kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/
|
||||
} smc_partial_stop_option_t;
|
||||
|
||||
/*!
|
||||
* @brief SMC configuration status
|
||||
* @brief SMC configuration status.
|
||||
*/
|
||||
enum _smc_status
|
||||
{
|
||||
|
@ -190,7 +162,7 @@ typedef struct _smc_param
|
|||
#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \
|
||||
(defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)
|
||||
/*!
|
||||
* @brief SMC Low-Leakage Stop power mode config
|
||||
* @brief SMC Low-Leakage Stop power mode configuration.
|
||||
*/
|
||||
typedef struct _smc_power_mode_lls_config
|
||||
{
|
||||
|
@ -205,7 +177,7 @@ typedef struct _smc_power_mode_lls_config
|
|||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
/*!
|
||||
* @brief SMC Very Low-Leakage Stop power mode config
|
||||
* @brief SMC Very Low-Leakage Stop power mode configuration.
|
||||
*/
|
||||
typedef struct _smc_power_mode_vlls_config
|
||||
{
|
||||
|
@ -242,10 +214,10 @@ extern "C" {
|
|||
* @brief Gets the SMC version ID.
|
||||
*
|
||||
* This function gets the SMC version ID, including major version number,
|
||||
* minor version number and feature specification number.
|
||||
* minor version number, and feature specification number.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @param versionId Pointer to version ID structure.
|
||||
* @param versionId Pointer to the version ID structure.
|
||||
*/
|
||||
static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId)
|
||||
{
|
||||
|
@ -257,10 +229,10 @@ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId)
|
|||
/*!
|
||||
* @brief Gets the SMC parameter.
|
||||
*
|
||||
* This function gets the SMC parameter, including the enabled power mdoes.
|
||||
* This function gets the SMC parameter including the enabled power mdoes.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @param param Pointer to SMC param structure.
|
||||
* @param param Pointer to the SMC param structure.
|
||||
*/
|
||||
void SMC_GetParam(SMC_Type *base, smc_param_t *param);
|
||||
#endif
|
||||
|
@ -274,7 +246,7 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param);
|
|||
* system level initialization stage. See the reference manual for details.
|
||||
* This register can only write once after the power reset.
|
||||
*
|
||||
* The allowed modes are passed as bit map, for example, to allow LLS and VLLS,
|
||||
* The allowed modes are passed as bit map. For example, to allow LLS and VLLS,
|
||||
* use SMC_SetPowerModeProtection(kSMC_AllowPowerModeVlls | kSMC_AllowPowerModeVlps).
|
||||
* To allow all modes, use SMC_SetPowerModeProtection(kSMC_AllowPowerModeAll).
|
||||
*
|
||||
|
@ -289,13 +261,13 @@ static inline void SMC_SetPowerModeProtection(SMC_Type *base, uint8_t allowedMod
|
|||
/*!
|
||||
* @brief Gets the current power mode status.
|
||||
*
|
||||
* This function returns the current power mode stat. Once application
|
||||
* switches the power mode, it should always check the stat to check whether it
|
||||
* runs into the specified mode or not. An application should check
|
||||
* This function returns the current power mode status. After the application
|
||||
* switches the power mode, it should always check the status to check whether it
|
||||
* runs into the specified mode or not. The application should check
|
||||
* this mode before switching to a different mode. The system requires that
|
||||
* only certain modes can switch to other specific modes. See the
|
||||
* reference manual for details and the smc_power_state_t for information about
|
||||
* the power stat.
|
||||
* the power status.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return Current power mode status.
|
||||
|
@ -306,7 +278,37 @@ static inline smc_power_state_t SMC_GetPowerModeState(SMC_Type *base)
|
|||
}
|
||||
|
||||
/*!
|
||||
* @brief Configure the system to RUN power mode.
|
||||
* @brief Prepares to enter stop modes.
|
||||
*
|
||||
* This function should be called before entering STOP/VLPS/LLS/VLLS modes.
|
||||
*/
|
||||
void SMC_PreEnterStopModes(void);
|
||||
|
||||
/*!
|
||||
* @brief Recovers after wake up from stop modes.
|
||||
*
|
||||
* This function should be called after wake up from STOP/VLPS/LLS/VLLS modes.
|
||||
* It is used with @ref SMC_PreEnterStopModes.
|
||||
*/
|
||||
void SMC_PostExitStopModes(void);
|
||||
|
||||
/*!
|
||||
* @brief Prepares to enter wait modes.
|
||||
*
|
||||
* This function should be called before entering WAIT/VLPW modes.
|
||||
*/
|
||||
void SMC_PreEnterWaitModes(void);
|
||||
|
||||
/*!
|
||||
* @brief Recovers after wake up from stop modes.
|
||||
*
|
||||
* This function should be called after wake up from WAIT/VLPW modes.
|
||||
* It is used with @ref SMC_PreEnterWaitModes.
|
||||
*/
|
||||
void SMC_PostExitWaitModes(void);
|
||||
|
||||
/*!
|
||||
* @brief Configures the system to RUN power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -315,7 +317,7 @@ status_t SMC_SetPowerModeRun(SMC_Type *base);
|
|||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
/*!
|
||||
* @brief Configure the system to HSRUN power mode.
|
||||
* @brief Configures the system to HSRUN power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -324,7 +326,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base);
|
|||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
|
||||
/*!
|
||||
* @brief Configure the system to WAIT power mode.
|
||||
* @brief Configures the system to WAIT power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -332,7 +334,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base);
|
|||
status_t SMC_SetPowerModeWait(SMC_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Configure the system to Stop power mode.
|
||||
* @brief Configures the system to Stop power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @param option Partial Stop mode option.
|
||||
|
@ -342,7 +344,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option);
|
|||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)
|
||||
/*!
|
||||
* @brief Configure the system to VLPR power mode.
|
||||
* @brief Configures the system to VLPR power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @param wakeupMode Enter Normal Run mode if true, else stay in VLPR mode.
|
||||
|
@ -351,7 +353,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option);
|
|||
status_t SMC_SetPowerModeVlpr(SMC_Type *base, bool wakeupMode);
|
||||
#else
|
||||
/*!
|
||||
* @brief Configure the system to VLPR power mode.
|
||||
* @brief Configures the system to VLPR power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -360,7 +362,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base);
|
|||
#endif /* FSL_FEATURE_SMC_HAS_LPWUI */
|
||||
|
||||
/*!
|
||||
* @brief Configure the system to VLPW power mode.
|
||||
* @brief Configures the system to VLPW power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -368,7 +370,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base);
|
|||
status_t SMC_SetPowerModeVlpw(SMC_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Configure the system to VLPS power mode.
|
||||
* @brief Configures the system to VLPS power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -379,7 +381,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base);
|
|||
#if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \
|
||||
(defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO))
|
||||
/*!
|
||||
* @brief Configure the system to LLS power mode.
|
||||
* @brief Configures the system to LLS power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @param config The LLS power mode configuration structure
|
||||
|
@ -388,7 +390,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base);
|
|||
status_t SMC_SetPowerModeLls(SMC_Type *base, const smc_power_mode_lls_config_t *config);
|
||||
#else
|
||||
/*!
|
||||
* @brief Configure the system to LLS power mode.
|
||||
* @brief Configures the system to LLS power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -399,7 +401,7 @@ status_t SMC_SetPowerModeLls(SMC_Type *base);
|
|||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
/*!
|
||||
* @brief Configure the system to VLLS power mode.
|
||||
* @brief Configures the system to VLLS power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @param config The VLLS power mode configuration structure.
|
||||
|
|
|
@ -1,38 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_spi.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitons
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.spi"
|
||||
#endif
|
||||
|
||||
/*! @brief SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
|
||||
enum _spi_transfer_states_t
|
||||
{
|
||||
|
@ -46,12 +30,6 @@ typedef void (*spi_isr_t)(SPI_Type *base, spi_master_handle_t *spiHandle);
|
|||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Get the instance for SPI module.
|
||||
*
|
||||
* @param base SPI base address
|
||||
*/
|
||||
uint32_t SPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Sends a buffer of data bytes in non-blocking way.
|
||||
|
@ -71,6 +49,14 @@ static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
|
|||
*/
|
||||
static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
|
||||
|
||||
/*!
|
||||
* @brief Get the waterrmark value for this SPI instance.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @return Watermark value for the SPI instance.
|
||||
*/
|
||||
static uint8_t SPI_GetWatermark(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Send a piece of data for SPI.
|
||||
*
|
||||
|
@ -78,6 +64,7 @@ static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
|
|||
* and write the data into it. At the same time, this function updates the values in
|
||||
* master handle structure.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param handle Pointer to SPI master handle structure.
|
||||
*/
|
||||
static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle);
|
||||
|
@ -89,9 +76,18 @@ static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle);
|
|||
* and write the data to destination address. At the same time, this function updates
|
||||
* the values in master handle structure.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param handle Pointer to SPI master handle structure.
|
||||
*/
|
||||
static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Common IRQ handler for SPI.
|
||||
*
|
||||
* @param base SPI base pointer.
|
||||
* @param instance SPI instance number.
|
||||
*/
|
||||
static void SPI_CommonIRQHandler(SPI_Type *base, uint32_t instance);
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
@ -101,21 +97,31 @@ static spi_master_handle_t *s_spiHandle[FSL_FEATURE_SOC_SPI_COUNT];
|
|||
static SPI_Type *const s_spiBases[] = SPI_BASE_PTRS;
|
||||
/*! @brief IRQ name array */
|
||||
static const IRQn_Type s_spiIRQ[] = SPI_IRQS;
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/*! @brief Clock array name */
|
||||
static const clock_ip_name_t s_spiClock[] = SPI_CLOCKS;
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
/*! @brief Pointer to master IRQ handler for each instance. */
|
||||
static spi_isr_t s_spiIsr;
|
||||
static spi_isr_t s_spiMasterIsr;
|
||||
static spi_isr_t s_spiSlaveIsr;
|
||||
|
||||
/* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/
|
||||
volatile uint8_t g_spiDummyData[ARRAY_SIZE(s_spiBases)] = {0};
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* brief Get the instance for SPI module.
|
||||
*
|
||||
* param base SPI base address
|
||||
*/
|
||||
uint32_t SPI_GetInstance(SPI_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
/* Find the instance index from base address mappings. */
|
||||
for (instance = 0; instance < FSL_FEATURE_SOC_SPI_COUNT; instance++)
|
||||
for (instance = 0; instance < ARRAY_SIZE(s_spiBases); instance++)
|
||||
{
|
||||
if (s_spiBases[instance] == base)
|
||||
{
|
||||
|
@ -123,15 +129,28 @@ uint32_t SPI_GetInstance(SPI_Type *base)
|
|||
}
|
||||
}
|
||||
|
||||
assert(instance < FSL_FEATURE_SOC_SPI_COUNT);
|
||||
assert(instance < ARRAY_SIZE(s_spiBases));
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Set up the dummy data.
|
||||
*
|
||||
* param base SPI peripheral address.
|
||||
* param dummyData Data to be transferred when tx buffer is NULL.
|
||||
*/
|
||||
void SPI_SetDummyData(SPI_Type *base, uint8_t dummyData)
|
||||
{
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
g_spiDummyData[instance] = dummyData;
|
||||
}
|
||||
|
||||
static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0;
|
||||
uint8_t bytesPerFrame = 1U;
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
/* Check if 16 bits or 8 bits */
|
||||
|
@ -155,13 +174,13 @@ static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
base->DL = *buffer++;
|
||||
}
|
||||
#else
|
||||
base->D = *buffer++;
|
||||
base->D = *buffer++;
|
||||
#endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
|
||||
}
|
||||
/* Send dummy data */
|
||||
else
|
||||
{
|
||||
SPI_WriteData(base, SPI_DUMMYDATA);
|
||||
SPI_WriteData(base, ((uint32_t)g_spiDummyData[instance] << 8 | g_spiDummyData[instance]));
|
||||
}
|
||||
i += bytesPerFrame;
|
||||
}
|
||||
|
@ -169,7 +188,7 @@ static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
|
||||
static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0;
|
||||
uint8_t bytesPerFrame = 1U;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
|
@ -205,18 +224,68 @@ static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
}
|
||||
}
|
||||
|
||||
/* Get the watermark value of transfer. Please note that the entery width of FIFO is 16 bits. */
|
||||
static uint8_t SPI_GetWatermark(SPI_Type *base)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
uint8_t rxSize = 0U;
|
||||
/* Get the number to be sent if there is FIFO */
|
||||
if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
|
||||
{
|
||||
rxSize = (base->C3 & SPI_C3_RNFULLF_MARK_MASK) >> SPI_C3_RNFULLF_MARK_SHIFT;
|
||||
if (rxSize == 0U)
|
||||
{
|
||||
ret = FSL_FEATURE_SPI_FIFO_SIZEn(base) * 3U / 4U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = FSL_FEATURE_SPI_FIFO_SIZEn(base) / 2U;
|
||||
}
|
||||
}
|
||||
/* If no FIFO, just set the watermark to 1 */
|
||||
else
|
||||
{
|
||||
ret = 1U;
|
||||
}
|
||||
#else
|
||||
ret = 1U;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void SPI_SendInitialTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint8_t bytestoTransfer = handle->bytePerFrame;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
|
||||
if (handle->watermark > 1)
|
||||
{
|
||||
/* In the first time to send data to FIFO, if transfer size is not larger than
|
||||
* the FIFO size, send all data to FIFO, or send data to make the FIFO full.
|
||||
* Besides, The FIFO's entry width is 16 bits, need to translate it to bytes.
|
||||
*/
|
||||
bytestoTransfer = MIN(handle->txRemainingBytes, (FSL_FEATURE_SPI_FIFO_SIZEn(base) * 2));
|
||||
}
|
||||
#endif
|
||||
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytestoTransfer);
|
||||
|
||||
/* Update handle information */
|
||||
if (handle->txData)
|
||||
{
|
||||
handle->txData += bytestoTransfer;
|
||||
}
|
||||
handle->txRemainingBytes -= bytestoTransfer;
|
||||
}
|
||||
|
||||
static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint8_t bytes = MIN((handle->watermark * 2U), handle->txRemainingBytes);
|
||||
uint8_t bytes = handle->bytePerFrame;
|
||||
|
||||
/* Read S register and ensure SPTEF is 1, otherwise the write would be ignored. */
|
||||
if (handle->watermark == 1U)
|
||||
{
|
||||
if (bytes != 0U)
|
||||
{
|
||||
bytes = handle->bytePerFrame;
|
||||
}
|
||||
|
||||
/* Send data */
|
||||
if (base->C1 & SPI_C1_MSTR_MASK)
|
||||
{
|
||||
|
@ -231,11 +300,11 @@ static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
|||
}
|
||||
handle->txRemainingBytes -= bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
/* As a slave, send data until SPTEF cleared */
|
||||
while ((base->S & SPI_S_SPTEF_MASK) && (handle->txRemainingBytes > 0))
|
||||
while ((base->S & SPI_S_SPTEF_MASK) && (handle->txRemainingBytes >= bytes))
|
||||
{
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytes);
|
||||
|
||||
|
@ -253,56 +322,96 @@ static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
|||
/* If use FIFO */
|
||||
else
|
||||
{
|
||||
if (base->S & SPI_S_TNEAREF_MASK)
|
||||
{
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytes);
|
||||
/* The FIFO's entry width is 16 bits, need to translate it to bytes. */
|
||||
uint8_t bytestoTransfer = handle->watermark * 2;
|
||||
|
||||
/* Update handle information */
|
||||
if (handle->txData)
|
||||
{
|
||||
handle->txData += bytes;
|
||||
}
|
||||
handle->txRemainingBytes -= bytes;
|
||||
if (handle->txRemainingBytes < 8U)
|
||||
{
|
||||
bytestoTransfer = handle->txRemainingBytes;
|
||||
}
|
||||
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytestoTransfer);
|
||||
|
||||
/* Update handle information */
|
||||
if (handle->txData)
|
||||
{
|
||||
handle->txData += bytestoTransfer;
|
||||
}
|
||||
handle->txRemainingBytes -= bytestoTransfer;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint8_t bytes = MIN((handle->watermark * 2U), handle->rxRemainingBytes);
|
||||
uint8_t val = 1U;
|
||||
uint8_t bytes = handle->bytePerFrame;
|
||||
|
||||
/* Read S register and ensure SPRF is 1, otherwise the write would be ignored. */
|
||||
if (handle->watermark == 1U)
|
||||
{
|
||||
val = base->S & SPI_S_SPRF_MASK;
|
||||
if (bytes != 0U)
|
||||
if (base->S & SPI_S_SPRF_MASK)
|
||||
{
|
||||
bytes = handle->bytePerFrame;
|
||||
SPI_ReadNonBlocking(base, handle->rxData, bytes);
|
||||
|
||||
/* Update information in handle */
|
||||
if (handle->rxData)
|
||||
{
|
||||
handle->rxData += bytes;
|
||||
}
|
||||
handle->rxRemainingBytes -= bytes;
|
||||
}
|
||||
}
|
||||
|
||||
if (val)
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
|
||||
/* If use FIFO */
|
||||
else
|
||||
{
|
||||
SPI_ReadNonBlocking(base, handle->rxData, bytes);
|
||||
|
||||
/* Update information in handle */
|
||||
if (handle->rxData)
|
||||
/* While rx fifo not empty and remaining data can also trigger the last interrupt */
|
||||
while ((base->S & SPI_S_RFIFOEF_MASK) == 0U)
|
||||
{
|
||||
handle->rxData += bytes;
|
||||
SPI_ReadNonBlocking(base, handle->rxData, bytes);
|
||||
|
||||
/* Update information in handle */
|
||||
if (handle->rxData)
|
||||
{
|
||||
handle->rxData += bytes;
|
||||
}
|
||||
handle->rxRemainingBytes -= bytes;
|
||||
|
||||
/* If the reamining data equals to watermark, leave to last interrupt */
|
||||
if (handle->rxRemainingBytes == (handle->watermark * 2U))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
handle->rxRemainingBytes -= bytes;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sets the SPI master configuration structure to default values.
|
||||
*
|
||||
* The purpose of this API is to get the configuration structure initialized for use in SPI_MasterInit().
|
||||
* User may use the initialized structure unchanged in SPI_MasterInit(), or modify
|
||||
* some fields of the structure before calling SPI_MasterInit(). After calling this API,
|
||||
* the master is ready to transfer.
|
||||
* Example:
|
||||
code
|
||||
spi_master_config_t config;
|
||||
SPI_MasterGetDefaultConfig(&config);
|
||||
endcode
|
||||
*
|
||||
* param config pointer to master config structure
|
||||
*/
|
||||
void SPI_MasterGetDefaultConfig(spi_master_config_t *config)
|
||||
{
|
||||
config->enableMaster = true;
|
||||
/* Initializes the configure structure to zero. */
|
||||
memset(config, 0, sizeof(*config));
|
||||
|
||||
config->enableMaster = true;
|
||||
config->enableStopInWaitMode = false;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
config->dataMode = kSPI_8BitMode;
|
||||
|
@ -313,17 +422,37 @@ void SPI_MasterGetDefaultConfig(spi_master_config_t *config)
|
|||
config->rxWatermark = kSPI_RxFifoOneHalfFull;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
config->pinMode = kSPI_PinModeNormal;
|
||||
config->outputMode = kSPI_SlaveSelectAutomaticOutput;
|
||||
config->pinMode = kSPI_PinModeNormal;
|
||||
config->outputMode = kSPI_SlaveSelectAutomaticOutput;
|
||||
config->baudRate_Bps = 500000U;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI with master configuration.
|
||||
*
|
||||
* The configuration structure can be filled by user from scratch, or be set with default
|
||||
* values by SPI_MasterGetDefaultConfig(). After calling this API, the slave is ready to transfer.
|
||||
* Example
|
||||
code
|
||||
spi_master_config_t config = {
|
||||
.baudRate_Bps = 400000,
|
||||
...
|
||||
};
|
||||
SPI_MasterInit(SPI0, &config);
|
||||
endcode
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param config pointer to master configuration structure
|
||||
* param srcClock_Hz Source clock frequency.
|
||||
*/
|
||||
void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t srcClock_Hz)
|
||||
{
|
||||
assert(config && srcClock_Hz);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Open clock gate for SPI and open interrupt */
|
||||
CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
/* Disable SPI before configuration */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
|
@ -354,6 +483,9 @@ void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t
|
|||
/* Set baud rate */
|
||||
SPI_MasterSetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
|
||||
|
||||
/* Set the dummy data, this data will usefull when tx buffer is NULL. */
|
||||
SPI_SetDummyData(base, SPI_DUMMYDATA);
|
||||
|
||||
/* Enable SPI */
|
||||
if (config->enableMaster)
|
||||
{
|
||||
|
@ -361,12 +493,28 @@ void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sets the SPI slave configuration structure to default values.
|
||||
*
|
||||
* The purpose of this API is to get the configuration structure initialized for use in SPI_SlaveInit().
|
||||
* Modify some fields of the structure before calling SPI_SlaveInit().
|
||||
* Example:
|
||||
code
|
||||
spi_slave_config_t config;
|
||||
SPI_SlaveGetDefaultConfig(&config);
|
||||
endcode
|
||||
*
|
||||
* param config pointer to slave configuration structure
|
||||
*/
|
||||
void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config)
|
||||
{
|
||||
config->enableSlave = true;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
/* Initializes the configure structure to zero. */
|
||||
memset(config, 0, sizeof(*config));
|
||||
|
||||
config->enableSlave = true;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
config->enableStopInWaitMode = false;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
|
@ -377,14 +525,37 @@ void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config)
|
|||
config->txWatermark = kSPI_TxFifoOneHalfEmpty;
|
||||
config->rxWatermark = kSPI_RxFifoOneHalfFull;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
config->pinMode = kSPI_PinModeNormal;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI with slave configuration.
|
||||
*
|
||||
* The configuration structure can be filled by user from scratch or be set with
|
||||
* default values by SPI_SlaveGetDefaultConfig().
|
||||
* After calling this API, the slave is ready to transfer.
|
||||
* Example
|
||||
code
|
||||
spi_slave_config_t config = {
|
||||
.polarity = kSPIClockPolarity_ActiveHigh;
|
||||
.phase = kSPIClockPhase_FirstEdge;
|
||||
.direction = kSPIMsbFirst;
|
||||
...
|
||||
};
|
||||
SPI_MasterInit(SPI0, &config);
|
||||
endcode
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param config pointer to master configuration structure
|
||||
*/
|
||||
void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Open clock gate for SPI and open interrupt */
|
||||
CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
/* Disable SPI before configuration */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
|
@ -395,9 +566,11 @@ void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
|||
|
||||
/* Configure data mode if needed */
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
base->C2 = SPI_C2_SPIMODE(config->dataMode) | SPI_C2_SPISWAI(config->enableStopInWaitMode);
|
||||
base->C2 = SPI_C2_SPIMODE(config->dataMode) | SPI_C2_SPISWAI(config->enableStopInWaitMode) |
|
||||
SPI_C2_BIDIROE(config->pinMode >> 1U) | SPI_C2_SPC0(config->pinMode & 1U);
|
||||
#else
|
||||
base->C2 = SPI_C2_SPISWAI(config->enableStopInWaitMode);
|
||||
base->C2 = SPI_C2_SPISWAI(config->enableStopInWaitMode) | SPI_C2_BIDIROE(config->pinMode >> 1U) |
|
||||
SPI_C2_SPC0(config->pinMode & 1U);
|
||||
#endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
|
||||
|
||||
/* Set watermark */
|
||||
|
@ -409,6 +582,9 @@ void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
|||
}
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
/* Set the dummy data, this data will usefull when tx buffer is NULL. */
|
||||
SPI_SetDummyData(base, SPI_DUMMYDATA);
|
||||
|
||||
/* Enable SPI */
|
||||
if (config->enableSlave)
|
||||
{
|
||||
|
@ -416,15 +592,31 @@ void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief De-initializes the SPI.
|
||||
*
|
||||
* Calling this API resets the SPI module, gates the SPI clock.
|
||||
* The SPI module can't work unless calling the SPI_MasterInit/SPI_SlaveInit to initialize module.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
*/
|
||||
void SPI_Deinit(SPI_Type *base)
|
||||
{
|
||||
/* Disable SPI module before shutting down */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Gate the clock */
|
||||
CLOCK_DisableClock(s_spiClock[SPI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Gets the status flag.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* return SPI Status, use status flag to AND #_spi_flags could get the related status.
|
||||
*/
|
||||
uint32_t SPI_GetStatusFlags(SPI_Type *base)
|
||||
{
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
|
@ -441,6 +633,17 @@ uint32_t SPI_GetStatusFlags(SPI_Type *base)
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Enables the interrupt for the SPI.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param mask SPI interrupt source. The parameter can be any combination of the following values:
|
||||
* arg kSPI_RxFullAndModfInterruptEnable
|
||||
* arg kSPI_TxEmptyInterruptEnable
|
||||
* arg kSPI_MatchInterruptEnable
|
||||
* arg kSPI_RxFifoNearFullInterruptEnable
|
||||
* arg kSPI_TxFifoNearEmptyInterruptEnable
|
||||
*/
|
||||
void SPI_EnableInterrupts(SPI_Type *base, uint32_t mask)
|
||||
{
|
||||
/* Rx full interrupt */
|
||||
|
@ -480,6 +683,17 @@ void SPI_EnableInterrupts(SPI_Type *base, uint32_t mask)
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Disables the interrupt for the SPI.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param mask SPI interrupt source. The parameter can be any combination of the following values:
|
||||
* arg kSPI_RxFullAndModfInterruptEnable
|
||||
* arg kSPI_TxEmptyInterruptEnable
|
||||
* arg kSPI_MatchInterruptEnable
|
||||
* arg kSPI_RxFifoNearFullInterruptEnable
|
||||
* arg kSPI_TxFifoNearEmptyInterruptEnable
|
||||
*/
|
||||
void SPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
|
||||
{
|
||||
/* Rx full interrupt */
|
||||
|
@ -518,6 +732,13 @@ void SPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sets the baud rate for SPI transfer. This is only used in master.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param baudRate_Bps baud rate needed in Hz.
|
||||
* param srcClock_Hz SPI source clock frequency in Hz.
|
||||
*/
|
||||
void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
|
||||
{
|
||||
uint32_t prescaler;
|
||||
|
@ -535,7 +756,7 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl
|
|||
|
||||
/* Set the maximum divisor bit settings for each of the following divisors */
|
||||
bestPrescaler = 7U;
|
||||
bestDivisor = 8U;
|
||||
bestDivisor = 8U;
|
||||
|
||||
/* In all for loops, if min_diff = 0, the exit for loop*/
|
||||
for (prescaler = 0; (prescaler <= 7) && min_diff; prescaler++)
|
||||
|
@ -556,9 +777,9 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl
|
|||
if (min_diff > diff)
|
||||
{
|
||||
/* A better match found */
|
||||
min_diff = diff;
|
||||
min_diff = diff;
|
||||
bestPrescaler = prescaler;
|
||||
bestDivisor = rateDivisor;
|
||||
bestDivisor = rateDivisor;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,9 +792,18 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl
|
|||
base->BR = SPI_BR_SPR(bestDivisor) | SPI_BR_SPPR(bestPrescaler);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sends a buffer of data bytes using a blocking method.
|
||||
*
|
||||
* note This function blocks via polling until all bytes have been sent.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param buffer The data bytes to send
|
||||
* param size The number of data bytes to send
|
||||
*/
|
||||
void SPI_WriteBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0;
|
||||
uint8_t bytesPerFrame = 1U;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
|
@ -596,6 +826,12 @@ void SPI_WriteBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
}
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
/*!
|
||||
* brief Enables or disables the FIFO if there is a FIFO.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param enable True means enable FIFO, false means disable FIFO.
|
||||
*/
|
||||
void SPI_EnableFIFO(SPI_Type *base, bool enable)
|
||||
{
|
||||
if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0U)
|
||||
|
@ -612,6 +848,12 @@ void SPI_EnableFIFO(SPI_Type *base, bool enable)
|
|||
}
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
/*!
|
||||
* brief Writes a data into the SPI data register.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param data needs to be write.
|
||||
*/
|
||||
void SPI_WriteData(SPI_Type *base, uint16_t data)
|
||||
{
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
|
||||
|
@ -622,6 +864,12 @@ void SPI_WriteData(SPI_Type *base, uint16_t data)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Gets a data from the SPI data register.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* return Data in the register.
|
||||
*/
|
||||
uint16_t SPI_ReadData(SPI_Type *base)
|
||||
{
|
||||
uint16_t val = 0;
|
||||
|
@ -634,6 +882,14 @@ uint16_t SPI_ReadData(SPI_Type *base)
|
|||
return val;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Transfers a block of data using a polling method.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param xfer pointer to spi_xfer_config_t structure
|
||||
* retval kStatus_Success Successfully start a transfer.
|
||||
* retval kStatus_InvalidArgument Input argument is invalid.
|
||||
*/
|
||||
status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
||||
{
|
||||
assert(xfer);
|
||||
|
@ -651,10 +907,6 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
|||
bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
|
||||
#endif
|
||||
|
||||
/* Disable SPI and then enable it, this is used to clear S register */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
base->C1 |= SPI_C1_SPE_MASK;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
|
||||
/* Disable FIFO, as the FIFO may cause data loss if the data size is not integer
|
||||
|
@ -696,6 +948,17 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
|||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI master handle.
|
||||
*
|
||||
* This function initializes the SPI master handle which can be used for other SPI master transactional APIs. Usually,
|
||||
* for a specified SPI instance, call this API once to get the initialized handle.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI handle pointer.
|
||||
* param callback Callback function.
|
||||
* param userData User data.
|
||||
*/
|
||||
void SPI_MasterTransferCreateHandle(SPI_Type *base,
|
||||
spi_master_handle_t *handle,
|
||||
spi_master_callback_t callback,
|
||||
|
@ -705,35 +968,15 @@ void SPI_MasterTransferCreateHandle(SPI_Type *base,
|
|||
|
||||
uint8_t instance = SPI_GetInstance(base);
|
||||
|
||||
/* Zero the handle */
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
|
||||
/* Initialize the handle */
|
||||
s_spiHandle[instance] = handle;
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
s_spiIsr = SPI_MasterTransferHandleIRQ;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
uint8_t txSize = 0U;
|
||||
/* Get the number to be sent if there is FIFO */
|
||||
if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
|
||||
{
|
||||
txSize = (base->C3 & SPI_C3_TNEAREF_MARK_MASK) >> SPI_C3_TNEAREF_MARK_SHIFT;
|
||||
if (txSize == 0U)
|
||||
{
|
||||
handle->watermark = FSL_FEATURE_SPI_FIFO_SIZEn(base) * 3U / 4U;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle->watermark = FSL_FEATURE_SPI_FIFO_SIZEn(base) / 2U;
|
||||
}
|
||||
}
|
||||
/* If no FIFO, just set the watermark to 1 */
|
||||
else
|
||||
{
|
||||
handle->watermark = 1U;
|
||||
}
|
||||
#else
|
||||
handle->watermark = 1U;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
s_spiMasterIsr = SPI_MasterTransferHandleIRQ;
|
||||
handle->watermark = SPI_GetWatermark(base);
|
||||
|
||||
/* Get the bytes per frame */
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
|
||||
|
@ -746,6 +989,20 @@ void SPI_MasterTransferCreateHandle(SPI_Type *base,
|
|||
EnableIRQ(s_spiIRQ[instance]);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Performs a non-blocking SPI interrupt transfer.
|
||||
*
|
||||
* note The API immediately returns after transfer initialization is finished.
|
||||
* Call SPI_GetStatusIRQ() to get the transfer status.
|
||||
* note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
* param xfer pointer to spi_xfer_config_t structure
|
||||
* retval kStatus_Success Successfully start a transfer.
|
||||
* retval kStatus_InvalidArgument Input argument is invalid.
|
||||
* retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
|
||||
*/
|
||||
status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *handle, spi_transfer_t *xfer)
|
||||
{
|
||||
assert(handle && xfer);
|
||||
|
@ -763,47 +1020,76 @@ status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *hand
|
|||
}
|
||||
|
||||
/* Set the handle information */
|
||||
handle->txData = xfer->txData;
|
||||
handle->rxData = xfer->rxData;
|
||||
handle->transferSize = xfer->dataSize;
|
||||
handle->txData = xfer->txData;
|
||||
handle->rxData = xfer->rxData;
|
||||
handle->transferSize = xfer->dataSize;
|
||||
handle->txRemainingBytes = xfer->dataSize;
|
||||
handle->rxRemainingBytes = xfer->dataSize;
|
||||
|
||||
/* Set the SPI state to busy */
|
||||
handle->state = kSPI_Busy;
|
||||
|
||||
/* Disable SPI and then enable it, this is used to clear S register*/
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
base->C1 |= SPI_C1_SPE_MASK;
|
||||
|
||||
/* Enable Interrupt, only enable Rx interrupt, use rx interrupt to driver SPI transfer */
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
|
||||
handle->watermark = SPI_GetWatermark(base);
|
||||
|
||||
/* If the size of the transfer size less than watermark, set watermark to 1 */
|
||||
if (xfer->dataSize < handle->watermark * 2U)
|
||||
{
|
||||
handle->watermark = 1U;
|
||||
}
|
||||
|
||||
/* According to watermark size, enable interrupts */
|
||||
if (handle->watermark > 1U)
|
||||
{
|
||||
SPI_EnableFIFO(base, true);
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
while ((base->S & SPI_S_TNEAREF_MASK) != SPI_S_TNEAREF_MASK)
|
||||
{
|
||||
}
|
||||
SPI_SendInitialTransfer(base, handle);
|
||||
/* Enable Rx near full interrupt */
|
||||
SPI_EnableInterrupts(base, kSPI_RxFifoNearFullInterruptEnable);
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_EnableFIFO(base, false);
|
||||
while ((base->S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK)
|
||||
{
|
||||
}
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
SPI_SendInitialTransfer(base, handle);
|
||||
SPI_EnableInterrupts(base, kSPI_RxFullAndModfInterruptEnable);
|
||||
}
|
||||
#else
|
||||
while ((base->S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK)
|
||||
{
|
||||
}
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
SPI_SendInitialTransfer(base, handle);
|
||||
SPI_EnableInterrupts(base, kSPI_RxFullAndModfInterruptEnable);
|
||||
#endif
|
||||
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
SPI_SendTransfer(base, handle);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Gets the bytes of the SPI interrupt transferred.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle Pointer to SPI transfer handle, this should be a static variable.
|
||||
* param count Transferred bytes of SPI master.
|
||||
* retval kStatus_SPI_Success Succeed get the transfer count.
|
||||
* retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
|
||||
*/
|
||||
status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle, size_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
status_t status = kStatus_Success;
|
||||
|
||||
if (handle->state != kStatus_SPI_Busy)
|
||||
if (handle->state != kSPI_Busy)
|
||||
{
|
||||
status = kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
@ -823,6 +1109,12 @@ status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle,
|
|||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Aborts an SPI transfer using interrupt.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle Pointer to SPI transfer handle, this should be a static variable.
|
||||
*/
|
||||
void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -849,6 +1141,12 @@ void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle)
|
|||
handle->txRemainingBytes = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Interrupts the handler for the SPI.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle pointer to spi_master_handle_t structure which stores the transfer state.
|
||||
*/
|
||||
void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -878,6 +1176,17 @@ void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI slave handle.
|
||||
*
|
||||
* This function initializes the SPI slave handle which can be used for other SPI slave transactional APIs. Usually,
|
||||
* for a specified SPI instance, call this API once to get the initialized handle.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI handle pointer.
|
||||
* param callback Callback function.
|
||||
* param userData User data.
|
||||
*/
|
||||
void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
|
@ -888,9 +1197,15 @@ void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
|||
/* Slave create handle share same logic with master create handle, the only difference
|
||||
is the Isr pointer. */
|
||||
SPI_MasterTransferCreateHandle(base, handle, callback, userData);
|
||||
s_spiIsr = SPI_SlaveTransferHandleIRQ;
|
||||
s_spiSlaveIsr = SPI_SlaveTransferHandleIRQ;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Interrupts a handler for the SPI slave.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle pointer to spi_slave_handle_t structure which stores the transfer state
|
||||
*/
|
||||
void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -920,11 +1235,28 @@ void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle)
|
|||
}
|
||||
}
|
||||
|
||||
static void SPI_CommonIRQHandler(SPI_Type *base, uint32_t instance)
|
||||
{
|
||||
if (base->C1 & SPI_C1_MSTR_MASK)
|
||||
{
|
||||
s_spiMasterIsr(base, s_spiHandle[instance]);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_spiSlaveIsr(base, s_spiHandle[instance]);
|
||||
}
|
||||
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
||||
exception return operation might vector to incorrect interrupt */
|
||||
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
||||
__DSB();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(SPI0)
|
||||
void SPI0_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_spiHandle[0]);
|
||||
s_spiIsr(SPI0, s_spiHandle[0]);
|
||||
SPI_CommonIRQHandler(SPI0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -932,7 +1264,7 @@ void SPI0_DriverIRQHandler(void)
|
|||
void SPI1_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_spiHandle[1]);
|
||||
s_spiIsr(SPI1, s_spiHandle[1]);
|
||||
SPI_CommonIRQHandler(SPI1, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -940,6 +1272,6 @@ void SPI1_DriverIRQHandler(void)
|
|||
void SPI2_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_spiHandle[2]);
|
||||
s_spiIsr(SPI0, s_spiHandle[2]);
|
||||
SPI_CommonIRQHandler(SPI2, 2);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used tom endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_SPI_H_
|
||||
#define _FSL_SPI_H_
|
||||
|
@ -37,15 +15,14 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SPI driver version 2.0.1. */
|
||||
#define FSL_SPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
|
||||
/*! @brief SPI driver version 2.0.4. */
|
||||
#define FSL_SPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 4))
|
||||
/*@}*/
|
||||
|
||||
#ifndef SPI_DUMMYDATA
|
||||
|
@ -53,12 +30,15 @@
|
|||
#define SPI_DUMMYDATA (0xFFU)
|
||||
#endif
|
||||
|
||||
/*! @brief Global variable for dummy data value setting. */
|
||||
extern volatile uint8_t g_spiDummyData[];
|
||||
|
||||
/*! @brief Return status for the SPI driver.*/
|
||||
enum _spi_status
|
||||
{
|
||||
kStatus_SPI_Busy = MAKE_STATUS(kStatusGroup_SPI, 0), /*!< SPI bus is busy */
|
||||
kStatus_SPI_Idle = MAKE_STATUS(kStatusGroup_SPI, 1), /*!< SPI is idle */
|
||||
kStatus_SPI_Error = MAKE_STATUS(kStatusGroup_SPI, 2) /*!< SPI error */
|
||||
kStatus_SPI_Busy = MAKE_STATUS(kStatusGroup_SPI, 0), /*!< SPI bus is busy */
|
||||
kStatus_SPI_Idle = MAKE_STATUS(kStatusGroup_SPI, 1), /*!< SPI is idle */
|
||||
kStatus_SPI_Error = MAKE_STATUS(kStatusGroup_SPI, 2) /*!< SPI error */
|
||||
};
|
||||
|
||||
/*! @brief SPI clock polarity configuration.*/
|
||||
|
@ -87,16 +67,16 @@ typedef enum _spi_shift_direction
|
|||
/*! @brief SPI slave select output mode options.*/
|
||||
typedef enum _spi_ss_output_mode
|
||||
{
|
||||
kSPI_SlaveSelectAsGpio = 0x0U, /*!< Slave select pin configured as GPIO. */
|
||||
kSPI_SlaveSelectFaultInput = 0x2U, /*!< Slave select pin configured for fault detection. */
|
||||
kSPI_SlaveSelectAutomaticOutput = 0x3U /*!< Slave select pin configured for automatic SPI output. */
|
||||
kSPI_SlaveSelectAsGpio = 0x0U, /*!< Slave select pin configured as GPIO. */
|
||||
kSPI_SlaveSelectFaultInput = 0x2U, /*!< Slave select pin configured for fault detection. */
|
||||
kSPI_SlaveSelectAutomaticOutput = 0x3U /*!< Slave select pin configured for automatic SPI output. */
|
||||
} spi_ss_output_mode_t;
|
||||
|
||||
/*! @brief SPI pin mode options.*/
|
||||
typedef enum _spi_pin_mode
|
||||
{
|
||||
kSPI_PinModeNormal = 0x0U, /*!< Pins operate in normal, single-direction mode.*/
|
||||
kSPI_PinModeInput = 0x1U, /*!< Bidirectional mode. Master: MOSI pin is input;
|
||||
kSPI_PinModeInput = 0x1U, /*!< Bidirectional mode. Master: MOSI pin is input;
|
||||
* Slave: MISO pin is input. */
|
||||
kSPI_PinModeOutput = 0x3U /*!< Bidirectional mode. Master: MOSI pin is output;
|
||||
* Slave: MISO pin is output. */
|
||||
|
@ -113,10 +93,10 @@ typedef enum _spi_data_bitcount_mode
|
|||
enum _spi_interrupt_enable
|
||||
{
|
||||
kSPI_RxFullAndModfInterruptEnable = 0x1U, /*!< Receive buffer full (SPRF) and mode fault (MODF) interrupt */
|
||||
kSPI_TxEmptyInterruptEnable = 0x2U, /*!< Transmit buffer empty interrupt */
|
||||
kSPI_MatchInterruptEnable = 0x4U, /*!< Match interrupt */
|
||||
kSPI_TxEmptyInterruptEnable = 0x2U, /*!< Transmit buffer empty interrupt */
|
||||
kSPI_MatchInterruptEnable = 0x4U, /*!< Match interrupt */
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
kSPI_RxFifoNearFullInterruptEnable = 0x8U, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_RxFifoNearFullInterruptEnable = 0x8U, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_TxFifoNearEmptyInterruptEnable = 0x10U, /*!< Transmit FIFO nearly empty interrupt */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
};
|
||||
|
@ -124,44 +104,44 @@ enum _spi_interrupt_enable
|
|||
/*! @brief SPI status flags.*/
|
||||
enum _spi_flags
|
||||
{
|
||||
kSPI_RxBufferFullFlag = SPI_S_SPRF_MASK, /*!< Read buffer full flag */
|
||||
kSPI_MatchFlag = SPI_S_SPMF_MASK, /*!< Match flag */
|
||||
kSPI_RxBufferFullFlag = SPI_S_SPRF_MASK, /*!< Read buffer full flag */
|
||||
kSPI_MatchFlag = SPI_S_SPMF_MASK, /*!< Match flag */
|
||||
kSPI_TxBufferEmptyFlag = SPI_S_SPTEF_MASK, /*!< Transmit buffer empty flag */
|
||||
kSPI_ModeFaultFlag = SPI_S_MODF_MASK, /*!< Mode fault flag */
|
||||
kSPI_ModeFaultFlag = SPI_S_MODF_MASK, /*!< Mode fault flag */
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
kSPI_RxFifoNearFullFlag = SPI_S_RNFULLF_MASK, /*!< Rx FIFO near full */
|
||||
kSPI_TxFifoNearEmptyFlag = SPI_S_TNEAREF_MASK, /*!< Tx FIFO near empty */
|
||||
kSPI_TxFifoFullFlag = SPI_S_TXFULLF_MASK, /*!< Tx FIFO full */
|
||||
kSPI_RxFifoEmptyFlag = SPI_S_RFIFOEF_MASK, /*!< Rx FIFO empty */
|
||||
kSPI_TxFifoError = SPI_CI_TXFERR_MASK << 8U, /*!< Tx FIFO error */
|
||||
kSPI_RxFifoError = SPI_CI_RXFERR_MASK << 8U, /*!< Rx FIFO error */
|
||||
kSPI_TxOverflow = SPI_CI_TXFOF_MASK << 8U, /*!< Tx FIFO Overflow */
|
||||
kSPI_RxOverflow = SPI_CI_RXFOF_MASK << 8U /*!< Rx FIFO Overflow */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
kSPI_RxFifoNearFullFlag = SPI_S_RNFULLF_MASK, /*!< Rx FIFO near full */
|
||||
kSPI_TxFifoNearEmptyFlag = SPI_S_TNEAREF_MASK, /*!< Tx FIFO near empty */
|
||||
kSPI_TxFifoFullFlag = SPI_S_TXFULLF_MASK, /*!< Tx FIFO full */
|
||||
kSPI_RxFifoEmptyFlag = SPI_S_RFIFOEF_MASK, /*!< Rx FIFO empty */
|
||||
kSPI_TxFifoError = SPI_CI_TXFERR_MASK << 8U, /*!< Tx FIFO error */
|
||||
kSPI_RxFifoError = SPI_CI_RXFERR_MASK << 8U, /*!< Rx FIFO error */
|
||||
kSPI_TxOverflow = SPI_CI_TXFOF_MASK << 8U, /*!< Tx FIFO Overflow */
|
||||
kSPI_RxOverflow = SPI_CI_RXFOF_MASK << 8U /*!< Rx FIFO Overflow */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
};
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
/*! @brief SPI FIFO write-1-to-clear interrupt flags.*/
|
||||
typedef enum _spi_w1c_interrupt
|
||||
{
|
||||
kSPI_RxFifoFullClearInterrupt = SPI_CI_SPRFCI_MASK, /*!< Receive FIFO full interrupt */
|
||||
kSPI_TxFifoEmptyClearInterrupt = SPI_CI_SPTEFCI_MASK, /*!< Transmit FIFO empty interrupt */
|
||||
kSPI_RxNearFullClearInterrupt = SPI_CI_RNFULLFCI_MASK, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_TxNearEmptyClearInterrupt = SPI_CI_TNEAREFCI_MASK /*!< Transmit FIFO nearly empty interrupt */
|
||||
kSPI_RxFifoFullClearInterrupt = SPI_CI_SPRFCI_MASK, /*!< Receive FIFO full interrupt */
|
||||
kSPI_TxFifoEmptyClearInterrupt = SPI_CI_SPTEFCI_MASK, /*!< Transmit FIFO empty interrupt */
|
||||
kSPI_RxNearFullClearInterrupt = SPI_CI_RNFULLFCI_MASK, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_TxNearEmptyClearInterrupt = SPI_CI_TNEAREFCI_MASK /*!< Transmit FIFO nearly empty interrupt */
|
||||
} spi_w1c_interrupt_t;
|
||||
|
||||
/*! @brief SPI TX FIFO watermark settings.*/
|
||||
typedef enum _spi_txfifo_watermark
|
||||
{
|
||||
kSPI_TxFifoOneFourthEmpty = 0, /*!< SPI tx watermark at 1/4 FIFO size */
|
||||
kSPI_TxFifoOneHalfEmpty = 1 /*!< SPI tx watermark at 1/2 FIFO size */
|
||||
kSPI_TxFifoOneHalfEmpty = 1 /*!< SPI tx watermark at 1/2 FIFO size */
|
||||
} spi_txfifo_watermark_t;
|
||||
|
||||
/*! @brief SPI RX FIFO watermark settings.*/
|
||||
typedef enum _spi_rxfifo_watermark
|
||||
{
|
||||
kSPI_RxFifoThreeFourthsFull = 0, /*!< SPI rx watermark at 3/4 FIFO size */
|
||||
kSPI_RxFifoOneHalfFull = 1 /*!< SPI rx watermark at 1/2 FIFO size */
|
||||
kSPI_RxFifoOneHalfFull = 1 /*!< SPI rx watermark at 1/2 FIFO size */
|
||||
} spi_rxfifo_watermark_t;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
|
@ -169,8 +149,8 @@ typedef enum _spi_rxfifo_watermark
|
|||
/*! @brief SPI DMA source*/
|
||||
enum _spi_dma_enable_t
|
||||
{
|
||||
kSPI_TxDmaEnable = SPI_C2_TXDMAE_MASK, /*!< Tx DMA request source */
|
||||
kSPI_RxDmaEnable = SPI_C2_RXDMAE_MASK, /*!< Rx DMA request source */
|
||||
kSPI_TxDmaEnable = SPI_C2_TXDMAE_MASK, /*!< Tx DMA request source */
|
||||
kSPI_RxDmaEnable = SPI_C2_RXDMAE_MASK, /*!< Rx DMA request source */
|
||||
kSPI_DmaAllEnable = (SPI_C2_TXDMAE_MASK | SPI_C2_RXDMAE_MASK) /*!< All DMA request source*/
|
||||
};
|
||||
#endif /* FSL_FEATURE_SPI_HAS_DMA_SUPPORT */
|
||||
|
@ -210,6 +190,7 @@ typedef struct _spi_slave_config
|
|||
spi_txfifo_watermark_t txWatermark; /*!< Tx watermark settings */
|
||||
spi_rxfifo_watermark_t rxWatermark; /*!< Rx watermark settings */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
spi_pin_mode_t pinMode; /*!< SPI pin mode select */
|
||||
} spi_slave_config_t;
|
||||
|
||||
/*! @brief SPI transfer structure */
|
||||
|
@ -478,6 +459,27 @@ static inline uint32_t SPI_GetDataRegisterAddress(SPI_Type *base)
|
|||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Get the instance for SPI module.
|
||||
*
|
||||
* @param base SPI base address
|
||||
*/
|
||||
uint32_t SPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Sets the pin mode for transfer.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param pinMode pin mode for transfer AND #_spi_pin_mode could get the related configuration.
|
||||
*/
|
||||
static inline void SPI_SetPinMode(SPI_Type *base, spi_pin_mode_t pinMode)
|
||||
{
|
||||
/* Clear SPC0 and BIDIROE bit. */
|
||||
base->C2 &= ~(SPI_C2_BIDIROE_MASK | SPI_C2_SPC0_MASK);
|
||||
/* Set pin mode for transfer. */
|
||||
base->C2 |= SPI_C2_BIDIROE(pinMode >> 1U) | SPI_C2_SPC0(pinMode & 1U);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets the baud rate for SPI transfer. This is only used in master.
|
||||
*
|
||||
|
@ -544,6 +546,13 @@ void SPI_WriteData(SPI_Type *base, uint16_t data);
|
|||
*/
|
||||
uint16_t SPI_ReadData(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Set up the dummy data.
|
||||
*
|
||||
* @param base SPI peripheral address.
|
||||
* @param dummyData Data to be transferred when tx buffer is NULL.
|
||||
*/
|
||||
void SPI_SetDummyData(SPI_Type *base, uint8_t dummyData);
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
|
@ -582,11 +591,7 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer);
|
|||
*
|
||||
* @note The API immediately returns after transfer initialization is finished.
|
||||
* Call SPI_GetStatusIRQ() to get the transfer status.
|
||||
* @note If using the SPI with FIFO for the interrupt transfer, the transfer size is the integer times of the watermark.
|
||||
* Otherwise,
|
||||
* the last data may be lost because it cannot generate an interrupt request. Users can also call the functional API to
|
||||
* get the last
|
||||
* received data.
|
||||
* @note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
|
@ -636,8 +641,8 @@ void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle);
|
|||
* @param userData User data.
|
||||
*/
|
||||
void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
void *userData);
|
||||
|
||||
/*!
|
||||
|
@ -645,11 +650,7 @@ void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
|||
*
|
||||
* @note The API returns immediately after the transfer initialization is finished.
|
||||
* Call SPI_GetStatusIRQ() to get the transfer status.
|
||||
* @note If using the SPI with FIFO for the interrupt transfer, the transfer size is the integer times the watermark.
|
||||
* Otherwise,
|
||||
* the last data may be lost because it cannot generate an interrupt request. Call the functional API to get the last
|
||||
* several
|
||||
* receive data.
|
||||
* @note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
|
|
|
@ -1,38 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_spi_dma.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitons
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.spi_dma"
|
||||
#endif
|
||||
|
||||
/*<! Structure definition for spi_dma_private_handle_t. The structure is private. */
|
||||
typedef struct _spi_dma_private_handle
|
||||
{
|
||||
|
@ -52,13 +36,6 @@ static spi_dma_private_handle_t s_dmaPrivateHandle[FSL_FEATURE_SOC_SPI_COUNT];
|
|||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Get the instance for SPI module.
|
||||
*
|
||||
* @param base SPI base address
|
||||
*/
|
||||
extern uint32_t SPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief DMA callback function for SPI send transfer.
|
||||
*
|
||||
|
@ -76,25 +53,18 @@ static void SPI_TxDMACallback(dma_handle_t *handle, void *userData);
|
|||
static void SPI_RxDMACallback(dma_handle_t *handle, void *userData);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
/* Dummy data used to send */
|
||||
static const uint8_t s_dummyData = SPI_DUMMYDATA;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static void SPI_TxDMACallback(dma_handle_t *handle, void *userData)
|
||||
{
|
||||
spi_dma_private_handle_t *privHandle = (spi_dma_private_handle_t *)userData;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
|
||||
/* Disable Tx dma */
|
||||
SPI_EnableDMA(base, kSPI_TxDmaEnable, false);
|
||||
|
||||
/* Stop DMA tranfer */
|
||||
/* Stop DMA transfer */
|
||||
DMA_StopTransfer(spiHandle->txHandle);
|
||||
|
||||
/* change the state */
|
||||
|
@ -114,13 +84,13 @@ static void SPI_TxDMACallback(dma_handle_t *handle, void *userData)
|
|||
static void SPI_RxDMACallback(dma_handle_t *handle, void *userData)
|
||||
{
|
||||
spi_dma_private_handle_t *privHandle = (spi_dma_private_handle_t *)userData;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
|
||||
/* Disable Tx dma */
|
||||
SPI_EnableDMA(base, kSPI_RxDmaEnable, false);
|
||||
|
||||
/* Stop DMA tranfer */
|
||||
/* Stop DMA transfer */
|
||||
DMA_StopTransfer(spiHandle->rxHandle);
|
||||
|
||||
/* change the state */
|
||||
|
@ -137,6 +107,19 @@ static void SPI_RxDMACallback(dma_handle_t *handle, void *userData)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initialize the SPI master DMA handle.
|
||||
*
|
||||
* This function initializes the SPI master DMA handle which can be used for other SPI master transactional APIs.
|
||||
* Usually, for a specified SPI instance, user need only call this API once to get the initialized handle.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI handle pointer.
|
||||
* param callback User callback function called at the end of a transfer.
|
||||
* param userData User data for callback.
|
||||
* param txHandle DMA handle pointer for SPI Tx, the handle shall be static allocated by users.
|
||||
* param rxHandle DMA handle pointer for SPI Rx, the handle shall be static allocated by users.
|
||||
*/
|
||||
void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
||||
spi_dma_handle_t *handle,
|
||||
spi_dma_callback_t callback,
|
||||
|
@ -146,7 +129,10 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
{
|
||||
assert(handle);
|
||||
dma_transfer_config_t config = {0};
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
|
||||
/* Zero the handle */
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
|
||||
/* Set spi base to handle */
|
||||
handle->txHandle = txHandle;
|
||||
|
@ -158,7 +144,7 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
handle->state = kSPI_Idle;
|
||||
|
||||
/* Set handle to global state */
|
||||
s_dmaPrivateHandle[instance].base = base;
|
||||
s_dmaPrivateHandle[instance].base = base;
|
||||
s_dmaPrivateHandle[instance].handle = handle;
|
||||
|
||||
/* Compute internal state */
|
||||
|
@ -180,27 +166,27 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
/* Set the non-change attribute for Tx DMA transfer, to improve efficiency */
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.enableDestIncrement = false;
|
||||
config.enableSrcIncrement = true;
|
||||
config.enableSrcIncrement = true;
|
||||
if (handle->bytesPerFrame == 1U)
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.destSize = kDMA_Transfersize8bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.destSize = kDMA_Transfersize16bits;
|
||||
}
|
||||
|
||||
DMA_SubmitTransfer(handle->txHandle, &config, true);
|
||||
|
||||
/* Set non-change attribute for Rx DMA */
|
||||
config.srcAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = 0U;
|
||||
config.srcAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = 0U;
|
||||
config.enableDestIncrement = true;
|
||||
config.enableSrcIncrement = false;
|
||||
config.enableSrcIncrement = false;
|
||||
DMA_SubmitTransfer(handle->rxHandle, &config, true);
|
||||
|
||||
/* Install callback for Tx dma channel */
|
||||
|
@ -208,6 +194,19 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
DMA_SetCallback(handle->rxHandle, SPI_RxDMACallback, &s_dmaPrivateHandle[instance]);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Perform a non-blocking SPI transfer using DMA.
|
||||
*
|
||||
* note This interface returned immediately after transfer initiates, users should call
|
||||
* SPI_GetTransferStatus to poll the transfer status to check whether SPI transfer finished.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI DMA handle pointer.
|
||||
* param xfer Pointer to dma transfer structure.
|
||||
* retval kStatus_Success Successfully start a transfer.
|
||||
* retval kStatus_InvalidArgument Input argument is invalid.
|
||||
* retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
|
||||
*/
|
||||
status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_transfer_t *xfer)
|
||||
{
|
||||
assert(handle && xfer);
|
||||
|
@ -231,16 +230,16 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
SPI_Enable(base, true);
|
||||
|
||||
/* Configure tx transfer DMA */
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.enableDestIncrement = false;
|
||||
if (handle->bytesPerFrame == 1U)
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.destSize = kDMA_Transfersize8bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.destSize = kDMA_Transfersize16bits;
|
||||
}
|
||||
config.transferSize = xfer->dataSize;
|
||||
|
@ -248,13 +247,13 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
if (xfer->txData)
|
||||
{
|
||||
config.enableSrcIncrement = true;
|
||||
config.srcAddr = (uint32_t)(xfer->txData);
|
||||
config.srcAddr = (uint32_t)(xfer->txData);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the source increasement and source set to dummyData */
|
||||
config.enableSrcIncrement = false;
|
||||
config.srcAddr = (uint32_t)(&s_dummyData);
|
||||
config.srcAddr = (uint32_t)(&g_spiDummyData[SPI_GetInstance(base)]);
|
||||
}
|
||||
DMA_SubmitTransfer(handle->txHandle, &config, true);
|
||||
|
||||
|
@ -270,7 +269,7 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
|
||||
/* Change the state of handle */
|
||||
handle->transferSize = xfer->dataSize;
|
||||
handle->state = kSPI_Busy;
|
||||
handle->state = kSPI_Busy;
|
||||
|
||||
/* Start Rx transfer if needed */
|
||||
if (xfer->rxData)
|
||||
|
@ -288,6 +287,15 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Get the transferred bytes for SPI slave DMA.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI DMA handle pointer.
|
||||
* param count Transferred bytes.
|
||||
* retval kStatus_SPI_Success Succeed get the transfer count.
|
||||
* retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
|
||||
*/
|
||||
status_t SPI_MasterTransferGetCountDMA(SPI_Type *base, spi_dma_handle_t *handle, size_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -313,6 +321,12 @@ status_t SPI_MasterTransferGetCountDMA(SPI_Type *base, spi_dma_handle_t *handle,
|
|||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Abort a SPI transfer using DMA.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI DMA handle pointer.
|
||||
*/
|
||||
void SPI_MasterTransferAbortDMA(SPI_Type *base, spi_dma_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -327,5 +341,5 @@ void SPI_MasterTransferAbortDMA(SPI_Type *base, spi_dma_handle_t *handle)
|
|||
/* Set the handle state */
|
||||
handle->txInProgress = false;
|
||||
handle->rxInProgress = false;
|
||||
handle->state = kSPI_Idle;
|
||||
handle->state = kSPI_Idle;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_SPI_DMA_H_
|
||||
#define _FSL_SPI_DMA_H_
|
||||
|
@ -38,11 +16,16 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SPI DMA driver version 2.0.4. */
|
||||
#define FSL_SPI_DMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 4))
|
||||
/*@}*/
|
||||
|
||||
typedef struct _spi_dma_handle spi_dma_handle_t;
|
||||
|
||||
/*! @brief SPI DMA callback called at the end of transfer. */
|
||||
|
@ -55,7 +38,7 @@ struct _spi_dma_handle
|
|||
bool rxInProgress; /*!< Receive transfer finished */
|
||||
dma_handle_t *txHandle; /*!< DMA handler for SPI send */
|
||||
dma_handle_t *rxHandle; /*!< DMA handler for SPI receive */
|
||||
uint8_t bytesPerFrame; /*!< Bytes in a frame for SPI tranfer */
|
||||
uint8_t bytesPerFrame; /*!< Bytes in a frame for SPI transfer */
|
||||
spi_dma_callback_t callback; /*!< Callback for SPI DMA transfer */
|
||||
void *userData; /*!< User Data for SPI DMA callback */
|
||||
uint32_t state; /*!< Internal state of SPI DMA transfer */
|
||||
|
|
|
@ -288,4 +288,14 @@ const PinMap *serial_rts_pinmap()
|
|||
return PinMap_UART_RTS;
|
||||
}
|
||||
|
||||
void serial_wait_tx_complete(uint32_t uart_index)
|
||||
{
|
||||
LPUART_Type *base = uart_addrs[uart_index];
|
||||
|
||||
/* Wait till data is flushed out of transmit buffer */
|
||||
while (!(kLPUART_TransmissionCompleteFlag & LPUART_GetStatusFlags((LPUART_Type *)base)))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -116,16 +116,18 @@ int spi_master_write(spi_t *obj, int value)
|
|||
}
|
||||
|
||||
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
|
||||
char *rx_buffer, int rx_length, char write_fill) {
|
||||
char *rx_buffer, int rx_length, char write_fill)
|
||||
{
|
||||
int total = (tx_length > rx_length) ? tx_length : rx_length;
|
||||
|
||||
for (int i = 0; i < total; i++) {
|
||||
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
|
||||
char in = spi_master_write(obj, out);
|
||||
if (i < rx_length) {
|
||||
rx_buffer[i] = in;
|
||||
}
|
||||
}
|
||||
// Default write is done in each and every call, in future can create HAL API instead
|
||||
SPI_SetDummyData(spi_address[obj->instance], write_fill);
|
||||
|
||||
SPI_MasterTransferBlocking(spi_address[obj->instance], &(spi_transfer_t) {
|
||||
.txData = (uint8_t *)tx_buffer,
|
||||
.rxData = (uint8_t *)rx_buffer,
|
||||
.dataSize = total
|
||||
});
|
||||
|
||||
return total;
|
||||
}
|
||||
|
|
|
@ -1,60 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_smc.h"
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.smc"
|
||||
#endif
|
||||
|
||||
typedef void (*smc_stop_ram_func_t)(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
static void SMC_EnterStopRamFunc(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
static uint32_t g_savedPrimask;
|
||||
|
||||
/*
|
||||
* The ram function code is:
|
||||
*
|
||||
* uint32_t i;
|
||||
* for (i=0; i<0x8; i++)
|
||||
* {
|
||||
* __NOP();
|
||||
* }
|
||||
* __DSB();
|
||||
* __WFI();
|
||||
* __ISB();
|
||||
*
|
||||
* When entring the stop modes, the flash prefetch might be interrupted, thus
|
||||
* the prefetched code or data might be broken. To make sure the flash is idle
|
||||
* when entring the stop modes, the code is moved to ram. And delay for a while
|
||||
* before WFI to make sure previous flash prefetch is finished.
|
||||
*
|
||||
* Only need to do like this when code is in flash, if code is in rom or ram,
|
||||
* this is not necessary.
|
||||
*/
|
||||
static uint16_t s_stopRamFuncArray[] = {
|
||||
0x2000, /* MOVS R0, #0 */
|
||||
0x2808, /* CMP R0, #8 */
|
||||
0xD202, /* BCS.N */
|
||||
0xBF00, /* NOP */
|
||||
0x1C40, /* ADDS R0, R0, #1 */
|
||||
0xE7FA, /* B.N */
|
||||
0xF3BF, 0x8F4F, /* DSB */
|
||||
0xBF30, /* WFI */
|
||||
0xF3BF, 0x8F6F, /* ISB */
|
||||
0x4770, /* BX LR */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static void SMC_EnterStopRamFunc(void)
|
||||
{
|
||||
uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U;
|
||||
smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry;
|
||||
stopRamFunc();
|
||||
}
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM)
|
||||
/*!
|
||||
* brief Gets the SMC parameter.
|
||||
*
|
||||
* This function gets the SMC parameter including the enabled power mdoes.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* param param Pointer to the SMC param structure.
|
||||
*/
|
||||
void SMC_GetParam(SMC_Type *base, smc_param_t *param)
|
||||
{
|
||||
uint32_t reg = base->PARAM;
|
||||
uint32_t reg = base->PARAM;
|
||||
param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK);
|
||||
param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK);
|
||||
param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK);
|
||||
param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK);
|
||||
param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK);
|
||||
param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK);
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_PARAM */
|
||||
|
||||
/*!
|
||||
* brief Prepares to enter stop modes.
|
||||
*
|
||||
* This function should be called before entering STOP/VLPS/LLS/VLLS modes.
|
||||
*/
|
||||
void SMC_PreEnterStopModes(void)
|
||||
{
|
||||
g_savedPrimask = DisableGlobalIRQ();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Recovers after wake up from stop modes.
|
||||
*
|
||||
* This function should be called after wake up from STOP/VLPS/LLS/VLLS modes.
|
||||
* It is used with ref SMC_PreEnterStopModes.
|
||||
*/
|
||||
void SMC_PostExitStopModes(void)
|
||||
{
|
||||
EnableGlobalIRQ(g_savedPrimask);
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Prepares to enter wait modes.
|
||||
*
|
||||
* This function should be called before entering WAIT/VLPW modes.
|
||||
*/
|
||||
void SMC_PreEnterWaitModes(void)
|
||||
{
|
||||
g_savedPrimask = DisableGlobalIRQ();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Recovers after wake up from stop modes.
|
||||
*
|
||||
* This function should be called after wake up from WAIT/VLPW modes.
|
||||
* It is used with ref SMC_PreEnterWaitModes.
|
||||
*/
|
||||
void SMC_PostExitWaitModes(void)
|
||||
{
|
||||
EnableGlobalIRQ(g_savedPrimask);
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to RUN power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeRun(SMC_Type *base)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
reg = base->PMCTRL;
|
||||
/* configure Normal RUN mode */
|
||||
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
/*!
|
||||
* brief Configures the system to HSRUN power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeHsrun(SMC_Type *base)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
@ -62,38 +170,53 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base)
|
|||
reg = base->PMCTRL;
|
||||
/* configure High Speed RUN mode */
|
||||
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
|
||||
reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
|
||||
/*!
|
||||
* brief Configures the system to WAIT power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeWait(SMC_Type *base)
|
||||
{
|
||||
/* configure Normal Wait mode */
|
||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to Stop power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* param option Partial Stop mode option.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO)
|
||||
/* configure the Partial Stop mode in Noraml Stop mode */
|
||||
/* configure the Partial Stop mode in Normal Stop mode */
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_PSTOPO_MASK;
|
||||
reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK;
|
||||
reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#endif
|
||||
|
||||
/* configure Normal Stop mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */
|
||||
|
@ -101,10 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__WFI();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter Stop mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
@ -114,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to VLPR power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlpr(SMC_Type *base
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)
|
||||
,
|
||||
bool wakeupMode
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
|
@ -134,42 +263,50 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base
|
|||
else
|
||||
{
|
||||
/* remains in VLP mode on an interrupt */
|
||||
reg &= ~SMC_PMCTRL_LPWUI_MASK;
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK;
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LPWUI */
|
||||
|
||||
/* configure VLPR mode */
|
||||
reg &= ~SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK;
|
||||
reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to VLPW power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlpw(SMC_Type *base)
|
||||
{
|
||||
/* Power mode transaction to VLPW can only happen in VLPR mode */
|
||||
if (kSMC_PowerStateVlpr != SMC_GetPowerModeState(base))
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
/* configure VLPW mode */
|
||||
/* Set the SLEEPDEEP bit to enable deep sleep mode */
|
||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Configures the system to VLPS power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
/* configure VLPS mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* Set the SLEEPDEEP bit to enable deep sleep mode */
|
||||
|
@ -177,10 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__WFI();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter VLPS mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
@ -191,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base)
|
|||
}
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
/*!
|
||||
* brief Configures the system to LLS power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeLls(SMC_Type *base
|
||||
#if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \
|
||||
(defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO))
|
||||
,
|
||||
const smc_power_mode_lls_config_t *config
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
/* configure to LLS mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* configure LLS sub-mode*/
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
|
||||
|
||||
|
@ -231,10 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__WFI();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter LLS mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
@ -246,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base
|
|||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
/*!
|
||||
* brief Configures the system to VLLS power mode.
|
||||
*
|
||||
* param base SMC peripheral base address.
|
||||
* param config The VLLS power mode configuration structure.
|
||||
* return SMC configuration error code.
|
||||
*/
|
||||
status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
@ -258,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
#endif
|
||||
{
|
||||
/* configure whether the Por Detect work in Vlls0 mode */
|
||||
if (config->enablePorDetectInVlls0)
|
||||
if (true == config->enablePorDetectInVlls0)
|
||||
{
|
||||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK;
|
||||
#else
|
||||
base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK;
|
||||
base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -281,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
else if (config->subMode == kSMC_StopSub2)
|
||||
{
|
||||
/* configure whether the Por Detect work in Vlls0 mode */
|
||||
if (config->enableRam2InVlls2)
|
||||
if (true == config->enableRam2InVlls2)
|
||||
{
|
||||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK;
|
||||
|
@ -294,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK;
|
||||
#else
|
||||
base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK;
|
||||
base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */
|
||||
}
|
||||
#endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */
|
||||
|
||||
/* configure to VLLS mode */
|
||||
reg = base->PMCTRL;
|
||||
reg &= ~SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK;
|
||||
reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
|
||||
base->PMCTRL = reg;
|
||||
|
||||
/* configure the VLLS sub-mode */
|
||||
#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
|
||||
reg = base->VLLSCTRL;
|
||||
reg &= ~SMC_VLLSCTRL_VLLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT);
|
||||
reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT);
|
||||
base->VLLSCTRL = reg;
|
||||
#else
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK;
|
||||
reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#else
|
||||
reg = base->STOPCTRL;
|
||||
reg &= ~SMC_STOPCTRL_VLLSM_MASK;
|
||||
reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT);
|
||||
reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT);
|
||||
base->STOPCTRL = reg;
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
|
||||
#endif
|
||||
|
@ -345,10 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t
|
|||
|
||||
/* read back to make sure the configuration valid before enter stop mode */
|
||||
(void)base->PMCTRL;
|
||||
__WFI();
|
||||
SMC_EnterStopRamFunc();
|
||||
|
||||
/* check whether the power mode enter LLS mode succeed */
|
||||
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
|
||||
if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
|
||||
{
|
||||
return kStatus_SMC_StopAbort;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef _FSL_SMC_H_
|
||||
|
@ -36,16 +14,14 @@
|
|||
/*! @addtogroup smc */
|
||||
/*! @{ */
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SMC driver version 2.0.1. */
|
||||
#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
|
||||
/*! @brief SMC driver version 2.0.5. */
|
||||
#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5))
|
||||
/*@}*/
|
||||
|
||||
/*!
|
||||
|
@ -54,29 +30,25 @@
|
|||
typedef enum _smc_power_mode_protection
|
||||
{
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-Low-Leakage Stop Mode. */
|
||||
kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-low-leakage Stop Mode. */
|
||||
#endif
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-Leakage Stop Mode. */
|
||||
kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-leakage Stop Mode. */
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-Power Mode. */
|
||||
kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-power Mode. */
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High Speed Run mode. */
|
||||
kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High-speed Run mode. */
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
kSMC_AllowPowerModeAll = (0U
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
|
|
||||
SMC_PMPROT_AVLLS_MASK
|
||||
| SMC_PMPROT_AVLLS_MASK
|
||||
#endif
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
|
|
||||
SMC_PMPROT_ALLS_MASK
|
||||
| SMC_PMPROT_ALLS_MASK
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
|
|
||||
SMC_PMPROT_AVLP_MASK
|
||||
| SMC_PMPROT_AVLP_MASK
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
|
|
||||
kSMC_AllowPowerModeHsrun
|
||||
| kSMC_AllowPowerModeHsrun
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
) /*!< Allow all power mode. */
|
||||
} smc_power_mode_protection_t;
|
||||
|
@ -86,7 +58,7 @@ typedef enum _smc_power_mode_protection
|
|||
*/
|
||||
typedef enum _smc_power_state
|
||||
{
|
||||
kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */
|
||||
kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */
|
||||
kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */
|
||||
kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */
|
||||
kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */
|
||||
|
@ -107,10 +79,10 @@ typedef enum _smc_power_state
|
|||
*/
|
||||
typedef enum _smc_run_mode
|
||||
{
|
||||
kSMC_RunNormal = 0U, /*!< normal RUN mode. */
|
||||
kSMC_RunVlpr = 2U, /*!< Very-Low-Power RUN mode. */
|
||||
kSMC_RunNormal = 0U, /*!< Normal RUN mode. */
|
||||
kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
kSMC_Hsrun = 3U /*!< High Speed Run mode (HSRUN). */
|
||||
kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */
|
||||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
} smc_run_mode_t;
|
||||
|
||||
|
@ -120,12 +92,12 @@ typedef enum _smc_run_mode
|
|||
typedef enum _smc_stop_mode
|
||||
{
|
||||
kSMC_StopNormal = 0U, /*!< Normal STOP mode. */
|
||||
kSMC_StopVlps = 2U, /*!< Very-Low-Power STOP mode. */
|
||||
kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
|
||||
kSMC_StopLls = 3U, /*!< Low-Leakage Stop mode. */
|
||||
kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */
|
||||
#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
kSMC_StopVlls = 4U /*!< Very-Low-Leakage Stop mode. */
|
||||
kSMC_StopVlls = 4U /*!< Very-low-leakage Stop mode. */
|
||||
#endif
|
||||
} smc_stop_mode_t;
|
||||
|
||||
|
@ -149,13 +121,13 @@ typedef enum _smc_stop_submode
|
|||
*/
|
||||
typedef enum _smc_partial_stop_mode
|
||||
{
|
||||
kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/
|
||||
kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/
|
||||
kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/
|
||||
kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/
|
||||
} smc_partial_stop_option_t;
|
||||
|
||||
/*!
|
||||
* @brief SMC configuration status
|
||||
* @brief SMC configuration status.
|
||||
*/
|
||||
enum _smc_status
|
||||
{
|
||||
|
@ -190,7 +162,7 @@ typedef struct _smc_param
|
|||
#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \
|
||||
(defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)
|
||||
/*!
|
||||
* @brief SMC Low-Leakage Stop power mode config
|
||||
* @brief SMC Low-Leakage Stop power mode configuration.
|
||||
*/
|
||||
typedef struct _smc_power_mode_lls_config
|
||||
{
|
||||
|
@ -205,7 +177,7 @@ typedef struct _smc_power_mode_lls_config
|
|||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
/*!
|
||||
* @brief SMC Very Low-Leakage Stop power mode config
|
||||
* @brief SMC Very Low-Leakage Stop power mode configuration.
|
||||
*/
|
||||
typedef struct _smc_power_mode_vlls_config
|
||||
{
|
||||
|
@ -242,10 +214,10 @@ extern "C" {
|
|||
* @brief Gets the SMC version ID.
|
||||
*
|
||||
* This function gets the SMC version ID, including major version number,
|
||||
* minor version number and feature specification number.
|
||||
* minor version number, and feature specification number.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @param versionId Pointer to version ID structure.
|
||||
* @param versionId Pointer to the version ID structure.
|
||||
*/
|
||||
static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId)
|
||||
{
|
||||
|
@ -257,10 +229,10 @@ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId)
|
|||
/*!
|
||||
* @brief Gets the SMC parameter.
|
||||
*
|
||||
* This function gets the SMC parameter, including the enabled power mdoes.
|
||||
* This function gets the SMC parameter including the enabled power mdoes.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @param param Pointer to SMC param structure.
|
||||
* @param param Pointer to the SMC param structure.
|
||||
*/
|
||||
void SMC_GetParam(SMC_Type *base, smc_param_t *param);
|
||||
#endif
|
||||
|
@ -274,7 +246,7 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param);
|
|||
* system level initialization stage. See the reference manual for details.
|
||||
* This register can only write once after the power reset.
|
||||
*
|
||||
* The allowed modes are passed as bit map, for example, to allow LLS and VLLS,
|
||||
* The allowed modes are passed as bit map. For example, to allow LLS and VLLS,
|
||||
* use SMC_SetPowerModeProtection(kSMC_AllowPowerModeVlls | kSMC_AllowPowerModeVlps).
|
||||
* To allow all modes, use SMC_SetPowerModeProtection(kSMC_AllowPowerModeAll).
|
||||
*
|
||||
|
@ -289,13 +261,13 @@ static inline void SMC_SetPowerModeProtection(SMC_Type *base, uint8_t allowedMod
|
|||
/*!
|
||||
* @brief Gets the current power mode status.
|
||||
*
|
||||
* This function returns the current power mode stat. Once application
|
||||
* switches the power mode, it should always check the stat to check whether it
|
||||
* runs into the specified mode or not. An application should check
|
||||
* This function returns the current power mode status. After the application
|
||||
* switches the power mode, it should always check the status to check whether it
|
||||
* runs into the specified mode or not. The application should check
|
||||
* this mode before switching to a different mode. The system requires that
|
||||
* only certain modes can switch to other specific modes. See the
|
||||
* reference manual for details and the smc_power_state_t for information about
|
||||
* the power stat.
|
||||
* the power status.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return Current power mode status.
|
||||
|
@ -306,7 +278,37 @@ static inline smc_power_state_t SMC_GetPowerModeState(SMC_Type *base)
|
|||
}
|
||||
|
||||
/*!
|
||||
* @brief Configure the system to RUN power mode.
|
||||
* @brief Prepares to enter stop modes.
|
||||
*
|
||||
* This function should be called before entering STOP/VLPS/LLS/VLLS modes.
|
||||
*/
|
||||
void SMC_PreEnterStopModes(void);
|
||||
|
||||
/*!
|
||||
* @brief Recovers after wake up from stop modes.
|
||||
*
|
||||
* This function should be called after wake up from STOP/VLPS/LLS/VLLS modes.
|
||||
* It is used with @ref SMC_PreEnterStopModes.
|
||||
*/
|
||||
void SMC_PostExitStopModes(void);
|
||||
|
||||
/*!
|
||||
* @brief Prepares to enter wait modes.
|
||||
*
|
||||
* This function should be called before entering WAIT/VLPW modes.
|
||||
*/
|
||||
void SMC_PreEnterWaitModes(void);
|
||||
|
||||
/*!
|
||||
* @brief Recovers after wake up from stop modes.
|
||||
*
|
||||
* This function should be called after wake up from WAIT/VLPW modes.
|
||||
* It is used with @ref SMC_PreEnterWaitModes.
|
||||
*/
|
||||
void SMC_PostExitWaitModes(void);
|
||||
|
||||
/*!
|
||||
* @brief Configures the system to RUN power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -315,7 +317,7 @@ status_t SMC_SetPowerModeRun(SMC_Type *base);
|
|||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
|
||||
/*!
|
||||
* @brief Configure the system to HSRUN power mode.
|
||||
* @brief Configures the system to HSRUN power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -324,7 +326,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base);
|
|||
#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
|
||||
|
||||
/*!
|
||||
* @brief Configure the system to WAIT power mode.
|
||||
* @brief Configures the system to WAIT power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -332,7 +334,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base);
|
|||
status_t SMC_SetPowerModeWait(SMC_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Configure the system to Stop power mode.
|
||||
* @brief Configures the system to Stop power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @param option Partial Stop mode option.
|
||||
|
@ -342,7 +344,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option);
|
|||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)
|
||||
/*!
|
||||
* @brief Configure the system to VLPR power mode.
|
||||
* @brief Configures the system to VLPR power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @param wakeupMode Enter Normal Run mode if true, else stay in VLPR mode.
|
||||
|
@ -351,7 +353,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option);
|
|||
status_t SMC_SetPowerModeVlpr(SMC_Type *base, bool wakeupMode);
|
||||
#else
|
||||
/*!
|
||||
* @brief Configure the system to VLPR power mode.
|
||||
* @brief Configures the system to VLPR power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -360,7 +362,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base);
|
|||
#endif /* FSL_FEATURE_SMC_HAS_LPWUI */
|
||||
|
||||
/*!
|
||||
* @brief Configure the system to VLPW power mode.
|
||||
* @brief Configures the system to VLPW power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -368,7 +370,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base);
|
|||
status_t SMC_SetPowerModeVlpw(SMC_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Configure the system to VLPS power mode.
|
||||
* @brief Configures the system to VLPS power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -379,7 +381,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base);
|
|||
#if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \
|
||||
(defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO))
|
||||
/*!
|
||||
* @brief Configure the system to LLS power mode.
|
||||
* @brief Configures the system to LLS power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @param config The LLS power mode configuration structure
|
||||
|
@ -388,7 +390,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base);
|
|||
status_t SMC_SetPowerModeLls(SMC_Type *base, const smc_power_mode_lls_config_t *config);
|
||||
#else
|
||||
/*!
|
||||
* @brief Configure the system to LLS power mode.
|
||||
* @brief Configures the system to LLS power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @return SMC configuration error code.
|
||||
|
@ -399,7 +401,7 @@ status_t SMC_SetPowerModeLls(SMC_Type *base);
|
|||
|
||||
#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
|
||||
/*!
|
||||
* @brief Configure the system to VLLS power mode.
|
||||
* @brief Configures the system to VLLS power mode.
|
||||
*
|
||||
* @param base SMC peripheral base address.
|
||||
* @param config The VLLS power mode configuration structure.
|
||||
|
|
|
@ -1,38 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_spi.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitons
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.spi"
|
||||
#endif
|
||||
|
||||
/*! @brief SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
|
||||
enum _spi_transfer_states_t
|
||||
{
|
||||
|
@ -46,12 +30,6 @@ typedef void (*spi_isr_t)(SPI_Type *base, spi_master_handle_t *spiHandle);
|
|||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Get the instance for SPI module.
|
||||
*
|
||||
* @param base SPI base address
|
||||
*/
|
||||
uint32_t SPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Sends a buffer of data bytes in non-blocking way.
|
||||
|
@ -71,6 +49,14 @@ static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
|
|||
*/
|
||||
static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
|
||||
|
||||
/*!
|
||||
* @brief Get the waterrmark value for this SPI instance.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @return Watermark value for the SPI instance.
|
||||
*/
|
||||
static uint8_t SPI_GetWatermark(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Send a piece of data for SPI.
|
||||
*
|
||||
|
@ -78,6 +64,7 @@ static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
|
|||
* and write the data into it. At the same time, this function updates the values in
|
||||
* master handle structure.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param handle Pointer to SPI master handle structure.
|
||||
*/
|
||||
static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle);
|
||||
|
@ -89,9 +76,18 @@ static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle);
|
|||
* and write the data to destination address. At the same time, this function updates
|
||||
* the values in master handle structure.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param handle Pointer to SPI master handle structure.
|
||||
*/
|
||||
static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Common IRQ handler for SPI.
|
||||
*
|
||||
* @param base SPI base pointer.
|
||||
* @param instance SPI instance number.
|
||||
*/
|
||||
static void SPI_CommonIRQHandler(SPI_Type *base, uint32_t instance);
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
@ -101,21 +97,31 @@ static spi_master_handle_t *s_spiHandle[FSL_FEATURE_SOC_SPI_COUNT];
|
|||
static SPI_Type *const s_spiBases[] = SPI_BASE_PTRS;
|
||||
/*! @brief IRQ name array */
|
||||
static const IRQn_Type s_spiIRQ[] = SPI_IRQS;
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/*! @brief Clock array name */
|
||||
static const clock_ip_name_t s_spiClock[] = SPI_CLOCKS;
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
/*! @brief Pointer to master IRQ handler for each instance. */
|
||||
static spi_isr_t s_spiIsr;
|
||||
static spi_isr_t s_spiMasterIsr;
|
||||
static spi_isr_t s_spiSlaveIsr;
|
||||
|
||||
/* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/
|
||||
volatile uint8_t g_spiDummyData[ARRAY_SIZE(s_spiBases)] = {0};
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* brief Get the instance for SPI module.
|
||||
*
|
||||
* param base SPI base address
|
||||
*/
|
||||
uint32_t SPI_GetInstance(SPI_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
/* Find the instance index from base address mappings. */
|
||||
for (instance = 0; instance < FSL_FEATURE_SOC_SPI_COUNT; instance++)
|
||||
for (instance = 0; instance < ARRAY_SIZE(s_spiBases); instance++)
|
||||
{
|
||||
if (s_spiBases[instance] == base)
|
||||
{
|
||||
|
@ -123,15 +129,28 @@ uint32_t SPI_GetInstance(SPI_Type *base)
|
|||
}
|
||||
}
|
||||
|
||||
assert(instance < FSL_FEATURE_SOC_SPI_COUNT);
|
||||
assert(instance < ARRAY_SIZE(s_spiBases));
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Set up the dummy data.
|
||||
*
|
||||
* param base SPI peripheral address.
|
||||
* param dummyData Data to be transferred when tx buffer is NULL.
|
||||
*/
|
||||
void SPI_SetDummyData(SPI_Type *base, uint8_t dummyData)
|
||||
{
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
g_spiDummyData[instance] = dummyData;
|
||||
}
|
||||
|
||||
static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0;
|
||||
uint8_t bytesPerFrame = 1U;
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
/* Check if 16 bits or 8 bits */
|
||||
|
@ -155,13 +174,13 @@ static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
base->DL = *buffer++;
|
||||
}
|
||||
#else
|
||||
base->D = *buffer++;
|
||||
base->D = *buffer++;
|
||||
#endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
|
||||
}
|
||||
/* Send dummy data */
|
||||
else
|
||||
{
|
||||
SPI_WriteData(base, SPI_DUMMYDATA);
|
||||
SPI_WriteData(base, ((uint32_t)g_spiDummyData[instance] << 8 | g_spiDummyData[instance]));
|
||||
}
|
||||
i += bytesPerFrame;
|
||||
}
|
||||
|
@ -169,7 +188,7 @@ static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
|
||||
static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0;
|
||||
uint8_t bytesPerFrame = 1U;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
|
@ -205,18 +224,68 @@ static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
}
|
||||
}
|
||||
|
||||
/* Get the watermark value of transfer. Please note that the entery width of FIFO is 16 bits. */
|
||||
static uint8_t SPI_GetWatermark(SPI_Type *base)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
uint8_t rxSize = 0U;
|
||||
/* Get the number to be sent if there is FIFO */
|
||||
if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
|
||||
{
|
||||
rxSize = (base->C3 & SPI_C3_RNFULLF_MARK_MASK) >> SPI_C3_RNFULLF_MARK_SHIFT;
|
||||
if (rxSize == 0U)
|
||||
{
|
||||
ret = FSL_FEATURE_SPI_FIFO_SIZEn(base) * 3U / 4U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = FSL_FEATURE_SPI_FIFO_SIZEn(base) / 2U;
|
||||
}
|
||||
}
|
||||
/* If no FIFO, just set the watermark to 1 */
|
||||
else
|
||||
{
|
||||
ret = 1U;
|
||||
}
|
||||
#else
|
||||
ret = 1U;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void SPI_SendInitialTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint8_t bytestoTransfer = handle->bytePerFrame;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
|
||||
if (handle->watermark > 1)
|
||||
{
|
||||
/* In the first time to send data to FIFO, if transfer size is not larger than
|
||||
* the FIFO size, send all data to FIFO, or send data to make the FIFO full.
|
||||
* Besides, The FIFO's entry width is 16 bits, need to translate it to bytes.
|
||||
*/
|
||||
bytestoTransfer = MIN(handle->txRemainingBytes, (FSL_FEATURE_SPI_FIFO_SIZEn(base) * 2));
|
||||
}
|
||||
#endif
|
||||
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytestoTransfer);
|
||||
|
||||
/* Update handle information */
|
||||
if (handle->txData)
|
||||
{
|
||||
handle->txData += bytestoTransfer;
|
||||
}
|
||||
handle->txRemainingBytes -= bytestoTransfer;
|
||||
}
|
||||
|
||||
static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint8_t bytes = MIN((handle->watermark * 2U), handle->txRemainingBytes);
|
||||
uint8_t bytes = handle->bytePerFrame;
|
||||
|
||||
/* Read S register and ensure SPTEF is 1, otherwise the write would be ignored. */
|
||||
if (handle->watermark == 1U)
|
||||
{
|
||||
if (bytes != 0U)
|
||||
{
|
||||
bytes = handle->bytePerFrame;
|
||||
}
|
||||
|
||||
/* Send data */
|
||||
if (base->C1 & SPI_C1_MSTR_MASK)
|
||||
{
|
||||
|
@ -235,7 +304,7 @@ static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
|||
else
|
||||
{
|
||||
/* As a slave, send data until SPTEF cleared */
|
||||
while ((base->S & SPI_S_SPTEF_MASK) && (handle->txRemainingBytes > 0))
|
||||
while ((base->S & SPI_S_SPTEF_MASK) && (handle->txRemainingBytes >= bytes))
|
||||
{
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytes);
|
||||
|
||||
|
@ -253,56 +322,96 @@ static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
|||
/* If use FIFO */
|
||||
else
|
||||
{
|
||||
if (base->S & SPI_S_TNEAREF_MASK)
|
||||
{
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytes);
|
||||
/* The FIFO's entry width is 16 bits, need to translate it to bytes. */
|
||||
uint8_t bytestoTransfer = handle->watermark * 2;
|
||||
|
||||
/* Update handle information */
|
||||
if (handle->txData)
|
||||
{
|
||||
handle->txData += bytes;
|
||||
}
|
||||
handle->txRemainingBytes -= bytes;
|
||||
if (handle->txRemainingBytes < 8U)
|
||||
{
|
||||
bytestoTransfer = handle->txRemainingBytes;
|
||||
}
|
||||
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytestoTransfer);
|
||||
|
||||
/* Update handle information */
|
||||
if (handle->txData)
|
||||
{
|
||||
handle->txData += bytestoTransfer;
|
||||
}
|
||||
handle->txRemainingBytes -= bytestoTransfer;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint8_t bytes = MIN((handle->watermark * 2U), handle->rxRemainingBytes);
|
||||
uint8_t val = 1U;
|
||||
uint8_t bytes = handle->bytePerFrame;
|
||||
|
||||
/* Read S register and ensure SPRF is 1, otherwise the write would be ignored. */
|
||||
if (handle->watermark == 1U)
|
||||
{
|
||||
val = base->S & SPI_S_SPRF_MASK;
|
||||
if (bytes != 0U)
|
||||
if (base->S & SPI_S_SPRF_MASK)
|
||||
{
|
||||
bytes = handle->bytePerFrame;
|
||||
SPI_ReadNonBlocking(base, handle->rxData, bytes);
|
||||
|
||||
/* Update information in handle */
|
||||
if (handle->rxData)
|
||||
{
|
||||
handle->rxData += bytes;
|
||||
}
|
||||
handle->rxRemainingBytes -= bytes;
|
||||
}
|
||||
}
|
||||
|
||||
if (val)
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
|
||||
/* If use FIFO */
|
||||
else
|
||||
{
|
||||
SPI_ReadNonBlocking(base, handle->rxData, bytes);
|
||||
|
||||
/* Update information in handle */
|
||||
if (handle->rxData)
|
||||
/* While rx fifo not empty and remaining data can also trigger the last interrupt */
|
||||
while ((base->S & SPI_S_RFIFOEF_MASK) == 0U)
|
||||
{
|
||||
handle->rxData += bytes;
|
||||
SPI_ReadNonBlocking(base, handle->rxData, bytes);
|
||||
|
||||
/* Update information in handle */
|
||||
if (handle->rxData)
|
||||
{
|
||||
handle->rxData += bytes;
|
||||
}
|
||||
handle->rxRemainingBytes -= bytes;
|
||||
|
||||
/* If the reamining data equals to watermark, leave to last interrupt */
|
||||
if (handle->rxRemainingBytes == (handle->watermark * 2U))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
handle->rxRemainingBytes -= bytes;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sets the SPI master configuration structure to default values.
|
||||
*
|
||||
* The purpose of this API is to get the configuration structure initialized for use in SPI_MasterInit().
|
||||
* User may use the initialized structure unchanged in SPI_MasterInit(), or modify
|
||||
* some fields of the structure before calling SPI_MasterInit(). After calling this API,
|
||||
* the master is ready to transfer.
|
||||
* Example:
|
||||
code
|
||||
spi_master_config_t config;
|
||||
SPI_MasterGetDefaultConfig(&config);
|
||||
endcode
|
||||
*
|
||||
* param config pointer to master config structure
|
||||
*/
|
||||
void SPI_MasterGetDefaultConfig(spi_master_config_t *config)
|
||||
{
|
||||
config->enableMaster = true;
|
||||
/* Initializes the configure structure to zero. */
|
||||
memset(config, 0, sizeof(*config));
|
||||
|
||||
config->enableMaster = true;
|
||||
config->enableStopInWaitMode = false;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
config->dataMode = kSPI_8BitMode;
|
||||
|
@ -313,17 +422,37 @@ void SPI_MasterGetDefaultConfig(spi_master_config_t *config)
|
|||
config->rxWatermark = kSPI_RxFifoOneHalfFull;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
config->pinMode = kSPI_PinModeNormal;
|
||||
config->outputMode = kSPI_SlaveSelectAutomaticOutput;
|
||||
config->pinMode = kSPI_PinModeNormal;
|
||||
config->outputMode = kSPI_SlaveSelectAutomaticOutput;
|
||||
config->baudRate_Bps = 500000U;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI with master configuration.
|
||||
*
|
||||
* The configuration structure can be filled by user from scratch, or be set with default
|
||||
* values by SPI_MasterGetDefaultConfig(). After calling this API, the slave is ready to transfer.
|
||||
* Example
|
||||
code
|
||||
spi_master_config_t config = {
|
||||
.baudRate_Bps = 400000,
|
||||
...
|
||||
};
|
||||
SPI_MasterInit(SPI0, &config);
|
||||
endcode
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param config pointer to master configuration structure
|
||||
* param srcClock_Hz Source clock frequency.
|
||||
*/
|
||||
void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t srcClock_Hz)
|
||||
{
|
||||
assert(config && srcClock_Hz);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Open clock gate for SPI and open interrupt */
|
||||
CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
/* Disable SPI before configuration */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
|
@ -354,6 +483,9 @@ void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t
|
|||
/* Set baud rate */
|
||||
SPI_MasterSetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
|
||||
|
||||
/* Set the dummy data, this data will usefull when tx buffer is NULL. */
|
||||
SPI_SetDummyData(base, SPI_DUMMYDATA);
|
||||
|
||||
/* Enable SPI */
|
||||
if (config->enableMaster)
|
||||
{
|
||||
|
@ -361,12 +493,28 @@ void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sets the SPI slave configuration structure to default values.
|
||||
*
|
||||
* The purpose of this API is to get the configuration structure initialized for use in SPI_SlaveInit().
|
||||
* Modify some fields of the structure before calling SPI_SlaveInit().
|
||||
* Example:
|
||||
code
|
||||
spi_slave_config_t config;
|
||||
SPI_SlaveGetDefaultConfig(&config);
|
||||
endcode
|
||||
*
|
||||
* param config pointer to slave configuration structure
|
||||
*/
|
||||
void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config)
|
||||
{
|
||||
config->enableSlave = true;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
/* Initializes the configure structure to zero. */
|
||||
memset(config, 0, sizeof(*config));
|
||||
|
||||
config->enableSlave = true;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
config->enableStopInWaitMode = false;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
|
@ -377,14 +525,37 @@ void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config)
|
|||
config->txWatermark = kSPI_TxFifoOneHalfEmpty;
|
||||
config->rxWatermark = kSPI_RxFifoOneHalfFull;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
config->pinMode = kSPI_PinModeNormal;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI with slave configuration.
|
||||
*
|
||||
* The configuration structure can be filled by user from scratch or be set with
|
||||
* default values by SPI_SlaveGetDefaultConfig().
|
||||
* After calling this API, the slave is ready to transfer.
|
||||
* Example
|
||||
code
|
||||
spi_slave_config_t config = {
|
||||
.polarity = kSPIClockPolarity_ActiveHigh;
|
||||
.phase = kSPIClockPhase_FirstEdge;
|
||||
.direction = kSPIMsbFirst;
|
||||
...
|
||||
};
|
||||
SPI_MasterInit(SPI0, &config);
|
||||
endcode
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param config pointer to master configuration structure
|
||||
*/
|
||||
void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Open clock gate for SPI and open interrupt */
|
||||
CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
/* Disable SPI before configuration */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
|
@ -395,9 +566,11 @@ void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
|||
|
||||
/* Configure data mode if needed */
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
base->C2 = SPI_C2_SPIMODE(config->dataMode) | SPI_C2_SPISWAI(config->enableStopInWaitMode);
|
||||
base->C2 = SPI_C2_SPIMODE(config->dataMode) | SPI_C2_SPISWAI(config->enableStopInWaitMode) |
|
||||
SPI_C2_BIDIROE(config->pinMode >> 1U) | SPI_C2_SPC0(config->pinMode & 1U);
|
||||
#else
|
||||
base->C2 = SPI_C2_SPISWAI(config->enableStopInWaitMode);
|
||||
base->C2 = SPI_C2_SPISWAI(config->enableStopInWaitMode) | SPI_C2_BIDIROE(config->pinMode >> 1U) |
|
||||
SPI_C2_SPC0(config->pinMode & 1U);
|
||||
#endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
|
||||
|
||||
/* Set watermark */
|
||||
|
@ -409,6 +582,9 @@ void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
|||
}
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
/* Set the dummy data, this data will usefull when tx buffer is NULL. */
|
||||
SPI_SetDummyData(base, SPI_DUMMYDATA);
|
||||
|
||||
/* Enable SPI */
|
||||
if (config->enableSlave)
|
||||
{
|
||||
|
@ -416,15 +592,31 @@ void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief De-initializes the SPI.
|
||||
*
|
||||
* Calling this API resets the SPI module, gates the SPI clock.
|
||||
* The SPI module can't work unless calling the SPI_MasterInit/SPI_SlaveInit to initialize module.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
*/
|
||||
void SPI_Deinit(SPI_Type *base)
|
||||
{
|
||||
/* Disable SPI module before shutting down */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Gate the clock */
|
||||
CLOCK_DisableClock(s_spiClock[SPI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Gets the status flag.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* return SPI Status, use status flag to AND #_spi_flags could get the related status.
|
||||
*/
|
||||
uint32_t SPI_GetStatusFlags(SPI_Type *base)
|
||||
{
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
|
@ -441,6 +633,17 @@ uint32_t SPI_GetStatusFlags(SPI_Type *base)
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Enables the interrupt for the SPI.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param mask SPI interrupt source. The parameter can be any combination of the following values:
|
||||
* arg kSPI_RxFullAndModfInterruptEnable
|
||||
* arg kSPI_TxEmptyInterruptEnable
|
||||
* arg kSPI_MatchInterruptEnable
|
||||
* arg kSPI_RxFifoNearFullInterruptEnable
|
||||
* arg kSPI_TxFifoNearEmptyInterruptEnable
|
||||
*/
|
||||
void SPI_EnableInterrupts(SPI_Type *base, uint32_t mask)
|
||||
{
|
||||
/* Rx full interrupt */
|
||||
|
@ -480,6 +683,17 @@ void SPI_EnableInterrupts(SPI_Type *base, uint32_t mask)
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Disables the interrupt for the SPI.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param mask SPI interrupt source. The parameter can be any combination of the following values:
|
||||
* arg kSPI_RxFullAndModfInterruptEnable
|
||||
* arg kSPI_TxEmptyInterruptEnable
|
||||
* arg kSPI_MatchInterruptEnable
|
||||
* arg kSPI_RxFifoNearFullInterruptEnable
|
||||
* arg kSPI_TxFifoNearEmptyInterruptEnable
|
||||
*/
|
||||
void SPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
|
||||
{
|
||||
/* Rx full interrupt */
|
||||
|
@ -518,6 +732,13 @@ void SPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sets the baud rate for SPI transfer. This is only used in master.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param baudRate_Bps baud rate needed in Hz.
|
||||
* param srcClock_Hz SPI source clock frequency in Hz.
|
||||
*/
|
||||
void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
|
||||
{
|
||||
uint32_t prescaler;
|
||||
|
@ -535,7 +756,7 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl
|
|||
|
||||
/* Set the maximum divisor bit settings for each of the following divisors */
|
||||
bestPrescaler = 7U;
|
||||
bestDivisor = 8U;
|
||||
bestDivisor = 8U;
|
||||
|
||||
/* In all for loops, if min_diff = 0, the exit for loop*/
|
||||
for (prescaler = 0; (prescaler <= 7) && min_diff; prescaler++)
|
||||
|
@ -556,9 +777,9 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl
|
|||
if (min_diff > diff)
|
||||
{
|
||||
/* A better match found */
|
||||
min_diff = diff;
|
||||
min_diff = diff;
|
||||
bestPrescaler = prescaler;
|
||||
bestDivisor = rateDivisor;
|
||||
bestDivisor = rateDivisor;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,9 +792,18 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl
|
|||
base->BR = SPI_BR_SPR(bestDivisor) | SPI_BR_SPPR(bestPrescaler);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sends a buffer of data bytes using a blocking method.
|
||||
*
|
||||
* note This function blocks via polling until all bytes have been sent.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param buffer The data bytes to send
|
||||
* param size The number of data bytes to send
|
||||
*/
|
||||
void SPI_WriteBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0;
|
||||
uint8_t bytesPerFrame = 1U;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
|
@ -596,6 +826,12 @@ void SPI_WriteBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
}
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
/*!
|
||||
* brief Enables or disables the FIFO if there is a FIFO.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param enable True means enable FIFO, false means disable FIFO.
|
||||
*/
|
||||
void SPI_EnableFIFO(SPI_Type *base, bool enable)
|
||||
{
|
||||
if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0U)
|
||||
|
@ -612,6 +848,12 @@ void SPI_EnableFIFO(SPI_Type *base, bool enable)
|
|||
}
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
/*!
|
||||
* brief Writes a data into the SPI data register.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param data needs to be write.
|
||||
*/
|
||||
void SPI_WriteData(SPI_Type *base, uint16_t data)
|
||||
{
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
|
||||
|
@ -622,6 +864,12 @@ void SPI_WriteData(SPI_Type *base, uint16_t data)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Gets a data from the SPI data register.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* return Data in the register.
|
||||
*/
|
||||
uint16_t SPI_ReadData(SPI_Type *base)
|
||||
{
|
||||
uint16_t val = 0;
|
||||
|
@ -634,6 +882,14 @@ uint16_t SPI_ReadData(SPI_Type *base)
|
|||
return val;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Transfers a block of data using a polling method.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param xfer pointer to spi_xfer_config_t structure
|
||||
* retval kStatus_Success Successfully start a transfer.
|
||||
* retval kStatus_InvalidArgument Input argument is invalid.
|
||||
*/
|
||||
status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
||||
{
|
||||
assert(xfer);
|
||||
|
@ -651,10 +907,6 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
|||
bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
|
||||
#endif
|
||||
|
||||
/* Disable SPI and then enable it, this is used to clear S register */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
base->C1 |= SPI_C1_SPE_MASK;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
|
||||
/* Disable FIFO, as the FIFO may cause data loss if the data size is not integer
|
||||
|
@ -696,6 +948,17 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
|||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI master handle.
|
||||
*
|
||||
* This function initializes the SPI master handle which can be used for other SPI master transactional APIs. Usually,
|
||||
* for a specified SPI instance, call this API once to get the initialized handle.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI handle pointer.
|
||||
* param callback Callback function.
|
||||
* param userData User data.
|
||||
*/
|
||||
void SPI_MasterTransferCreateHandle(SPI_Type *base,
|
||||
spi_master_handle_t *handle,
|
||||
spi_master_callback_t callback,
|
||||
|
@ -705,35 +968,15 @@ void SPI_MasterTransferCreateHandle(SPI_Type *base,
|
|||
|
||||
uint8_t instance = SPI_GetInstance(base);
|
||||
|
||||
/* Zero the handle */
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
|
||||
/* Initialize the handle */
|
||||
s_spiHandle[instance] = handle;
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
s_spiIsr = SPI_MasterTransferHandleIRQ;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
uint8_t txSize = 0U;
|
||||
/* Get the number to be sent if there is FIFO */
|
||||
if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
|
||||
{
|
||||
txSize = (base->C3 & SPI_C3_TNEAREF_MARK_MASK) >> SPI_C3_TNEAREF_MARK_SHIFT;
|
||||
if (txSize == 0U)
|
||||
{
|
||||
handle->watermark = FSL_FEATURE_SPI_FIFO_SIZEn(base) * 3U / 4U;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle->watermark = FSL_FEATURE_SPI_FIFO_SIZEn(base) / 2U;
|
||||
}
|
||||
}
|
||||
/* If no FIFO, just set the watermark to 1 */
|
||||
else
|
||||
{
|
||||
handle->watermark = 1U;
|
||||
}
|
||||
#else
|
||||
handle->watermark = 1U;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
s_spiMasterIsr = SPI_MasterTransferHandleIRQ;
|
||||
handle->watermark = SPI_GetWatermark(base);
|
||||
|
||||
/* Get the bytes per frame */
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
|
||||
|
@ -746,6 +989,20 @@ void SPI_MasterTransferCreateHandle(SPI_Type *base,
|
|||
EnableIRQ(s_spiIRQ[instance]);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Performs a non-blocking SPI interrupt transfer.
|
||||
*
|
||||
* note The API immediately returns after transfer initialization is finished.
|
||||
* Call SPI_GetStatusIRQ() to get the transfer status.
|
||||
* note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
* param xfer pointer to spi_xfer_config_t structure
|
||||
* retval kStatus_Success Successfully start a transfer.
|
||||
* retval kStatus_InvalidArgument Input argument is invalid.
|
||||
* retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
|
||||
*/
|
||||
status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *handle, spi_transfer_t *xfer)
|
||||
{
|
||||
assert(handle && xfer);
|
||||
|
@ -763,47 +1020,76 @@ status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *hand
|
|||
}
|
||||
|
||||
/* Set the handle information */
|
||||
handle->txData = xfer->txData;
|
||||
handle->rxData = xfer->rxData;
|
||||
handle->transferSize = xfer->dataSize;
|
||||
handle->txData = xfer->txData;
|
||||
handle->rxData = xfer->rxData;
|
||||
handle->transferSize = xfer->dataSize;
|
||||
handle->txRemainingBytes = xfer->dataSize;
|
||||
handle->rxRemainingBytes = xfer->dataSize;
|
||||
|
||||
/* Set the SPI state to busy */
|
||||
handle->state = kSPI_Busy;
|
||||
|
||||
/* Disable SPI and then enable it, this is used to clear S register*/
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
base->C1 |= SPI_C1_SPE_MASK;
|
||||
|
||||
/* Enable Interrupt, only enable Rx interrupt, use rx interrupt to driver SPI transfer */
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
|
||||
handle->watermark = SPI_GetWatermark(base);
|
||||
|
||||
/* If the size of the transfer size less than watermark, set watermark to 1 */
|
||||
if (xfer->dataSize < handle->watermark * 2U)
|
||||
{
|
||||
handle->watermark = 1U;
|
||||
}
|
||||
|
||||
/* According to watermark size, enable interrupts */
|
||||
if (handle->watermark > 1U)
|
||||
{
|
||||
SPI_EnableFIFO(base, true);
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
while ((base->S & SPI_S_TNEAREF_MASK) != SPI_S_TNEAREF_MASK)
|
||||
{
|
||||
}
|
||||
SPI_SendInitialTransfer(base, handle);
|
||||
/* Enable Rx near full interrupt */
|
||||
SPI_EnableInterrupts(base, kSPI_RxFifoNearFullInterruptEnable);
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_EnableFIFO(base, false);
|
||||
while ((base->S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK)
|
||||
{
|
||||
}
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
SPI_SendInitialTransfer(base, handle);
|
||||
SPI_EnableInterrupts(base, kSPI_RxFullAndModfInterruptEnable);
|
||||
}
|
||||
#else
|
||||
while ((base->S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK)
|
||||
{
|
||||
}
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
SPI_SendInitialTransfer(base, handle);
|
||||
SPI_EnableInterrupts(base, kSPI_RxFullAndModfInterruptEnable);
|
||||
#endif
|
||||
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
SPI_SendTransfer(base, handle);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Gets the bytes of the SPI interrupt transferred.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle Pointer to SPI transfer handle, this should be a static variable.
|
||||
* param count Transferred bytes of SPI master.
|
||||
* retval kStatus_SPI_Success Succeed get the transfer count.
|
||||
* retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
|
||||
*/
|
||||
status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle, size_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
status_t status = kStatus_Success;
|
||||
|
||||
if (handle->state != kStatus_SPI_Busy)
|
||||
if (handle->state != kSPI_Busy)
|
||||
{
|
||||
status = kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
@ -823,6 +1109,12 @@ status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle,
|
|||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Aborts an SPI transfer using interrupt.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle Pointer to SPI transfer handle, this should be a static variable.
|
||||
*/
|
||||
void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -849,6 +1141,12 @@ void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle)
|
|||
handle->txRemainingBytes = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Interrupts the handler for the SPI.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle pointer to spi_master_handle_t structure which stores the transfer state.
|
||||
*/
|
||||
void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -878,6 +1176,17 @@ void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI slave handle.
|
||||
*
|
||||
* This function initializes the SPI slave handle which can be used for other SPI slave transactional APIs. Usually,
|
||||
* for a specified SPI instance, call this API once to get the initialized handle.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI handle pointer.
|
||||
* param callback Callback function.
|
||||
* param userData User data.
|
||||
*/
|
||||
void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
|
@ -888,9 +1197,15 @@ void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
|||
/* Slave create handle share same logic with master create handle, the only difference
|
||||
is the Isr pointer. */
|
||||
SPI_MasterTransferCreateHandle(base, handle, callback, userData);
|
||||
s_spiIsr = SPI_SlaveTransferHandleIRQ;
|
||||
s_spiSlaveIsr = SPI_SlaveTransferHandleIRQ;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Interrupts a handler for the SPI slave.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle pointer to spi_slave_handle_t structure which stores the transfer state
|
||||
*/
|
||||
void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -920,11 +1235,28 @@ void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle)
|
|||
}
|
||||
}
|
||||
|
||||
static void SPI_CommonIRQHandler(SPI_Type *base, uint32_t instance)
|
||||
{
|
||||
if (base->C1 & SPI_C1_MSTR_MASK)
|
||||
{
|
||||
s_spiMasterIsr(base, s_spiHandle[instance]);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_spiSlaveIsr(base, s_spiHandle[instance]);
|
||||
}
|
||||
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
||||
exception return operation might vector to incorrect interrupt */
|
||||
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
||||
__DSB();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(SPI0)
|
||||
void SPI0_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_spiHandle[0]);
|
||||
s_spiIsr(SPI0, s_spiHandle[0]);
|
||||
SPI_CommonIRQHandler(SPI0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -932,7 +1264,7 @@ void SPI0_DriverIRQHandler(void)
|
|||
void SPI1_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_spiHandle[1]);
|
||||
s_spiIsr(SPI1, s_spiHandle[1]);
|
||||
SPI_CommonIRQHandler(SPI1, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -940,6 +1272,6 @@ void SPI1_DriverIRQHandler(void)
|
|||
void SPI2_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_spiHandle[2]);
|
||||
s_spiIsr(SPI0, s_spiHandle[2]);
|
||||
SPI_CommonIRQHandler(SPI2, 2);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used tom endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_SPI_H_
|
||||
#define _FSL_SPI_H_
|
||||
|
@ -37,15 +15,14 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SPI driver version 2.0.1. */
|
||||
#define FSL_SPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
|
||||
/*! @brief SPI driver version 2.0.4. */
|
||||
#define FSL_SPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 4))
|
||||
/*@}*/
|
||||
|
||||
#ifndef SPI_DUMMYDATA
|
||||
|
@ -53,12 +30,15 @@
|
|||
#define SPI_DUMMYDATA (0xFFU)
|
||||
#endif
|
||||
|
||||
/*! @brief Global variable for dummy data value setting. */
|
||||
extern volatile uint8_t g_spiDummyData[];
|
||||
|
||||
/*! @brief Return status for the SPI driver.*/
|
||||
enum _spi_status
|
||||
{
|
||||
kStatus_SPI_Busy = MAKE_STATUS(kStatusGroup_SPI, 0), /*!< SPI bus is busy */
|
||||
kStatus_SPI_Idle = MAKE_STATUS(kStatusGroup_SPI, 1), /*!< SPI is idle */
|
||||
kStatus_SPI_Error = MAKE_STATUS(kStatusGroup_SPI, 2) /*!< SPI error */
|
||||
kStatus_SPI_Busy = MAKE_STATUS(kStatusGroup_SPI, 0), /*!< SPI bus is busy */
|
||||
kStatus_SPI_Idle = MAKE_STATUS(kStatusGroup_SPI, 1), /*!< SPI is idle */
|
||||
kStatus_SPI_Error = MAKE_STATUS(kStatusGroup_SPI, 2) /*!< SPI error */
|
||||
};
|
||||
|
||||
/*! @brief SPI clock polarity configuration.*/
|
||||
|
@ -87,16 +67,16 @@ typedef enum _spi_shift_direction
|
|||
/*! @brief SPI slave select output mode options.*/
|
||||
typedef enum _spi_ss_output_mode
|
||||
{
|
||||
kSPI_SlaveSelectAsGpio = 0x0U, /*!< Slave select pin configured as GPIO. */
|
||||
kSPI_SlaveSelectFaultInput = 0x2U, /*!< Slave select pin configured for fault detection. */
|
||||
kSPI_SlaveSelectAutomaticOutput = 0x3U /*!< Slave select pin configured for automatic SPI output. */
|
||||
kSPI_SlaveSelectAsGpio = 0x0U, /*!< Slave select pin configured as GPIO. */
|
||||
kSPI_SlaveSelectFaultInput = 0x2U, /*!< Slave select pin configured for fault detection. */
|
||||
kSPI_SlaveSelectAutomaticOutput = 0x3U /*!< Slave select pin configured for automatic SPI output. */
|
||||
} spi_ss_output_mode_t;
|
||||
|
||||
/*! @brief SPI pin mode options.*/
|
||||
typedef enum _spi_pin_mode
|
||||
{
|
||||
kSPI_PinModeNormal = 0x0U, /*!< Pins operate in normal, single-direction mode.*/
|
||||
kSPI_PinModeInput = 0x1U, /*!< Bidirectional mode. Master: MOSI pin is input;
|
||||
kSPI_PinModeInput = 0x1U, /*!< Bidirectional mode. Master: MOSI pin is input;
|
||||
* Slave: MISO pin is input. */
|
||||
kSPI_PinModeOutput = 0x3U /*!< Bidirectional mode. Master: MOSI pin is output;
|
||||
* Slave: MISO pin is output. */
|
||||
|
@ -113,10 +93,10 @@ typedef enum _spi_data_bitcount_mode
|
|||
enum _spi_interrupt_enable
|
||||
{
|
||||
kSPI_RxFullAndModfInterruptEnable = 0x1U, /*!< Receive buffer full (SPRF) and mode fault (MODF) interrupt */
|
||||
kSPI_TxEmptyInterruptEnable = 0x2U, /*!< Transmit buffer empty interrupt */
|
||||
kSPI_MatchInterruptEnable = 0x4U, /*!< Match interrupt */
|
||||
kSPI_TxEmptyInterruptEnable = 0x2U, /*!< Transmit buffer empty interrupt */
|
||||
kSPI_MatchInterruptEnable = 0x4U, /*!< Match interrupt */
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
kSPI_RxFifoNearFullInterruptEnable = 0x8U, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_RxFifoNearFullInterruptEnable = 0x8U, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_TxFifoNearEmptyInterruptEnable = 0x10U, /*!< Transmit FIFO nearly empty interrupt */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
};
|
||||
|
@ -124,44 +104,44 @@ enum _spi_interrupt_enable
|
|||
/*! @brief SPI status flags.*/
|
||||
enum _spi_flags
|
||||
{
|
||||
kSPI_RxBufferFullFlag = SPI_S_SPRF_MASK, /*!< Read buffer full flag */
|
||||
kSPI_MatchFlag = SPI_S_SPMF_MASK, /*!< Match flag */
|
||||
kSPI_RxBufferFullFlag = SPI_S_SPRF_MASK, /*!< Read buffer full flag */
|
||||
kSPI_MatchFlag = SPI_S_SPMF_MASK, /*!< Match flag */
|
||||
kSPI_TxBufferEmptyFlag = SPI_S_SPTEF_MASK, /*!< Transmit buffer empty flag */
|
||||
kSPI_ModeFaultFlag = SPI_S_MODF_MASK, /*!< Mode fault flag */
|
||||
kSPI_ModeFaultFlag = SPI_S_MODF_MASK, /*!< Mode fault flag */
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
kSPI_RxFifoNearFullFlag = SPI_S_RNFULLF_MASK, /*!< Rx FIFO near full */
|
||||
kSPI_TxFifoNearEmptyFlag = SPI_S_TNEAREF_MASK, /*!< Tx FIFO near empty */
|
||||
kSPI_TxFifoFullFlag = SPI_S_TXFULLF_MASK, /*!< Tx FIFO full */
|
||||
kSPI_RxFifoEmptyFlag = SPI_S_RFIFOEF_MASK, /*!< Rx FIFO empty */
|
||||
kSPI_TxFifoError = SPI_CI_TXFERR_MASK << 8U, /*!< Tx FIFO error */
|
||||
kSPI_RxFifoError = SPI_CI_RXFERR_MASK << 8U, /*!< Rx FIFO error */
|
||||
kSPI_TxOverflow = SPI_CI_TXFOF_MASK << 8U, /*!< Tx FIFO Overflow */
|
||||
kSPI_RxOverflow = SPI_CI_RXFOF_MASK << 8U /*!< Rx FIFO Overflow */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
kSPI_RxFifoNearFullFlag = SPI_S_RNFULLF_MASK, /*!< Rx FIFO near full */
|
||||
kSPI_TxFifoNearEmptyFlag = SPI_S_TNEAREF_MASK, /*!< Tx FIFO near empty */
|
||||
kSPI_TxFifoFullFlag = SPI_S_TXFULLF_MASK, /*!< Tx FIFO full */
|
||||
kSPI_RxFifoEmptyFlag = SPI_S_RFIFOEF_MASK, /*!< Rx FIFO empty */
|
||||
kSPI_TxFifoError = SPI_CI_TXFERR_MASK << 8U, /*!< Tx FIFO error */
|
||||
kSPI_RxFifoError = SPI_CI_RXFERR_MASK << 8U, /*!< Rx FIFO error */
|
||||
kSPI_TxOverflow = SPI_CI_TXFOF_MASK << 8U, /*!< Tx FIFO Overflow */
|
||||
kSPI_RxOverflow = SPI_CI_RXFOF_MASK << 8U /*!< Rx FIFO Overflow */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
};
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
/*! @brief SPI FIFO write-1-to-clear interrupt flags.*/
|
||||
typedef enum _spi_w1c_interrupt
|
||||
{
|
||||
kSPI_RxFifoFullClearInterrupt = SPI_CI_SPRFCI_MASK, /*!< Receive FIFO full interrupt */
|
||||
kSPI_TxFifoEmptyClearInterrupt = SPI_CI_SPTEFCI_MASK, /*!< Transmit FIFO empty interrupt */
|
||||
kSPI_RxNearFullClearInterrupt = SPI_CI_RNFULLFCI_MASK, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_TxNearEmptyClearInterrupt = SPI_CI_TNEAREFCI_MASK /*!< Transmit FIFO nearly empty interrupt */
|
||||
kSPI_RxFifoFullClearInterrupt = SPI_CI_SPRFCI_MASK, /*!< Receive FIFO full interrupt */
|
||||
kSPI_TxFifoEmptyClearInterrupt = SPI_CI_SPTEFCI_MASK, /*!< Transmit FIFO empty interrupt */
|
||||
kSPI_RxNearFullClearInterrupt = SPI_CI_RNFULLFCI_MASK, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_TxNearEmptyClearInterrupt = SPI_CI_TNEAREFCI_MASK /*!< Transmit FIFO nearly empty interrupt */
|
||||
} spi_w1c_interrupt_t;
|
||||
|
||||
/*! @brief SPI TX FIFO watermark settings.*/
|
||||
typedef enum _spi_txfifo_watermark
|
||||
{
|
||||
kSPI_TxFifoOneFourthEmpty = 0, /*!< SPI tx watermark at 1/4 FIFO size */
|
||||
kSPI_TxFifoOneHalfEmpty = 1 /*!< SPI tx watermark at 1/2 FIFO size */
|
||||
kSPI_TxFifoOneHalfEmpty = 1 /*!< SPI tx watermark at 1/2 FIFO size */
|
||||
} spi_txfifo_watermark_t;
|
||||
|
||||
/*! @brief SPI RX FIFO watermark settings.*/
|
||||
typedef enum _spi_rxfifo_watermark
|
||||
{
|
||||
kSPI_RxFifoThreeFourthsFull = 0, /*!< SPI rx watermark at 3/4 FIFO size */
|
||||
kSPI_RxFifoOneHalfFull = 1 /*!< SPI rx watermark at 1/2 FIFO size */
|
||||
kSPI_RxFifoOneHalfFull = 1 /*!< SPI rx watermark at 1/2 FIFO size */
|
||||
} spi_rxfifo_watermark_t;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
|
@ -169,8 +149,8 @@ typedef enum _spi_rxfifo_watermark
|
|||
/*! @brief SPI DMA source*/
|
||||
enum _spi_dma_enable_t
|
||||
{
|
||||
kSPI_TxDmaEnable = SPI_C2_TXDMAE_MASK, /*!< Tx DMA request source */
|
||||
kSPI_RxDmaEnable = SPI_C2_RXDMAE_MASK, /*!< Rx DMA request source */
|
||||
kSPI_TxDmaEnable = SPI_C2_TXDMAE_MASK, /*!< Tx DMA request source */
|
||||
kSPI_RxDmaEnable = SPI_C2_RXDMAE_MASK, /*!< Rx DMA request source */
|
||||
kSPI_DmaAllEnable = (SPI_C2_TXDMAE_MASK | SPI_C2_RXDMAE_MASK) /*!< All DMA request source*/
|
||||
};
|
||||
#endif /* FSL_FEATURE_SPI_HAS_DMA_SUPPORT */
|
||||
|
@ -210,6 +190,7 @@ typedef struct _spi_slave_config
|
|||
spi_txfifo_watermark_t txWatermark; /*!< Tx watermark settings */
|
||||
spi_rxfifo_watermark_t rxWatermark; /*!< Rx watermark settings */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
spi_pin_mode_t pinMode; /*!< SPI pin mode select */
|
||||
} spi_slave_config_t;
|
||||
|
||||
/*! @brief SPI transfer structure */
|
||||
|
@ -478,6 +459,27 @@ static inline uint32_t SPI_GetDataRegisterAddress(SPI_Type *base)
|
|||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Get the instance for SPI module.
|
||||
*
|
||||
* @param base SPI base address
|
||||
*/
|
||||
uint32_t SPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Sets the pin mode for transfer.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param pinMode pin mode for transfer AND #_spi_pin_mode could get the related configuration.
|
||||
*/
|
||||
static inline void SPI_SetPinMode(SPI_Type *base, spi_pin_mode_t pinMode)
|
||||
{
|
||||
/* Clear SPC0 and BIDIROE bit. */
|
||||
base->C2 &= ~(SPI_C2_BIDIROE_MASK | SPI_C2_SPC0_MASK);
|
||||
/* Set pin mode for transfer. */
|
||||
base->C2 |= SPI_C2_BIDIROE(pinMode >> 1U) | SPI_C2_SPC0(pinMode & 1U);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets the baud rate for SPI transfer. This is only used in master.
|
||||
*
|
||||
|
@ -544,6 +546,13 @@ void SPI_WriteData(SPI_Type *base, uint16_t data);
|
|||
*/
|
||||
uint16_t SPI_ReadData(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Set up the dummy data.
|
||||
*
|
||||
* @param base SPI peripheral address.
|
||||
* @param dummyData Data to be transferred when tx buffer is NULL.
|
||||
*/
|
||||
void SPI_SetDummyData(SPI_Type *base, uint8_t dummyData);
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
|
@ -582,11 +591,7 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer);
|
|||
*
|
||||
* @note The API immediately returns after transfer initialization is finished.
|
||||
* Call SPI_GetStatusIRQ() to get the transfer status.
|
||||
* @note If using the SPI with FIFO for the interrupt transfer, the transfer size is the integer times of the watermark.
|
||||
* Otherwise,
|
||||
* the last data may be lost because it cannot generate an interrupt request. Users can also call the functional API to
|
||||
* get the last
|
||||
* received data.
|
||||
* @note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
|
@ -636,8 +641,8 @@ void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle);
|
|||
* @param userData User data.
|
||||
*/
|
||||
void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
void *userData);
|
||||
|
||||
/*!
|
||||
|
@ -645,11 +650,7 @@ void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
|||
*
|
||||
* @note The API returns immediately after the transfer initialization is finished.
|
||||
* Call SPI_GetStatusIRQ() to get the transfer status.
|
||||
* @note If using the SPI with FIFO for the interrupt transfer, the transfer size is the integer times the watermark.
|
||||
* Otherwise,
|
||||
* the last data may be lost because it cannot generate an interrupt request. Call the functional API to get the last
|
||||
* several
|
||||
* receive data.
|
||||
* @note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
|
|
|
@ -1,38 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_spi_dma.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitons
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.spi_dma"
|
||||
#endif
|
||||
|
||||
/*<! Structure definition for spi_dma_private_handle_t. The structure is private. */
|
||||
typedef struct _spi_dma_private_handle
|
||||
{
|
||||
|
@ -52,13 +36,6 @@ static spi_dma_private_handle_t s_dmaPrivateHandle[FSL_FEATURE_SOC_SPI_COUNT];
|
|||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Get the instance for SPI module.
|
||||
*
|
||||
* @param base SPI base address
|
||||
*/
|
||||
extern uint32_t SPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief DMA callback function for SPI send transfer.
|
||||
*
|
||||
|
@ -76,25 +53,18 @@ static void SPI_TxDMACallback(dma_handle_t *handle, void *userData);
|
|||
static void SPI_RxDMACallback(dma_handle_t *handle, void *userData);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
/* Dummy data used to send */
|
||||
static const uint8_t s_dummyData = SPI_DUMMYDATA;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static void SPI_TxDMACallback(dma_handle_t *handle, void *userData)
|
||||
{
|
||||
spi_dma_private_handle_t *privHandle = (spi_dma_private_handle_t *)userData;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
|
||||
/* Disable Tx dma */
|
||||
SPI_EnableDMA(base, kSPI_TxDmaEnable, false);
|
||||
|
||||
/* Stop DMA tranfer */
|
||||
/* Stop DMA transfer */
|
||||
DMA_StopTransfer(spiHandle->txHandle);
|
||||
|
||||
/* change the state */
|
||||
|
@ -114,13 +84,13 @@ static void SPI_TxDMACallback(dma_handle_t *handle, void *userData)
|
|||
static void SPI_RxDMACallback(dma_handle_t *handle, void *userData)
|
||||
{
|
||||
spi_dma_private_handle_t *privHandle = (spi_dma_private_handle_t *)userData;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
|
||||
/* Disable Tx dma */
|
||||
SPI_EnableDMA(base, kSPI_RxDmaEnable, false);
|
||||
|
||||
/* Stop DMA tranfer */
|
||||
/* Stop DMA transfer */
|
||||
DMA_StopTransfer(spiHandle->rxHandle);
|
||||
|
||||
/* change the state */
|
||||
|
@ -137,6 +107,19 @@ static void SPI_RxDMACallback(dma_handle_t *handle, void *userData)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initialize the SPI master DMA handle.
|
||||
*
|
||||
* This function initializes the SPI master DMA handle which can be used for other SPI master transactional APIs.
|
||||
* Usually, for a specified SPI instance, user need only call this API once to get the initialized handle.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI handle pointer.
|
||||
* param callback User callback function called at the end of a transfer.
|
||||
* param userData User data for callback.
|
||||
* param txHandle DMA handle pointer for SPI Tx, the handle shall be static allocated by users.
|
||||
* param rxHandle DMA handle pointer for SPI Rx, the handle shall be static allocated by users.
|
||||
*/
|
||||
void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
||||
spi_dma_handle_t *handle,
|
||||
spi_dma_callback_t callback,
|
||||
|
@ -146,7 +129,10 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
{
|
||||
assert(handle);
|
||||
dma_transfer_config_t config = {0};
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
|
||||
/* Zero the handle */
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
|
||||
/* Set spi base to handle */
|
||||
handle->txHandle = txHandle;
|
||||
|
@ -158,7 +144,7 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
handle->state = kSPI_Idle;
|
||||
|
||||
/* Set handle to global state */
|
||||
s_dmaPrivateHandle[instance].base = base;
|
||||
s_dmaPrivateHandle[instance].base = base;
|
||||
s_dmaPrivateHandle[instance].handle = handle;
|
||||
|
||||
/* Compute internal state */
|
||||
|
@ -180,27 +166,27 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
/* Set the non-change attribute for Tx DMA transfer, to improve efficiency */
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.enableDestIncrement = false;
|
||||
config.enableSrcIncrement = true;
|
||||
config.enableSrcIncrement = true;
|
||||
if (handle->bytesPerFrame == 1U)
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.destSize = kDMA_Transfersize8bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.destSize = kDMA_Transfersize16bits;
|
||||
}
|
||||
|
||||
DMA_SubmitTransfer(handle->txHandle, &config, true);
|
||||
|
||||
/* Set non-change attribute for Rx DMA */
|
||||
config.srcAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = 0U;
|
||||
config.srcAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = 0U;
|
||||
config.enableDestIncrement = true;
|
||||
config.enableSrcIncrement = false;
|
||||
config.enableSrcIncrement = false;
|
||||
DMA_SubmitTransfer(handle->rxHandle, &config, true);
|
||||
|
||||
/* Install callback for Tx dma channel */
|
||||
|
@ -208,6 +194,19 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
DMA_SetCallback(handle->rxHandle, SPI_RxDMACallback, &s_dmaPrivateHandle[instance]);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Perform a non-blocking SPI transfer using DMA.
|
||||
*
|
||||
* note This interface returned immediately after transfer initiates, users should call
|
||||
* SPI_GetTransferStatus to poll the transfer status to check whether SPI transfer finished.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI DMA handle pointer.
|
||||
* param xfer Pointer to dma transfer structure.
|
||||
* retval kStatus_Success Successfully start a transfer.
|
||||
* retval kStatus_InvalidArgument Input argument is invalid.
|
||||
* retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
|
||||
*/
|
||||
status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_transfer_t *xfer)
|
||||
{
|
||||
assert(handle && xfer);
|
||||
|
@ -231,16 +230,16 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
SPI_Enable(base, true);
|
||||
|
||||
/* Configure tx transfer DMA */
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.enableDestIncrement = false;
|
||||
if (handle->bytesPerFrame == 1U)
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.destSize = kDMA_Transfersize8bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.destSize = kDMA_Transfersize16bits;
|
||||
}
|
||||
config.transferSize = xfer->dataSize;
|
||||
|
@ -248,13 +247,13 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
if (xfer->txData)
|
||||
{
|
||||
config.enableSrcIncrement = true;
|
||||
config.srcAddr = (uint32_t)(xfer->txData);
|
||||
config.srcAddr = (uint32_t)(xfer->txData);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the source increasement and source set to dummyData */
|
||||
config.enableSrcIncrement = false;
|
||||
config.srcAddr = (uint32_t)(&s_dummyData);
|
||||
config.srcAddr = (uint32_t)(&g_spiDummyData[SPI_GetInstance(base)]);
|
||||
}
|
||||
DMA_SubmitTransfer(handle->txHandle, &config, true);
|
||||
|
||||
|
@ -270,7 +269,7 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
|
||||
/* Change the state of handle */
|
||||
handle->transferSize = xfer->dataSize;
|
||||
handle->state = kSPI_Busy;
|
||||
handle->state = kSPI_Busy;
|
||||
|
||||
/* Start Rx transfer if needed */
|
||||
if (xfer->rxData)
|
||||
|
@ -288,6 +287,15 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Get the transferred bytes for SPI slave DMA.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI DMA handle pointer.
|
||||
* param count Transferred bytes.
|
||||
* retval kStatus_SPI_Success Succeed get the transfer count.
|
||||
* retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
|
||||
*/
|
||||
status_t SPI_MasterTransferGetCountDMA(SPI_Type *base, spi_dma_handle_t *handle, size_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -313,6 +321,12 @@ status_t SPI_MasterTransferGetCountDMA(SPI_Type *base, spi_dma_handle_t *handle,
|
|||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Abort a SPI transfer using DMA.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI DMA handle pointer.
|
||||
*/
|
||||
void SPI_MasterTransferAbortDMA(SPI_Type *base, spi_dma_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -327,5 +341,5 @@ void SPI_MasterTransferAbortDMA(SPI_Type *base, spi_dma_handle_t *handle)
|
|||
/* Set the handle state */
|
||||
handle->txInProgress = false;
|
||||
handle->rxInProgress = false;
|
||||
handle->state = kSPI_Idle;
|
||||
handle->state = kSPI_Idle;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_SPI_DMA_H_
|
||||
#define _FSL_SPI_DMA_H_
|
||||
|
@ -38,11 +16,16 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SPI DMA driver version 2.0.4. */
|
||||
#define FSL_SPI_DMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 4))
|
||||
/*@}*/
|
||||
|
||||
typedef struct _spi_dma_handle spi_dma_handle_t;
|
||||
|
||||
/*! @brief SPI DMA callback called at the end of transfer. */
|
||||
|
@ -55,7 +38,7 @@ struct _spi_dma_handle
|
|||
bool rxInProgress; /*!< Receive transfer finished */
|
||||
dma_handle_t *txHandle; /*!< DMA handler for SPI send */
|
||||
dma_handle_t *rxHandle; /*!< DMA handler for SPI receive */
|
||||
uint8_t bytesPerFrame; /*!< Bytes in a frame for SPI tranfer */
|
||||
uint8_t bytesPerFrame; /*!< Bytes in a frame for SPI transfer */
|
||||
spi_dma_callback_t callback; /*!< Callback for SPI DMA transfer */
|
||||
void *userData; /*!< User Data for SPI DMA callback */
|
||||
uint32_t state; /*!< Internal state of SPI DMA transfer */
|
||||
|
|
|
@ -300,4 +300,14 @@ const PinMap *serial_rts_pinmap()
|
|||
return PinMap_UART_RTS;
|
||||
}
|
||||
|
||||
void serial_wait_tx_complete(uint32_t uart_index)
|
||||
{
|
||||
LPUART_Type *base = uart_addrs[uart_index];
|
||||
|
||||
/* Wait till data is flushed out of transmit buffer */
|
||||
while (!(kLPUART_TransmissionCompleteFlag & LPUART_GetStatusFlags((LPUART_Type *)base)))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -116,16 +116,18 @@ int spi_master_write(spi_t *obj, int value)
|
|||
}
|
||||
|
||||
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
|
||||
char *rx_buffer, int rx_length, char write_fill) {
|
||||
char *rx_buffer, int rx_length, char write_fill)
|
||||
{
|
||||
int total = (tx_length > rx_length) ? tx_length : rx_length;
|
||||
|
||||
for (int i = 0; i < total; i++) {
|
||||
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
|
||||
char in = spi_master_write(obj, out);
|
||||
if (i < rx_length) {
|
||||
rx_buffer[i] = in;
|
||||
}
|
||||
}
|
||||
// Default write is done in each and every call, in future can create HAL API instead
|
||||
SPI_SetDummyData(spi_address[obj->instance], write_fill);
|
||||
|
||||
SPI_MasterTransferBlocking(spi_address[obj->instance], &(spi_transfer_t) {
|
||||
.txData = (uint8_t *)tx_buffer,
|
||||
.rxData = (uint8_t *)rx_buffer,
|
||||
.dataSize = total
|
||||
});
|
||||
|
||||
return total;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2018 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_DSPI_EDMA_H_
|
||||
#define _FSL_DSPI_EDMA_H_
|
||||
|
@ -37,28 +15,33 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/***********************************************************************************************************************
|
||||
* Definitions
|
||||
**********************************************************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief DSPI EDMA driver version 2.2.2. */
|
||||
#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 2))
|
||||
/*@}*/
|
||||
|
||||
/*!
|
||||
* @brief Forward declaration of the DSPI eDMA master handle typedefs.
|
||||
*/
|
||||
* @brief Forward declaration of the DSPI eDMA master handle typedefs.
|
||||
*/
|
||||
typedef struct _dspi_master_edma_handle dspi_master_edma_handle_t;
|
||||
|
||||
/*!
|
||||
* @brief Forward declaration of the DSPI eDMA slave handle typedefs.
|
||||
*/
|
||||
* @brief Forward declaration of the DSPI eDMA slave handle typedefs.
|
||||
*/
|
||||
typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t;
|
||||
|
||||
/*!
|
||||
* @brief Completion callback function pointer type.
|
||||
*
|
||||
* @param base DSPI peripheral base address.
|
||||
* @param handle Pointer to the handle for the DSPI master.
|
||||
* @param handle A pointer to the handle for the DSPI master.
|
||||
* @param status Success or error code describing whether the transfer completed.
|
||||
* @param userData Arbitrary pointer-dataSized value passed from the application.
|
||||
* @param userData An arbitrary pointer-dataSized value passed from the application.
|
||||
*/
|
||||
typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base,
|
||||
dspi_master_edma_handle_t *handle,
|
||||
|
@ -68,38 +51,39 @@ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base,
|
|||
* @brief Completion callback function pointer type.
|
||||
*
|
||||
* @param base DSPI peripheral base address.
|
||||
* @param handle Pointer to the handle for the DSPI slave.
|
||||
* @param handle A pointer to the handle for the DSPI slave.
|
||||
* @param status Success or error code describing whether the transfer completed.
|
||||
* @param userData Arbitrary pointer-dataSized value passed from the application.
|
||||
* @param userData An arbitrary pointer-dataSized value passed from the application.
|
||||
*/
|
||||
typedef void (*dspi_slave_edma_transfer_callback_t)(SPI_Type *base,
|
||||
dspi_slave_edma_handle_t *handle,
|
||||
status_t status,
|
||||
void *userData);
|
||||
|
||||
/*! @brief DSPI master eDMA transfer handle structure used for transactional API. */
|
||||
/*! @brief DSPI master eDMA transfer handle structure used for the transactional API. */
|
||||
struct _dspi_master_edma_handle
|
||||
{
|
||||
uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */
|
||||
volatile uint32_t command; /*!< Desired data command. */
|
||||
volatile uint32_t lastCommand; /*!< Desired last data command. */
|
||||
uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */
|
||||
volatile uint32_t command; /*!< The desired data command. */
|
||||
volatile uint32_t lastCommand; /*!< The desired last data command. */
|
||||
|
||||
uint8_t fifoSize; /*!< FIFO dataSize. */
|
||||
|
||||
volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/
|
||||
volatile bool isThereExtraByte; /*!< Is there extra byte.*/
|
||||
volatile bool
|
||||
isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal keeps active after the last frame transfer.*/
|
||||
|
||||
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
|
||||
volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/
|
||||
|
||||
uint8_t *volatile txData; /*!< Send buffer. */
|
||||
uint8_t *volatile rxData; /*!< Receive buffer. */
|
||||
volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/
|
||||
volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/
|
||||
size_t totalByteCount; /*!< Number of transfer bytes*/
|
||||
volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/
|
||||
volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/
|
||||
size_t totalByteCount; /*!< A number of transfer bytes*/
|
||||
|
||||
uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/
|
||||
uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/
|
||||
|
||||
volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/
|
||||
|
||||
dspi_master_edma_transfer_callback_t callback; /*!< Completion callback. */
|
||||
void *userData; /*!< Callback user data. */
|
||||
|
||||
|
@ -110,33 +94,30 @@ struct _dspi_master_edma_handle
|
|||
edma_tcd_t dspiSoftwareTCD[2]; /*!<SoftwareTCD , internal used*/
|
||||
};
|
||||
|
||||
/*! @brief DSPI slave eDMA transfer handle structure used for transactional API.*/
|
||||
/*! @brief DSPI slave eDMA transfer handle structure used for the transactional API.*/
|
||||
struct _dspi_slave_edma_handle
|
||||
{
|
||||
uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */
|
||||
volatile bool isThereExtraByte; /*!< Is there extra byte.*/
|
||||
uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */
|
||||
|
||||
uint8_t *volatile txData; /*!< Send buffer. */
|
||||
uint8_t *volatile rxData; /*!< Receive buffer. */
|
||||
volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/
|
||||
volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/
|
||||
size_t totalByteCount; /*!< Number of transfer bytes*/
|
||||
volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/
|
||||
volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/
|
||||
size_t totalByteCount; /*!< A number of transfer bytes*/
|
||||
|
||||
uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/
|
||||
uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/
|
||||
uint32_t txLastData; /*!< Used if there is an extra byte when 16bits per frame for DMA purpose.*/
|
||||
|
||||
volatile uint8_t state; /*!< DSPI transfer state.*/
|
||||
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
|
||||
|
||||
uint32_t errorCount; /*!< Error count for slave transfer.*/
|
||||
volatile uint8_t state; /*!< DSPI transfer state.*/
|
||||
|
||||
dspi_slave_edma_transfer_callback_t callback; /*!< Completion callback. */
|
||||
void *userData; /*!< Callback user data. */
|
||||
|
||||
edma_handle_t *edmaRxRegToRxDataHandle; /*!<edma_handle_t handle point used for RxReg to RxData buff*/
|
||||
edma_handle_t *edmaTxDataToTxRegHandle; /*!<edma_handle_t handle point used for TxData to TxReg*/
|
||||
|
||||
edma_tcd_t dspiSoftwareTCD[2]; /*!<SoftwareTCD , internal used*/
|
||||
};
|
||||
|
||||
/***********************************************************************************************************************
|
||||
|
@ -152,17 +133,18 @@ extern "C" {
|
|||
* @brief Initializes the DSPI master eDMA handle.
|
||||
*
|
||||
* This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a
|
||||
* specified DSPI instance, user need only call this API once to get the initialized handle.
|
||||
* specified DSPI instance, call this API once to get the initialized handle.
|
||||
*
|
||||
* Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request source.
|
||||
* (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and
|
||||
* Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request
|
||||
* source.
|
||||
* (1) For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and
|
||||
* TX DMAMUX source for edmaIntermediaryToTxRegHandle.
|
||||
* (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle.
|
||||
* (2) For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle.
|
||||
*
|
||||
* @param base DSPI peripheral base address.
|
||||
* @param handle DSPI handle pointer to dspi_master_edma_handle_t.
|
||||
* @param callback DSPI callback.
|
||||
* @param userData callback function parameter.
|
||||
* @param userData A callback function parameter.
|
||||
* @param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
|
||||
* @param edmaTxDataToIntermediaryHandle edmaTxDataToIntermediaryHandle pointer to edma_handle_t.
|
||||
* @param edmaIntermediaryToTxRegHandle edmaIntermediaryToTxRegHandle pointer to edma_handle_t.
|
||||
|
@ -178,34 +160,49 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base,
|
|||
/*!
|
||||
* @brief DSPI master transfer data using eDMA.
|
||||
*
|
||||
* This function transfer data using eDMA. This is non-blocking function, which returns right away. When all data
|
||||
* have been transfer, the callback function is called.
|
||||
* This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
|
||||
* is transferred, the callback function is called.
|
||||
*
|
||||
* @param base DSPI peripheral base address.
|
||||
* @param handle pointer to dspi_master_edma_handle_t structure which stores the transfer state.
|
||||
* @param transfer pointer to dspi_transfer_t structure.
|
||||
* @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
|
||||
* @param transfer A pointer to the dspi_transfer_t structure.
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer);
|
||||
|
||||
/*!
|
||||
* @brief DSPI master aborts a transfer which using eDMA.
|
||||
* @brief Transfers a block of data using a eDMA method.
|
||||
*
|
||||
* This function aborts a transfer which using eDMA.
|
||||
* This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function,
|
||||
* which returns right away. When all data is transferred, the callback function is called.
|
||||
*
|
||||
* @param base DSPI base pointer
|
||||
* @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
|
||||
* @param transfer A pointer to the dspi_half_duplex_transfer_t structure.
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base,
|
||||
dspi_master_edma_handle_t *handle,
|
||||
dspi_half_duplex_transfer_t *xfer);
|
||||
|
||||
/*!
|
||||
* @brief DSPI master aborts a transfer which is using eDMA.
|
||||
*
|
||||
* This function aborts a transfer which is using eDMA.
|
||||
*
|
||||
* @param base DSPI peripheral base address.
|
||||
* @param handle pointer to dspi_master_edma_handle_t structure which stores the transfer state.
|
||||
* @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
|
||||
*/
|
||||
void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Gets the master eDMA transfer count.
|
||||
*
|
||||
* This function get the master eDMA transfer count.
|
||||
* This function gets the master eDMA transfer count.
|
||||
*
|
||||
* @param base DSPI peripheral base address.
|
||||
* @param handle pointer to dspi_master_edma_handle_t structure which stores the transfer state.
|
||||
* @param count Number of bytes transferred so far by the non-blocking transaction.
|
||||
* @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
|
||||
* @param count A number of bytes transferred by the non-blocking transaction.
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count);
|
||||
|
@ -216,7 +213,8 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle
|
|||
* This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a
|
||||
* specified DSPI instance, call this API once to get the initialized handle.
|
||||
*
|
||||
* Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request source.
|
||||
* Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request
|
||||
* source.
|
||||
* (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and
|
||||
* TX DMAMUX source for edmaTxDataToTxRegHandle.
|
||||
* (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle.
|
||||
|
@ -224,7 +222,7 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle
|
|||
* @param base DSPI peripheral base address.
|
||||
* @param handle DSPI handle pointer to dspi_slave_edma_handle_t.
|
||||
* @param callback DSPI callback.
|
||||
* @param userData callback function parameter.
|
||||
* @param userData A callback function parameter.
|
||||
* @param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
|
||||
* @param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t.
|
||||
*/
|
||||
|
@ -238,25 +236,25 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base,
|
|||
/*!
|
||||
* @brief DSPI slave transfer data using eDMA.
|
||||
*
|
||||
* This function transfer data using eDMA. This is non-blocking function, which returns right away. When all data
|
||||
* have been transfer, the callback function is called.
|
||||
* Note that slave EDMA transfer cannot support the situation that transfer_size is 1 when the bitsPerFrame is greater
|
||||
* than 8 .
|
||||
* This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
|
||||
* is transferred, the callback function is called.
|
||||
* Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater
|
||||
* than eight.
|
||||
|
||||
* @param base DSPI peripheral base address.
|
||||
* @param handle pointer to dspi_slave_edma_handle_t structure which stores the transfer state.
|
||||
* @param transfer pointer to dspi_transfer_t structure.
|
||||
* @param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state.
|
||||
* @param transfer A pointer to the dspi_transfer_t structure.
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer);
|
||||
|
||||
/*!
|
||||
* @brief DSPI slave aborts a transfer which using eDMA.
|
||||
* @brief DSPI slave aborts a transfer which is using eDMA.
|
||||
*
|
||||
* This function aborts a transfer which using eDMA.
|
||||
* This function aborts a transfer which is using eDMA.
|
||||
*
|
||||
* @param base DSPI peripheral base address.
|
||||
* @param handle pointer to dspi_slave_edma_handle_t structure which stores the transfer state.
|
||||
* @param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state.
|
||||
*/
|
||||
void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle);
|
||||
|
||||
|
@ -266,8 +264,8 @@ void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handl
|
|||
* This function gets the slave eDMA transfer count.
|
||||
*
|
||||
* @param base DSPI peripheral base address.
|
||||
* @param handle pointer to dspi_slave_edma_handle_t structure which stores the transfer state.
|
||||
* @param count Number of bytes transferred so far by the non-blocking transaction.
|
||||
* @param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state.
|
||||
* @param count A number of bytes transferred so far by the non-blocking transaction.
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue