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

Commit

Permalink
Cellular change only: add support for LARA-R6xxx-01B.
Browse files Browse the repository at this point in the history
Support is added for the 01B version of the LARA-R6 cellular module: changes only to reading of RSRP/RSRQ (which has changed format in the AT+UCGED response) and for removal of u-blox security services.

Note that the NORA-W36 module is temporarily removed from the DATABASE.md entry for test instance 30 (where the LARA-R6 01B module has been added); NORA-W36 will be added again once the code required to support the second generation uConnectExpress interface has been added.
  • Loading branch information
RobMeades committed Dec 12, 2023
1 parent 1b102f0 commit ecc3f98
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 67 deletions.
7 changes: 7 additions & 0 deletions cell/api/u_cell_sec.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ void uCellSecPrivateLink(void);
/** Get whether a cellular module supports u-blox security services
* or not.
*
* Note: if the module is switched on it will be interrogated to
* confirm that u-blox security services are supported, else
* the return value will be dictated by an internal table which will
* may be "true" for all variants when particular module variants
* do not, in fact, support u-blox security. Hence it is best to
* ensure that the module is on before calling this function.
*
* @param cellHandle the handle of the cellular instance.
* @return true if the cellular module supports u-blox
* security services else false.
Expand Down
38 changes: 28 additions & 10 deletions cell/src/u_cell_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,17 +467,35 @@ static int32_t getRadioParamsUcged2LaraR6(uAtClientHandle_t atHandle,
pRadioParameters->cellIdPhysical = uAtClientReadInt(atHandle);
// Skip <mTmsi>, <mmeGrId> and <mmeCode>
uAtClientSkipParameters(atHandle, 3);
// RSRP is element 11, as a plain-old dBm value
// In the LARA-R6 00B FW RSRP (element 11) and RSRQ (element 12)
// are plain-old dBm values, while in the LARA-R6 01B FW they are
// both 3GPP coded values. Since RSRP is negative in plain-old
// form and positive in 3GPP form we can, thankfully, tell the
// difference
x = uAtClientReadInt(atHandle);
// RSRQ is element 12, as a plain-old dB value.
y = uAtClientReadInt(atHandle);
if (uAtClientErrorGet(atHandle) == 0) {
// Note that these last two are usually negative
// integers, hence we check for errors here so as
// not to mix up what might be a negative error
// code with a negative return value.
pRadioParameters->rsrpDbm = x;
pRadioParameters->rsrqDb = y;
if (x >= 0) {
// RSRP is coded as specified in TS 36.133
pRadioParameters->rsrpDbm = uCellPrivateRsrpToDbm(x);
// RSRQ is coded as specified in TS 36.133.
x = uAtClientReadInt(atHandle);
if (uAtClientErrorGet(atHandle) == 0) {
// Note that this can be a negative integer, hence
// we check for errors here so as not to mix up
// what might be a negative error code with a
// negative return value.
pRadioParameters->rsrqDb = uCellPrivateRsrqToDb(x);
}
} else {
// RSRP and RSRQ are plain-old dB values.
y = uAtClientReadInt(atHandle);
if (uAtClientErrorGet(atHandle) == 0) {
// Note that these last two are usually negative
// integers, hence we check for errors here so as
// not to mix up what might be a negative error
// code with a negative return value.
pRadioParameters->rsrpDbm = x;
pRadioParameters->rsrqDb = y;
}
}
// SINR is element 13, directly in tenths of a dB, a
// decimal number with a mantissa, 255 if unknown.
Expand Down
104 changes: 52 additions & 52 deletions cell/src/u_cell_pwr.c
Original file line number Diff line number Diff line change
Expand Up @@ -857,51 +857,6 @@ static void UUPSMR_urc(uAtClientHandle_t atHandle, void *pParameter)
* STATIC FUNCTIONS: POWERING UP/DOWN
* -------------------------------------------------------------- */

