Skip to content
This repository has been archived by the owner on Nov 11, 2024. It is now read-only.

Commit

Permalink
Cellular SARA-U201 change only: correct UART power saving support.
Browse files Browse the repository at this point in the history
The behaviour of SARA-U201 when UART power saving is switched on was not handled properly: where it says in the AT manual "On SARA-U2 modules, when the AT+UPSV=1 command is issued by the DTE, the UART is immediately disabled" it really does mean _immediately_, there is not even an "OK" response.  Also, the module _immediately_ requires an "AT" or whatever to wake up, it doesn't wait the 6 seconds it has been asked to wait.

With this commit a new API is added to the AT client uAtClientWakeUpHandlerForce(), which tells the AT client that it has to do the "AT" thing to wake-up the module immediately, and the power-up sequence is modified so that if power saving is being switched on for a SARA-U201 it does not expect an "OK" response to the "AT+UPSV=1,1300" command.

Test: 32 cell
  • Loading branch information
RobMeades committed Jun 25, 2024
1 parent a8603c0 commit 9b8b29a
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 11 deletions.
49 changes: 41 additions & 8 deletions cell/src/u_cell_pwr.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@
*/
#define U_CELL_INITIAL_CONFIG_RETRIES 2

#ifndef U_CELL_PWR_SARA_U201_SHORT_AT_TIMEOUT_MS
/** SARA-U201 sometimes switches off the UART to power save mode
* before it has sent the "OK" response, so use a short-timeout
* for that case to avoid hanging about when we're meant to be
* saving power.
*/
# define U_CELL_PWR_SARA_U201_SHORT_AT_TIMEOUT_MS 2000
#endif