// Check that the cellular module is alive.
static int32_t moduleIsAlive(uCellPrivateInstance_t *pInstance,
int32_t attempts)
{
int32_t errorCode = (int32_t) U_ERROR_COMMON_NOT_RESPONDING;
uAtClientDeviceError_t deviceError;
uAtClientHandle_t atHandle = pInstance->atHandle;
bool isAlive = false;

// It may be that we have been called when an AT client
// has just been instantiated (so it has no knowledge of
// previous transmit events against which to measure an
// inactivity time-out) and yet the module is already
// powered-on but is in UART power saving mode; call the
// wake-up call-back here to handle that case
if (!pInstance->inWakeUpCallback &&
(uCellPrivateWakeUpCallback(atHandle, pInstance) == 0)) {
// If it responds at this point then it must be alive,
// job done
isAlive = true;
} else {
// See if the cellular module is responding at the AT interface
// by poking it with "AT" up to "attempts" times.
// The response can be "OK" or it can also be "CMS/CMS ERROR"
// if the modem happened to be awake and in the middle
// of something from a previous command.
for (int32_t x = 0; !isAlive && (x < attempts); x++) {
uAtClientLock(atHandle);
uAtClientTimeoutSet(atHandle,
pInstance->pModule->responseMaxWaitMs);
uAtClientCommandStart(atHandle, "AT");
uAtClientCommandStopReadResponse(atHandle);
uAtClientDeviceErrorGet(atHandle, &deviceError);
isAlive = (uAtClientUnlock(atHandle) == 0) ||
(deviceError.type != U_AT_CLIENT_DEVICE_ERROR_TYPE_NO_ERROR);
}
}

if (isAlive) {
errorCode = (int32_t) U_ERROR_COMMON_SUCCESS;
}

return errorCode;
}

// Configure one item in the cellular module.
static bool moduleConfigureOne(uAtClientHandle_t atHandle,
const char *pAtString,
Expand Down Expand Up @@ -1309,7 +1264,7 @@ int32_t uCellPwrPrivateOn(uCellPrivateInstance_t *pInstance,
if (((pInstance->pinVInt >= 0) &&
(uPortGpioGet(pInstance->pinVInt) == U_CELL_PRIVATE_VINT_PIN_ON_STATE(pInstance->pinStates))) ||
((pInstance->pinVInt < 0) &&
(moduleIsAlive(pInstance, 1) == 0))) {
(uCellPwrPrivateIsAlive(pInstance, 1) == 0))) {
uPortLog("U_CELL_PWR: powering on, module is already on.\n");
// Configure the module. Since it was already
// powered on we might have been called from
Expand Down Expand Up @@ -1370,7 +1325,7 @@ int32_t uCellPwrPrivateOn(uCellPrivateInstance_t *pInstance,
(y > 0) && (errorCode != 0) &&
((pKeepGoingCallback == NULL) || pKeepGoingCallback(cellHandle));
y--) {
errorCode = moduleIsAlive(pInstance, 1);
errorCode = uCellPwrPrivateIsAlive(pInstance, 1);
}
if (errorCode == 0) {
// Configure the module, only putting into radio-off
Expand Down Expand Up @@ -1421,6 +1376,51 @@ int32_t uCellPwrPrivateOn(uCellPrivateInstance_t *pInstance,
return errorCode;
}

// Check that the cellular module is alive.
int32_t uCellPwrPrivateIsAlive(uCellPrivateInstance_t *pInstance,
int32_t attempts)
{
int32_t errorCode = (int32_t) U_ERROR_COMMON_NOT_RESPONDING;
uAtClientDeviceError_t deviceError;
uAtClientHandle_t atHandle = pInstance->atHandle;
bool isAlive = false;

// It may be that we have been called when an AT client
// has just been instantiated (so it has no knowledge of
// previous transmit events against which to measure an
// inactivity time-out) and yet the module is already
// powered-on but is in UART power saving mode; call the
// wake-up call-back here to handle that case
if (!pInstance->inWakeUpCallback &&
(uCellPrivateWakeUpCallback(atHandle, pInstance) == 0)) {
// If it responds at this point then it must be alive,
// job done
isAlive = true;
} else {
// See if the cellular module is responding at the AT interface
// by poking it with "AT" up to "attempts" times.
// The response can be "OK" or it can also be "CMS/CMS ERROR"
// if the modem happened to be awake and in the middle
// of something from a previous command.
for (int32_t x = 0; !isAlive && (x < attempts); x++) {
uAtClientLock(atHandle);
uAtClientTimeoutSet(atHandle,
pInstance->pModule->responseMaxWaitMs);
uAtClientCommandStart(atHandle, "AT");
uAtClientCommandStopReadResponse(atHandle);
uAtClientDeviceErrorGet(atHandle, &deviceError);
isAlive = (uAtClientUnlock(atHandle) == 0) ||
(deviceError.type != U_AT_CLIENT_DEVICE_ERROR_TYPE_NO_ERROR);
}
}

if (isAlive) {
errorCode = (int32_t) U_ERROR_COMMON_SUCCESS;
}

return errorCode;
}

// Decode an active time (T3324) string representing the binary value
// of a GPRS Timer 2 IE into seconds.
int32_t uCellPwrPrivateActiveTimeStrToSeconds(const char *pStr, int32_t *pSeconds)
Expand Down Expand Up @@ -1750,7 +1750,7 @@ bool uCellPwrIsAlive(uDeviceHandle_t cellHandle)

pInstance = pUCellPrivateGetInstance(cellHandle);
if (pInstance != NULL) {
isAlive = (moduleIsAlive(pInstance, 1) == 0);
isAlive = (uCellPwrPrivateIsAlive(pInstance, 1) == 0);
}

U_PORT_MUTEX_UNLOCK(gUCellPrivateMutex);
Expand Down Expand Up @@ -1957,8 +1957,8 @@ int32_t uCellPwrReboot(uDeviceHandle_t cellHandle,
uAtClientFlush(atHandle);
}
// Wait for the module to return to life and configure it
errorCode = moduleIsAlive(pInstance,
U_CELL_PWR_IS_ALIVE_ATTEMPTS_POWER_ON);
errorCode = uCellPwrPrivateIsAlive(pInstance,
U_CELL_PWR_IS_ALIVE_ATTEMPTS_POWER_ON);
if (errorCode == 0) {
// Sleep is no longer available
pInstance->deepSleepState = U_CELL_PRIVATE_DEEP_SLEEP_STATE_UNAVAILABLE;
Expand Down Expand Up @@ -2098,8 +2098,8 @@ int32_t uCellPwrResetHard(uDeviceHandle_t cellHandle, int32_t pinReset)
}
// Wait for the module to return to life and configure it
pInstance->lastCfunFlipTimeMs = uPortGetTickTimeMs();
errorCode = moduleIsAlive(pInstance,
U_CELL_PWR_IS_ALIVE_ATTEMPTS_POWER_ON);
errorCode = uCellPwrPrivateIsAlive(pInstance,
U_CELL_PWR_IS_ALIVE_ATTEMPTS_POWER_ON);
if (errorCode == 0) {
pInstance->deepSleepState = U_CELL_PRIVATE_DEEP_SLEEP_STATE_UNKNOWN;
// Configure the module
Expand Down
13 changes: 13 additions & 0 deletions cell/src/u_cell_pwr_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ extern "C" {
/** Power the cellular module on or wakeit from deep sleep. If this
* function returns success then the cellular module is ready to
* receive configuration commands and register with the cellular network.
*
* Note: gUCellPrivateMutex should be locked before this is called.
*
* @param pInstance a pointer to the instance.
Expand Down Expand Up @@ -77,6 +78,18 @@ int32_t uCellPwrPrivateOn(uCellPrivateInstance_t *pInstance,
bool (*pKeepGoingCallback) (uDeviceHandle_t),
bool allowPrinting);

/** Determine if the cellular module is alive.
*
* Note: gUCellPrivateMutex should be locked before this is called.
*
* @param pInstance a pointer to the instance.
* @param attempts the number of times to try poking it.
* @return zero if the module is alive, else negative
* error code.
*/
int32_t uCellPwrPrivateIsAlive(uCellPrivateInstance_t *pInstance,
int32_t attempts);

/** Decode a string representing the binary value of a 3GPP power
* saving active time (T3324) as a GPRS Timer 2 IE into seconds.
*
Expand Down
23 changes: 21 additions & 2 deletions cell/src/u_cell_sec.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "u_cell_net.h" // Order is important
#include "u_cell_private.h" // here don't change it
#include "u_cell_info.h" // For the IMEI
#include "u_cell_pwr_private.h"

#include "u_cell_sec.h"

Expand Down Expand Up @@ -203,17 +204,35 @@ bool uCellSecIsSupported(uDeviceHandle_t cellHandle)
{
bool isSupported = false;
uCellPrivateInstance_t *pInstance;
uAtClientHandle_t atHandle;
int32_t x;

if (gUCellPrivateMutex != NULL) {

U_PORT_MUTEX_LOCK(gUCellPrivateMutex);

pInstance = pUCellPrivateGetInstance(cellHandle);
if (pInstance != NULL) {
// No need to contact the module, this is something
// we know in advance for a given module type
isSupported = U_CELL_PRIVATE_HAS(pInstance->pModule,
U_CELL_PRIVATE_FEATURE_ROOT_OF_TRUST);
// If the module is powered-on, check that it
// _really_ has security services support
if (isSupported && (uCellPwrPrivateIsAlive(pInstance, 1) == 0)) {
isSupported = false;
atHandle = pInstance->atHandle;
uAtClientLock(atHandle);
// Poll the module for the UID of its root of trust
uAtClientCommandStart(atHandle, "AT+USECROTUID");
uAtClientCommandStop(atHandle);
uAtClientResponseStart(atHandle, "+USECROTUID:");
// Don't actually care about the answer, just that
// there is one
x = uAtClientReadString(atHandle, NULL, 0, false);
uAtClientResponseStop(atHandle);
if ((uAtClientUnlock(atHandle) == 0) && (x > 0)) {
isSupported = true;
}
}
}

U_PORT_MUTEX_UNLOCK(gUCellPrivateMutex);
Expand Down
2 changes: 1 addition & 1 deletion cell/test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ The module FW versions that these tests are run on are as follows:
- SARA-R412M-03B: none - no automated testing is performed on SARA-R412M-03B.
- SARA-R5: 02.05,A00.01 and 03.15,A00.01.
- SARA-R422: 00.12,A00.00.
- LARA-R6: 00.13,A00.01.
- LARA-R6: 00.13,A00.01 and 04.19,A00.01.
- LENA-R8: 02.00,A01.40.
3 changes: 2 additions & 1 deletion cell/test/u_cell_gpio_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,9 @@ U_PORT_TEST_FUNCTION("[cellGpio]", "cellGpioBasic")

// For toggling the CTS pin we need to know that it is not
// already in use for flow control and this command is also not
// supported on SARA-R4
// supported on SARA-R4 or LARA-R6
if (!U_CELL_PRIVATE_MODULE_IS_SARA_R4(pInstance->pModule->moduleType) &&
(pInstance->pModule->moduleType != U_CELL_MODULE_TYPE_LARA_R6) &&
!uCellInfoIsCtsFlowControlEnabled(cellHandle)) {
U_TEST_PRINT_LINE("getting CTS...");
x = uCellGpioGetCts(cellHandle);
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 @@ -64,7 +64,7 @@ The table below defines the instances of test hardware available on the `ubxlib`
| 27 | ESP32S3-DevKitC | ESP32S3 | | ESP-IDF | | M9 | port ubx_protocol gnss spartn | | U_CFG_TEST_GNSS_POWER_SAVING_NOT_SUPPORTED U_CFG_APP_GNSS_I2C=0 U_CFG_TEST_PIN_GNSS_RESET_N=40 U_GNSS_MGA_TEST_ASSIST_NOW_AUTONOMOUS_NOT_SUPPORTED U_CFG_TEST_PIN_A=1 U_CFG_TEST_PIN_B=9 U_CFG_TEST_PIN_C=38 U_CFG_TEST_PIN_UART_A_CTS=11 U_CFG_TEST_PIN_UART_A_RTS=47 U_CFG_TEST_PIN_UART_A_RXD=10 U_CFG_TEST_PIN_UART_A_TXD=48 U_CFG_APP_PIN_GNSS_SDA=18 U_CFG_APP_PIN_GNSS_SCL=17 U_CFG_MUTEX_DEBUG U_DEBUG_UTILS_DUMP_THREADS |
| 28 | Linux + EVK, Cat M1, uConnect | LINUX64 | | Linux | | SARA_R5 M9 NINA_W15 | port device network sock ble wifi cell short_range security mqtt_client http_client ubx_protocol gnss spartn location geofence |cell short_range gnss geodesic | U_CFG_GEOFENCE U_CFG_HEAP_MONITOR U_ASSERT_HOOK_FUNCTION_TEST_RETURN U_CFG_TEST_USE_VALGRIND U_CFG_CELL_DISABLE_UART_POWER_SAVING U_CFG_APP_UART_PREFIX=/dev/ttyAMA U_CFG_APP_CELL_UART=0 U_CFG_APP_PIN_CELL_PWR_ON=25 U_CELL_PWR_ON_PIN_DRIVE_MODE=U_PORT_GPIO_DRIVE_MODE_NORMAL U_CFG_APP_SHORT_RANGE_UART=1 U_CFG_APP_PIN_SHORT_RANGE_RESET_TO_DEFAULTS=26 U_CFG_APP_PIN_SHORT_RANGE_CTS=0 U_CFG_APP_PIN_SHORT_RANGE_RTS=0 U_BLE_TEST_CFG_REMOTE_SPS_CENTRAL=2462ABB6CC42p U_CFG_TEST_GNSS_SPI_SELECT_INDEX=0 U_CFG_APP_GNSS_SPI=0 U_CFG_APP_GNSS_I2C=8 U_CFG_TEST_PIN_GNSS_RESET_N=19 U_GNSS_MGA_TEST_HAS_FLASH U_CFG_TEST_UART_PREFIX=/tmp/ttyv U_CFG_TEST_UART_A=0 U_CFG_TEST_UART_B=1 U_AT_CLIENT_TEST_AT_TIMEOUT_TOLERANCE_MS=1000 U_CFG_TEST_PIN_A=17 U_CFG_TEST_PIN_B=27 U_CFG_TEST_PIN_C=22 U_CFG_MUTEX_DEBUG |
| 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_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, live network | STM32F4 | | STM32Cube | | LARA_R6 NORA_W36 | port device network sock ble wifi cell short_range security mqtt_client http_client location | cell short_range | CMSIS_V2 U_CFG_TEST_CELL_PWR_DISABLE HSE_VALUE=8000000U 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_CFG_APP_PIN_SHORT_RANGE_RESET_TO_DEFAULTS=0x42 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_DEBUG_UTILS_DUMP_THREADS |
| 30 | STM32F407 Discovery, NORA-W3, live network | STM32F4 | | STM32Cube | | LARA_R6 | port device network sock ble wifi cell short_range security mqtt_client http_client location | cell short_range | CMSIS_V2 U_CFG_TEST_CELL_PWR_DISABLE HSE_VALUE=8000000U 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_CFG_APP_PIN_SHORT_RANGE_RESET_TO_DEFAULTS=0x42 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_DEBUG_UTILS_DUMP_THREADS |

Notes:
- the \#defines listed are *overrides* on the default values that are defined in the code or additional to those defined in the code; they are not a complete list,
Expand Down

0 comments on commit ecc3f98

Please sign in to comment.