/* ----------------------------------------------------------------
* TYPES
* -------------------------------------------------------------- */
Expand Down Expand Up @@ -899,11 +908,15 @@ static void UUPSMR_urc(uAtClientHandle_t atHandle, void *pParameter)
// Configure one item in the cellular module.
static bool moduleConfigureOne(uAtClientHandle_t atHandle,
const char *pAtString,
int32_t configurationTries)
int32_t configurationTries,
int32_t atTimeoutMs)
{
bool success = false;
for (size_t x = configurationTries; (x > 0) && !success; x--) {
uAtClientLock(atHandle);
if (atTimeoutMs >= 0) {
uAtClientTimeoutSet(atHandle, atTimeoutMs);
}
uAtClientCommandStart(atHandle, pAtString);
uAtClientCommandStopReadResponse(atHandle);
success = (uAtClientUnlock(atHandle) == 0);
Expand All @@ -922,6 +935,7 @@ static int32_t moduleConfigure(uCellPrivateInstance_t *pInstance,
uAtClientStreamHandle_t stream = U_AT_CLIENT_STREAM_HANDLE_DEFAULTS;
uCellPwrPsvMode_t uartPowerSavingMode = U_CELL_PWR_PSV_MODE_DISABLED; // Assume no UART power saving
char buffer[20]; // Enough room for AT+UPSV=2,1300
int32_t atTimeoutMs = -1;
#if U_CELL_PWR_GNSS_PROFILE_BITS_EXTRA >= 0
char *pServerNameGnss;
int32_t y;
Expand All @@ -932,7 +946,7 @@ static int32_t moduleConfigure(uCellPrivateInstance_t *pInstance,
(x < sizeof(gpConfigCommand) / sizeof(gpConfigCommand[0])) &&
success; x++) {
success = moduleConfigureOne(atHandle, gpConfigCommand[x],
U_CELL_PWR_CONFIGURATION_COMMAND_TRIES);
U_CELL_PWR_CONFIGURATION_COMMAND_TRIES, -1);
}

if (success &&
Expand All @@ -943,10 +957,10 @@ static int32_t moduleConfigure(uCellPrivateInstance_t *pInstance,
// (SARA-R5 and SARA-U201 have a single mode and require no setting)
if (U_CELL_PRIVATE_HAS(pInstance->pModule, U_CELL_PRIVATE_FEATURE_UCGED5)) {
success = moduleConfigureOne(atHandle, "AT+UCGED=5",
U_CELL_PWR_CONFIGURATION_COMMAND_TRIES);
U_CELL_PWR_CONFIGURATION_COMMAND_TRIES, -1);
} else {
success = moduleConfigureOne(atHandle, "AT+UCGED=2",
U_CELL_PWR_CONFIGURATION_COMMAND_TRIES);
U_CELL_PWR_CONFIGURATION_COMMAND_TRIES, -1);
}
}

Expand All @@ -961,7 +975,7 @@ static int32_t moduleConfigure(uCellPrivateInstance_t *pInstance,
// of a cellular module
if (uPortUartIsRtsFlowControlEnabled(stream.handle.int32) &&
uPortUartIsCtsFlowControlEnabled(stream.handle.int32)) {
moduleConfigureOne(atHandle, "AT&K3", 1);
moduleConfigureOne(atHandle, "AT&K3", 1, -1);
if (uAtClientWakeUpHandlerIsSet(atHandle)) {
// The RTS/CTS handshaking lines are being used
// for flow control by the UART HW. This complicates
Expand All @@ -984,7 +998,7 @@ static int32_t moduleConfigure(uCellPrivateInstance_t *pInstance,
}
}
} else {
moduleConfigureOne(atHandle, "AT&K0", 1);
moduleConfigureOne(atHandle, "AT&K0", 1, -1);
// RTS/CTS handshaking is not used by the UART HW, we
// can use the wake-up on TX line feature without any
// complications
Expand Down Expand Up @@ -1048,7 +1062,18 @@ static int32_t moduleConfigure(uCellPrivateInstance_t *pInstance,
}
// Use the UART power saving mode AT command to set the mode
// in the module
if (!moduleConfigureOne(atHandle, buffer, 1) &&
// Note: SARA-U201 does not always respond to the AT+UPSV=1 command,
// it disables the UART immediately, hence here we set a short
// AT timeoutand ignore a failure to configure power saving if
// the module type is SARA-U201 and the power saving state is enabled
if ((pInstance->pModule->moduleType == U_CELL_MODULE_TYPE_SARA_U201) &&
(uartPowerSavingMode != U_CELL_PWR_PSV_MODE_DISABLED)) {
atTimeoutMs = U_CELL_PWR_SARA_U201_SHORT_AT_TIMEOUT_MS;
}

if ((!moduleConfigureOne(atHandle, buffer, 1, atTimeoutMs) &&
!((pInstance->pModule->moduleType == U_CELL_MODULE_TYPE_SARA_U201) &&
(uartPowerSavingMode != U_CELL_PWR_PSV_MODE_DISABLED))) &&
uAtClientWakeUpHandlerIsSet(atHandle) &&
!returningFromSleep) {
// If AT+UPSV returns error and we're not already returning
Expand All @@ -1059,6 +1084,14 @@ static int32_t moduleConfigure(uCellPrivateInstance_t *pInstance,
uAtClientSetWakeUpHandler(atHandle, NULL, NULL, 0);
uPortLog("U_CELL_PWR: power saving not supported.\n");
}
// If we have successfully enabled UART power saving on SARA-U201
// it is _immediately_ in UART power-saving mode, it doesn't wait
// for 6 seconds, so we have to tell the AT client that
if ((pInstance->pModule->moduleType == U_CELL_MODULE_TYPE_SARA_U201) &&
(uartPowerSavingMode != U_CELL_PWR_PSV_MODE_DISABLED)) {
uAtClientWakeUpHandlerForce(atHandle);
}

// Now tell the AT Client that it should control the
// DTR pin, if relevant
if (!returningFromSleep && (uartPowerSavingMode == U_CELL_PWR_PSV_MODE_DTR)) {
Expand All @@ -1074,7 +1107,7 @@ static int32_t moduleConfigure(uCellPrivateInstance_t *pInstance,
if (U_CELL_PRIVATE_HAS(pInstance->pModule,
U_CELL_PRIVATE_FEATURE_DEEP_SLEEP_URC)) {
success = moduleConfigureOne(atHandle, "AT+UPSMR=1",
U_CELL_PWR_CONFIGURATION_COMMAND_TRIES);
U_CELL_PWR_CONFIGURATION_COMMAND_TRIES, -1);
if (success && !returningFromSleep) {
// Add the URC handler if it wasn't there before
uAtClientSetUrcHandler(pInstance->atHandle, "+UUPSMR:",
Expand Down
8 changes: 8 additions & 0 deletions common/at_client/api/u_at_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -1759,6 +1759,14 @@ int32_t uAtClientSetWakeUpHandler(uAtClientHandle_t atHandle,
*/
bool uAtClientWakeUpHandlerIsSet(const uAtClientHandle_t atHandle);

/** Force the timeout of an AT wake-up handler set using
* uAtClientSetWakeUpHandler().
*
* @param atHandle the handle of the AT client.
* @return zero on success else negative error code.
*/
int32_t uAtClientWakeUpHandlerForce(const uAtClientHandle_t atHandle);

/** Get the current wake-up handler function and parameters.
*
* @param atHandle the handle of the AT client.
Expand Down
25 changes: 23 additions & 2 deletions common/at_client/src/u_at_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ typedef struct uAtClientInstance_t {
uTimeoutStart_t lastResponseStop; /** The time the last response ended in milliseconds. */
int32_t lockTimeMs; /** The time when the stream was locked. */
uTimeoutStart_t lastTxTime; /** The time when the last transmit activity was carried out. */
bool forceNextWakeUp; /** True if the application requires the AT client to force a module wake-up next time. */
size_t urcMaxStringLength; /** The longest URC string to monitor for. */
size_t maxRespLength; /** The max length of OK, (CME) (CMS) ERROR and URCs. */
bool delimiterRequired; /** Is a delimiter to be inserted before the next parameter or not. */
Expand Down Expand Up @@ -2264,9 +2265,12 @@ static size_t write(uAtClientInstance_t *pClient,
(pClient->error == U_ERROR_COMMON_SUCCESS)) {
lengthToWrite = length - (pData - pDataStart);
if ((pClient->pWakeUp != NULL) &&
uTimeoutExpiredMs(pClient->lastTxTime,
pClient->pWakeUp->inactivityTimeoutMs) &&
(uTimeoutExpiredMs(pClient->lastTxTime,
pClient->pWakeUp->inactivityTimeoutMs) ||
(pClient->forceNextWakeUp)) &&
(uPortMutexTryLock(pClient->pWakeUp->inWakeUpHandlerMutex, 0) == 0)) {
// Reset the force next flag
pClient->forceNextWakeUp = false;
// We have a wake-up handler, the inactivity timeout
// has expired and we've managed to lock the wake-up
// handler mutex (if we aren't able to lock the wake-up
Expand Down Expand Up @@ -4516,6 +4520,23 @@ bool uAtClientWakeUpHandlerIsSet(const uAtClientHandle_t atHandle)
return ((const uAtClientInstance_t *) atHandle)->pWakeUp != NULL;
}

// Force the next timeout of the AT wake-up handler.
int32_t uAtClientWakeUpHandlerForce(const uAtClientHandle_t atHandle)
{
int32_t errorCode = (int32_t) U_ERROR_COMMON_NOT_SUPPORTED;
uAtClientInstance_t *pClient = (uAtClientInstance_t *) atHandle;

U_AT_CLIENT_LOCK_CLIENT_MUTEX(pClient);

if (pClient->pWakeUp != NULL) {
pClient->forceNextWakeUp = true;
}

U_AT_CLIENT_UNLOCK_CLIENT_MUTEX(pClient);

return errorCode;
}

// Get the current wake-up handler function and parameters.
void uAtClientGetWakeUpHandler(uAtClientHandle_t atHandle,
int32_t (**ppHandler) (uAtClientHandle_t,
Expand Down
2 changes: 1 addition & 1 deletion port/platform/common/automation/DATABASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ The table below defines the instances of test hardware available on the `ubxlib`
| 29 | HPG C214 board (NINA-W1), live network | ESP32 | | ESP-IDF | | LENA_R8 M9 | port device network sock cell security mqtt_client gnss location || U_CFG_PPP_ENABLE U_HTTP_CLIENT_DISABLE_TEST U_CELL_GPIO_DISABLE_TEST U_MQTT_CLIENT_TEST_NO_NULL_SEND U_CFG_TEST_GNSS_POWER_SAVING_NOT_SUPPORTED U_GNSS_MGA_TEST_ASSIST_NOW_AUTONOMOUS_NOT_SUPPORTED U_CELL_CFG_TEST_USE_FIXED_TIME_SECONDS U_CFG_MONITOR_DTR_RTS_OFF U_CELL_TEST_NO_INVALID_APN U_CELL_TEST_CFG_BANDMASK1=0x0000000000080084ULL U_CELL_NET_TEST_RAT=U_CELL_NET_RAT_LTE U_CFG_APP_PIN_CELL_ENABLE_POWER=-1 U_CFG_APP_PIN_CELL_PWR_ON=0x801a U_CFG_APP_PIN_CELL_RESET=33 U_CELL_RESET_PIN_DRIVE_MODE=U_PORT_GPIO_DRIVE_MODE_NORMAL U_CFG_APP_PIN_CELL_VINT=0x8025 U_CFG_APP_PIN_CELL_DTR=15 U_CFG_APP_PIN_CELL_TXD=25 U_CFG_APP_PIN_CELL_RXD=34 U_CFG_APP_PIN_CELL_RTS=27 U_CFG_APP_PIN_CELL_CTS=36 U_CFG_APP_GNSS_I2C=0 U_GNSS_TEST_I2C_ADDRESS_EXTRA=0x43 U_CFG_APP_CELL_PIN_GNSS_POWER=-1 U_CFG_APP_CELL_PIN_GNSS_DATA_READY=-1 U_CFG_TEST_PIN_A=-1 U_CFG_TEST_PIN_B=-1 U_CFG_TEST_PIN_C=-1 U_CFG_TEST_UART_A=-1 U_DEBUG_UTILS_DUMP_THREADS |
| 30 | STM32F407 Discovery, NORA-W3, SARA-R520 EVK| STM32F4 | | STM32Cube | | SARA_R52 M10 NORA_W36 | port device network sock cell ble wifi short_range gnss security mqtt_client http_client location | cell gnss short_range short_range_gen2 | CMSIS_V2 HSE_VALUE=8000000U U_CFG_TEST_GNSS_POWER_SAVING_NOT_SUPPORTED U_CFG_APP_GNSS_UART=-1 U_CFG_LOC_TEST_CHANGE_SYSTEM_TYPES_DISABLE U_CFG_APP_PIN_C030_ENABLE_3V3=-1 U_CFG_APP_PIN_CELL_RESET=-1 U_CFG_APP_CELL_UART=2 U_CFG_APP_PIN_CELL_TXD=0x03 U_CFG_APP_PIN_CELL_RXD=0x02 U_CFG_APP_PIN_CELL_RTS=-1 U_CFG_APP_PIN_CELL_CTS=-1 U_CFG_TEST_PIN_A=-1 U_CFG_TEST_PIN_B=-1 U_CFG_TEST_PIN_C=-1 U_CFG_TEST_UART_A=-1 U_BLE_TEST_CFG_REMOTE_SPS_CENTRAL=2462ABB6CC42p U_BLE_TEST_CFG_REMOTE_SPS_PERIPHERAL=2462ABB6EAC6p U_CFG_APP_SHORT_RANGE_ROLE=3 U_CFG_APP_SHORT_RANGE_UART2=6 U_CFG_APP_PIN_SHORT_RANGE_TXD2=0x26 U_CFG_APP_PIN_SHORT_RANGE_RXD2=0x27 U_DEBUG_UTILS_DUMP_THREADS U_CFG_TEST_GNSS_TRANSPORT_AT_DISABLE |
| 31 | STM32F7, Nucleo-F767ZI, LARA-R6, live net | STM32 | nucleo_f767zi | Zephyr | | LARA_R6 | port device network sock cell security mqtt_client http_client location || U_ZEPHYR_PORT_UART_ASYNC U_CFG_TEST_DISABLE_MUX U_CFG_TEST_CELL_PWR_DISABLE U_CELL_TEST_CFG_APN=iot.1nce.net U_CELL_CFG_TEST_USE_FIXED_TIME_SECONDS U_CELL_TEST_NO_INVALID_APN U_CELL_TEST_CFG_BANDMASK1=0x0000000000080084ULL U_CELL_NET_TEST_RAT=U_CELL_NET_RAT_LTE U_CELL_TEST_CFG_MNO_PROFILE=90 U_DEBUG_UTILS_DUMP_THREADS |
| 32 | STM32U5, Nucleo-U575ZI-q | STM32 | nucleo_u575zi_q | Zephyr | | SARA_U201 M9 ODIN_W2 | port device network sock cell ble wifi short_range gnss security http_client location ubx_protocol spartn || U_CFG_CELL_DISABLE_UART_POWER_SAVING U_CELL_NET_TEST_RAT=U_CELL_NET_RAT_GSM_GPRS_EGPRS U_CELL_TEST_CFG_APN=iot.1nce.net U_CELL_CFG_APN_DEFAULT=iot.1nce.net U_CFG_TEST_TRANSPORT_SECURITY_DISABLE U_CELL_CFG_TEST_USE_FIXED_TIME_SECONDS U_CELL_TEST_NO_INVALID_APN U_CFG_CELL_DISABLE_UART_POWER_SAVING U_CFG_APP_GNSS_I2C=1 U_CFG_APP_I2C_MAX_SEGMENT_SIZE=255 U_GNSS_MGA_TEST_HAS_FLASH U_CFG_TEST_GNSS_POWER_SAVING_NOT_SUPPORTED U_GNSS_MGA_TEST_ASSIST_NOW_AUTONOMOUS_NOT_SUPPORTED U_CFG_TEST_PIN_GNSS_RESET_N=0x5D U_CFG_APP_SHORT_RANGE_UART=3 U_CFG_TEST_BLE_DISABLE_SPS U_CFG_TEST_UART_A=-1 U_DEBUG_UTILS_DUMP_THREADS |
| 32 | STM32U5, Nucleo-U575ZI-q | STM32 | nucleo_u575zi_q | Zephyr | | SARA_U201 M9 ODIN_W2 | port device network sock cell ble wifi short_range gnss security http_client location ubx_protocol spartn || U_CELL_NET_TEST_RAT=U_CELL_NET_RAT_GSM_GPRS_EGPRS U_CELL_TEST_CFG_APN=iot.1nce.net U_CELL_CFG_APN_DEFAULT=iot.1nce.net U_CFG_TEST_TRANSPORT_SECURITY_DISABLE U_CELL_CFG_TEST_USE_FIXED_TIME_SECONDS U_CELL_TEST_NO_INVALID_APN U_CFG_APP_GNSS_I2C=1 U_CFG_APP_I2C_MAX_SEGMENT_SIZE=255 U_GNSS_MGA_TEST_HAS_FLASH U_CFG_TEST_GNSS_POWER_SAVING_NOT_SUPPORTED U_GNSS_MGA_TEST_ASSIST_NOW_AUTONOMOUS_NOT_SUPPORTED U_CFG_TEST_PIN_GNSS_RESET_N=0x5D U_CFG_APP_SHORT_RANGE_UART=3 U_CFG_TEST_BLE_DISABLE_SPS U_CFG_TEST_UART_A=-1 U_DEBUG_UTILS_DUMP_THREADS |
| 33 | ESP32-DevKitC + EVK, live network | ESP32 | | ESP-IDF | | | port device network sock cell security mqtt_client http_client || U_CFG_TEST_UART_A=-1 U_CFG_TEST_PIN_A=-1 U_CFG_TEST_PIN_B=-1 U_CFG_TEST_PIN_C=-1 U_CFG_APP_PIN_CELL_VINT=-1 U_CFG_APP_PIN_CELL_ENABLE_POWER=-1 U_CFG_APP_CELL_PIN_GNSS_POWER=-1 U_CFG_APP_CELL_PIN_GNSS_DATA_READY=-1 U_DEBUG_UTILS_DUMP_THREADS |

Notes:
Expand Down

0 comments on commit 9b8b29a

Please sign in to comment.