lc15: port lc15bts-mgr dependency changes
That's mostly changes related to lc15bts-mgr from https://gitlab.com/nrw_noa/osmo-bts branch nrw/litecell15 based on eb5b7f80510b603579f7af6d7d5ead296c2fa260 commit: * adjust comments to simplify further diffs * add libsystemd dependency to lc15bts-mgr * add software watchdog which uses it * ocxo calibration and gps related code Change-Id: I475a330af771891ba3c897294ce0dd57ec2ba8db Related: SYS#3732
This commit is contained in:
parent
8785978c37
commit
0ebf985492
|
@ -143,6 +143,7 @@ if test "$enable_litecell15" = "yes"; then
|
|||
AC_CHECK_HEADER([nrw/litecell15/litecell15.h],[],
|
||||
[AC_MSG_ERROR([nrw/litecell15/litecell15.h can not be found in $litecell15_incdir])],
|
||||
[#include <nrw/litecell15/litecell15.h>])
|
||||
PKG_CHECK_MODULES(LIBSYSTEMD, libsystemd)
|
||||
CPPFLAGS=$oldCPPFLAGS
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
|
||||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(OPENBSC_INCDIR) -I$(LITECELL15_INCDIR)
|
||||
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBGPS_CFLAGS) $(ORTP_CFLAGS)
|
||||
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBGPS_CFLAGS) $(ORTP_CFLAGS) $(LIBSYSTEMD_CFLAGS)
|
||||
COMMON_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) $(ORTP_LIBS)
|
||||
|
||||
AM_CFLAGS += -DENABLE_LC15BTS
|
||||
|
||||
EXTRA_DIST = misc/lc15bts_mgr.h misc/lc15bts_misc.h misc/lc15bts_par.h misc/lc15bts_led.h \
|
||||
misc/lc15bts_temp.h misc/lc15bts_power.h misc/lc15bts_clock.h \
|
||||
misc/lc15bts_bid.h misc/lc15bts_nl.h misc/lc15bts_bts.h \
|
||||
misc/lc15bts_bid.h misc/lc15bts_nl.h misc/lc15bts_bts.h misc/lc15bts_swd.h \
|
||||
hw_misc.h l1_if.h l1_transp.h lc15bts.h oml_router.h utils.h
|
||||
|
||||
bin_PROGRAMS = osmo-bts-lc15 lc15bts-mgr lc15bts-util
|
||||
|
@ -29,9 +29,10 @@ lc15bts_mgr_SOURCES = \
|
|||
misc/lc15bts_mgr_temp.c \
|
||||
misc/lc15bts_mgr_calib.c \
|
||||
misc/lc15bts_led.c \
|
||||
misc/lc15bts_bts.c
|
||||
misc/lc15bts_bts.c \
|
||||
misc/lc15bts_swd.c
|
||||
|
||||
lc15bts_mgr_LDADD = $(top_builddir)/src/common/libbts.a $(LIBGPS_LIBS) $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCTRL_LIBS) $(COMMON_LDADD)
|
||||
lc15bts_mgr_LDADD = $(top_builddir)/src/common/libbts.a $(LIBGPS_LIBS) $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCTRL_LIBS) $(LIBSYSTEMD_LIBS) $(COMMON_LDADD)
|
||||
|
||||
lc15bts_util_SOURCES = misc/lc15bts_util.c misc/lc15bts_par.c
|
||||
lc15bts_util_LDADD = $(LIBOSMOCORE_LIBS)
|
||||
|
|
|
@ -42,10 +42,9 @@
|
|||
#include "lc15bts.h"
|
||||
#include "utils.h"
|
||||
|
||||
/**
|
||||
* * Maximum calibration data chunk size
|
||||
* */
|
||||
/* Maximum calibration data chunk size */
|
||||
#define MAX_CALIB_TBL_SIZE 65536
|
||||
/* Calibration header version */
|
||||
#define CALIB_HDR_V1 0x01
|
||||
|
||||
struct calib_file_desc {
|
||||
|
@ -93,19 +92,19 @@ struct calTbl_t
|
|||
{
|
||||
struct
|
||||
{
|
||||
uint8_t u8Version; // Header version (1)
|
||||
uint8_t u8Parity; // Parity byte (xor)
|
||||
uint8_t u8Type; // Table type (0:TX Downlink, 1:RX-A Uplink, 2:RX-B Uplink)
|
||||
uint8_t u8Band; // GSM Band (0:GSM-850, 1:EGSM-900, 2:DCS-1800, 3:PCS-1900)
|
||||
uint32_t u32Len; // Table length in bytes including the header
|
||||
uint8_t u8Version; /* Header version (1) */
|
||||
uint8_t u8Parity; /* Parity byte (xor) */
|
||||
uint8_t u8Type; /* Table type (0:TX Downlink, 1:RX-A Uplink, 2:RX-B Uplink) */
|
||||
uint8_t u8Band; /* GSM Band (0:GSM-850, 1:EGSM-900, 2:DCS-1800, 3:PCS-1900) */
|
||||
uint32_t u32Len; /* Table length in bytes including the header */
|
||||
struct
|
||||
{
|
||||
uint32_t u32DescOfst; // Description section offset
|
||||
uint32_t u32DateOfst; // Date section offset
|
||||
uint32_t u32StationOfst; // Calibration test station section offset
|
||||
uint32_t u32FpgaFwVerOfst; // Calibration FPGA firmware version section offset
|
||||
uint32_t u32DspFwVerOfst; // Calibration DSP firmware section offset
|
||||
uint32_t u32DataOfst; // Calibration data section offset
|
||||
uint32_t u32DescOfst; /* Description section offset */
|
||||
uint32_t u32DateOfst; /* Date section offset */
|
||||
uint32_t u32StationOfst; /* Calibration test station section offset */
|
||||
uint32_t u32FpgaFwVerOfst; /* Calibration FPGA firmware version section offset */
|
||||
uint32_t u32DspFwVerOfst; /* Calibration DSP firmware section offset */
|
||||
uint32_t u32DataOfst; /* Calibration data section offset */
|
||||
} toc;
|
||||
} v1;
|
||||
} hdr;
|
||||
|
@ -314,15 +313,14 @@ static int calib_verify(struct lc15l1_hdl *fl1h, const struct calib_file_desc *d
|
|||
struct calTbl_t *calTbl;
|
||||
char calChkSum ;
|
||||
|
||||
|
||||
//calculate file size in bytes
|
||||
/* calculate file size in bytes */
|
||||
fseek(st->fp, 0L, SEEK_END);
|
||||
sz = ftell(st->fp);
|
||||
|
||||
//rewind read poiner
|
||||
/* rewind read poiner */
|
||||
fseek(st->fp, 0L, SEEK_SET);
|
||||
|
||||
//read file
|
||||
/* read file */
|
||||
rbuf = (char *) malloc( sizeof(char) * sz );
|
||||
|
||||
rc = fread(rbuf, 1, sizeof(char) * sz, st->fp);
|
||||
|
@ -331,7 +329,7 @@ static int calib_verify(struct lc15l1_hdl *fl1h, const struct calib_file_desc *d
|
|||
LOGP(DL1C, LOGL_ERROR, "%s reading error\n", desc->fname);
|
||||
free(rbuf);
|
||||
|
||||
//close file
|
||||
/* close file */
|
||||
rc = calib_file_close(fl1h);
|
||||
if (rc < 0 ) {
|
||||
LOGP(DL1C, LOGL_ERROR, "%s can not close\n", desc->fname);
|
||||
|
@ -341,33 +339,32 @@ static int calib_verify(struct lc15l1_hdl *fl1h, const struct calib_file_desc *d
|
|||
return -2;
|
||||
}
|
||||
|
||||
|
||||
calTbl = (struct calTbl_t*) rbuf;
|
||||
//calcualte file checksum
|
||||
/* calculate file checksum */
|
||||
calChkSum = 0;
|
||||
while ( sz-- ) {
|
||||
calChkSum ^= rbuf[sz];
|
||||
}
|
||||
|
||||
//validate Tx calibration parity
|
||||
/* validate Tx calibration parity */
|
||||
if ( calChkSum ) {
|
||||
LOGP(DL1C, LOGL_ERROR, "%s has invalid checksum %x.\n", desc->fname, calChkSum);
|
||||
return -4;
|
||||
}
|
||||
|
||||
//validate Tx calibration header
|
||||
/* validate Tx calibration header */
|
||||
if ( calTbl->hdr.v1.u8Version != CALIB_HDR_V1 ) {
|
||||
LOGP(DL1C, LOGL_ERROR, "%s has invalid header version %u.\n", desc->fname, calTbl->hdr.v1.u8Version);
|
||||
return -5;
|
||||
}
|
||||
|
||||
//validate calibration description
|
||||
/* validate calibration description */
|
||||
if ( calTbl->hdr.v1.toc.u32DescOfst == 0xFFFFFFFF ) {
|
||||
LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration description offset.\n", desc->fname);
|
||||
return -6;
|
||||
}
|
||||
|
||||
//validate calibration date
|
||||
/* validate calibration date */
|
||||
if ( calTbl->hdr.v1.toc.u32DateOfst == 0xFFFFFFFF ) {
|
||||
LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration date offset.\n", desc->fname);
|
||||
return -7;
|
||||
|
@ -377,24 +374,25 @@ static int calib_verify(struct lc15l1_hdl *fl1h, const struct calib_file_desc *d
|
|||
desc->fname,
|
||||
calTbl->u8RawData + calTbl->hdr.v1.toc.u32DateOfst);
|
||||
|
||||
//validate calibration station
|
||||
/* validate calibration station */
|
||||
if ( calTbl->hdr.v1.toc.u32StationOfst == 0xFFFFFFFF ) {
|
||||
LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration station ID offset.\n", desc->fname);
|
||||
return -8;
|
||||
}
|
||||
|
||||
//validate FPGA FW version
|
||||
/* validate FPGA FW version */
|
||||
if ( calTbl->hdr.v1.toc.u32FpgaFwVerOfst == 0xFFFFFFFF ) {
|
||||
LOGP(DL1C, LOGL_ERROR, "%s has invalid FPGA FW version offset.\n", desc->fname);
|
||||
return -9;
|
||||
}
|
||||
//validate DSP FW version
|
||||
|
||||
/* validate DSP FW version */
|
||||
if ( calTbl->hdr.v1.toc.u32DspFwVerOfst == 0xFFFFFFFF ) {
|
||||
LOGP(DL1C, LOGL_ERROR, "%s has invalid DSP FW version offset.\n", desc->fname);
|
||||
return -10;
|
||||
}
|
||||
|
||||
//validate Tx calibration data offset
|
||||
/* validate Tx calibration data offset */
|
||||
if ( calTbl->hdr.v1.toc.u32DataOfst == 0xFFFFFFFF ) {
|
||||
LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration data offset.\n", desc->fname);
|
||||
return -11;
|
||||
|
@ -402,11 +400,11 @@ static int calib_verify(struct lc15l1_hdl *fl1h, const struct calib_file_desc *d
|
|||
|
||||
if ( !desc->rx ) {
|
||||
|
||||
//parse min/max Tx power
|
||||
/* parse min/max Tx power */
|
||||
fl1h->phy_inst->u.lc15.minTxPower = calTbl->u8RawData[calTbl->hdr.v1.toc.u32DataOfst + (5 << 2)];
|
||||
fl1h->phy_inst->u.lc15.maxTxPower = calTbl->u8RawData[calTbl->hdr.v1.toc.u32DataOfst + (6 << 2)];
|
||||
|
||||
//override nominal Tx power of given TRX if needed
|
||||
/* override nominal Tx power of given TRX if needed */
|
||||
if ( fl1h->phy_inst->trx->nominal_power > fl1h->phy_inst->u.lc15.maxTxPower) {
|
||||
LOGP(DL1C, LOGL_INFO, "Set TRX %u nominal Tx power to %d dBm (%d)\n",
|
||||
plink->num,
|
||||
|
@ -449,7 +447,7 @@ static int calib_verify(struct lc15l1_hdl *fl1h, const struct calib_file_desc *d
|
|||
fl1h->phy_inst->u.lc15.maxTxPower );
|
||||
}
|
||||
|
||||
//rewind read poiner for subsequence tasks
|
||||
/* rewind read pointer for subsequence tasks */
|
||||
fseek(st->fp, 0L, SEEK_SET);
|
||||
free(rbuf);
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#include "misc/lc15bts_par.h"
|
||||
#include "misc/lc15bts_bid.h"
|
||||
#include "misc/lc15bts_power.h"
|
||||
#include "misc/lc15bts_swd.h"
|
||||
|
||||
#include "lc15bts_led.h"
|
||||
|
||||
static int no_rom_write = 0;
|
||||
|
@ -163,6 +165,7 @@ static void check_sensor_timer_cb(void *unused)
|
|||
lc15bts_check_vswr(no_rom_write);
|
||||
osmo_timer_schedule(&sensor_timer, SENSOR_TIMER_SECS, 0);
|
||||
/* TODO checks if lc15bts_check_temp/lc15bts_check_power/lc15bts_check_vswr went ok */
|
||||
lc15bts_swd_event(&manager, SWD_CHECK_SENSOR);
|
||||
}
|
||||
|
||||
static struct osmo_timer_list hours_timer;
|
||||
|
@ -172,6 +175,7 @@ static void hours_timer_cb(void *unused)
|
|||
|
||||
osmo_timer_schedule(&hours_timer, HOURS_TIMER_SECS, 0);
|
||||
/* TODO: validates if lc15bts_update_hours went correctly */
|
||||
lc15bts_swd_event(&manager, SWD_UPDATE_HOURS);
|
||||
}
|
||||
|
||||
static void print_help(void)
|
||||
|
@ -317,6 +321,10 @@ int main(int argc, char **argv)
|
|||
INIT_LLIST_HEAD(&manager.lc15bts_leds.list);
|
||||
INIT_LLIST_HEAD(&manager.alarms.list);
|
||||
|
||||
/* Initialize the service watchdog notification for SWD_LAST event(s) */
|
||||
if (lc15bts_swd_init(&manager, (int)(SWD_LAST)) != 0)
|
||||
exit(3);
|
||||
|
||||
/* start temperature check timer */
|
||||
sensor_timer.cb = check_sensor_timer_cb;
|
||||
check_sensor_timer_cb(NULL);
|
||||
|
@ -357,5 +365,6 @@ int main(int argc, char **argv)
|
|||
while (1) {
|
||||
log_reset_context();
|
||||
osmo_select_main(0);
|
||||
lc15bts_swd_event(&manager, SWD_MAINLOOP);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include "misc/lc15bts_mgr.h"
|
||||
#include "misc/lc15bts_misc.h"
|
||||
#include "misc/lc15bts_clock.h"
|
||||
#include "misc/lc15bts_swd.h"
|
||||
#include "misc/lc15bts_par.h"
|
||||
#include "misc/lc15bts_led.h"
|
||||
#include "osmo-bts/msg_utils.h"
|
||||
|
||||
#include <osmocom/core/logging.h>
|
||||
|
@ -41,10 +44,14 @@
|
|||
#include <osmocom/abis/e1_input.h>
|
||||
#include <osmocom/abis/ipa.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
static void calib_adjust(struct lc15bts_mgr_instance *mgr);
|
||||
static void calib_state_reset(struct lc15bts_mgr_instance *mgr, int reason);
|
||||
static void calib_loop_run(void *_data);
|
||||
|
||||
static int ocxodac_saved_value = -1;
|
||||
|
||||
enum calib_state {
|
||||
CALIB_INITIAL,
|
||||
CALIB_IN_PROGRESS,
|
||||
|
@ -88,7 +95,9 @@ static void calib_adjust(struct lc15bts_mgr_instance *mgr)
|
|||
int interval_sec;
|
||||
int dac_value;
|
||||
int new_dac_value;
|
||||
double dac_correction;
|
||||
int dac_correction;
|
||||
time_t now;
|
||||
time_t last_gps_fix;
|
||||
|
||||
rc = lc15bts_clock_err_get(&fault, &error_ppt,
|
||||
&accuracy_ppq, &interval_sec);
|
||||
|
@ -99,12 +108,32 @@ static void calib_adjust(struct lc15bts_mgr_instance *mgr)
|
|||
return;
|
||||
}
|
||||
|
||||
/* get current time */
|
||||
now = time(NULL);
|
||||
|
||||
/* first time after start of manager program */
|
||||
if (mgr->gps.last_update == 0)
|
||||
mgr->gps.last_update = now;
|
||||
|
||||
/* read last GPS 3D fix from storage */
|
||||
rc = lc15bts_par_get_gps_fix(&last_gps_fix);
|
||||
if (rc < 0) {
|
||||
LOGP(DCALIB, LOGL_NOTICE, "Last GPS 3D fix can not read (%d). Last GPS 3D fix sets to zero\n", rc);
|
||||
last_gps_fix = 0;
|
||||
}
|
||||
|
||||
if (fault) {
|
||||
LOGP(DCALIB, LOGL_NOTICE, "GPS has no fix\n");
|
||||
calib_state_reset(mgr, CALIB_FAIL_GPSFIX);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We got GPS 3D fix */
|
||||
LOGP(DCALIB, LOGL_DEBUG, "Got GPS 3D fix warn_flags=0x%08x, last=%lld, now=%lld\n",
|
||||
mgr->lc15bts_ctrl.warn_flags,
|
||||
(long long)last_gps_fix,
|
||||
(long long)now);
|
||||
|
||||
rc = lc15bts_clock_dac_get(&dac_value);
|
||||
if (rc < 0) {
|
||||
LOGP(DCALIB, LOGL_ERROR,
|
||||
|
@ -113,60 +142,74 @@ static void calib_adjust(struct lc15bts_mgr_instance *mgr)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set OCXO initial dac value */
|
||||
if (ocxodac_saved_value < 0)
|
||||
ocxodac_saved_value = dac_value;
|
||||
|
||||
LOGP(DCALIB, LOGL_NOTICE,
|
||||
"Calibration ERR(%f PPB) ACC(%f PPB) INT(%d) DAC(%d)\n",
|
||||
error_ppt / 1000., accuracy_ppq / 1000000., interval_sec, dac_value);
|
||||
|
||||
/* 1 unit of correction equal about 0.5 - 1 PPB correction */
|
||||
dac_correction = (int)(-error_ppt * 0.00056);
|
||||
new_dac_value = dac_value + dac_correction + 0.5;
|
||||
|
||||
/* We have a fix, make sure the measured error is
|
||||
meaningful (10 times the accuracy) */
|
||||
if ((new_dac_value != dac_value) && ((100l * abs(error_ppt)) > accuracy_ppq)) {
|
||||
|
||||
/* Need integration time to correct */
|
||||
if (interval_sec) {
|
||||
/* 1 unit of correction equal about 0.5 - 1 PPB correction */
|
||||
dac_correction = (int)(-error_ppt * 0.0015);
|
||||
new_dac_value = dac_value + dac_correction;
|
||||
|
||||
if (new_dac_value > 4095)
|
||||
dac_value = 4095;
|
||||
new_dac_value = 4095;
|
||||
else if (new_dac_value < 0)
|
||||
dac_value = 0;
|
||||
else
|
||||
dac_value = new_dac_value;
|
||||
|
||||
LOGP(DCALIB, LOGL_NOTICE,
|
||||
"Going to apply %d as new clock setting.\n",
|
||||
dac_value);
|
||||
|
||||
rc = lc15bts_clock_dac_set(dac_value);
|
||||
if (rc < 0) {
|
||||
LOGP(DCALIB, LOGL_ERROR,
|
||||
"Failed to set OCXO dac value %d\n", rc);
|
||||
calib_state_reset(mgr, CALIB_FAIL_OCXODAC);
|
||||
return;
|
||||
}
|
||||
rc = lc15bts_clock_err_reset();
|
||||
if (rc < 0) {
|
||||
LOGP(DCALIB, LOGL_ERROR,
|
||||
"Failed to set reset clock error module %d\n", rc);
|
||||
calib_state_reset(mgr, CALIB_FAIL_CLKERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
new_dac_value = 0;
|
||||
|
||||
/* Save the correction value in the DAC eeprom if the
|
||||
frequency has been stable for 24 hours */
|
||||
else if (interval_sec >= (24 * 60 * 60)) {
|
||||
rc = lc15bts_clock_dac_save();
|
||||
if (rc < 0) {
|
||||
LOGP(DCALIB, LOGL_ERROR,
|
||||
"Failed to save OCXO dac value %d\n", rc);
|
||||
calib_state_reset(mgr, CALIB_FAIL_OCXODAC);
|
||||
/* We have a fix, make sure the measured error is
|
||||
meaningful (10 times the accuracy) */
|
||||
if ((new_dac_value != dac_value) && ((100l * abs(error_ppt)) > accuracy_ppq)) {
|
||||
|
||||
LOGP(DCALIB, LOGL_NOTICE,
|
||||
"Going to apply %d as new clock setting.\n",
|
||||
new_dac_value);
|
||||
|
||||
rc = lc15bts_clock_dac_set(new_dac_value);
|
||||
if (rc < 0) {
|
||||
LOGP(DCALIB, LOGL_ERROR,
|
||||
"Failed to set OCXO dac value %d\n", rc);
|
||||
calib_state_reset(mgr, CALIB_FAIL_OCXODAC);
|
||||
return;
|
||||
}
|
||||
rc = lc15bts_clock_err_reset();
|
||||
if (rc < 0) {
|
||||
LOGP(DCALIB, LOGL_ERROR,
|
||||
"Failed to reset clock error module %d\n", rc);
|
||||
calib_state_reset(mgr, CALIB_FAIL_CLKERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
rc = lc15bts_clock_err_reset();
|
||||
if (rc < 0) {
|
||||
LOGP(DCALIB, LOGL_ERROR,
|
||||
"Failed to set reste clock error module %d\n", rc);
|
||||
calib_state_reset(mgr, CALIB_FAIL_CLKERR);
|
||||
/* New conditions to store DAC value:
|
||||
* - Resolution accuracy less or equal than 0.01PPB (or 10000 PPQ)
|
||||
* - Error less or equal than 2PPB (or 2000PPT)
|
||||
* - Solution different than the last one */
|
||||
else if (accuracy_ppq <= 10000) {
|
||||
if((dac_value != ocxodac_saved_value) && (abs(error_ppt) < 2000)) {
|
||||
LOGP(DCALIB, LOGL_NOTICE, "Saving OCXO DAC value to memory... val = %d\n", dac_value);
|
||||
rc = lc15bts_clock_dac_save();
|
||||
if (rc < 0) {
|
||||
LOGP(DCALIB, LOGL_ERROR,
|
||||
"Failed to save OCXO dac value %d\n", rc);
|
||||
calib_state_reset(mgr, CALIB_FAIL_OCXODAC);
|
||||
} else {
|
||||
ocxodac_saved_value = dac_value;
|
||||
}
|
||||
}
|
||||
|
||||
rc = lc15bts_clock_err_reset();
|
||||
if (rc < 0) {
|
||||
LOGP(DCALIB, LOGL_ERROR,
|
||||
"Failed to reset clock error module %d\n", rc);
|
||||
calib_state_reset(mgr, CALIB_FAIL_CLKERR);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOGP(DCALIB, LOGL_NOTICE, "Skipping this iteration, no integration time\n");
|
||||
}
|
||||
|
||||
calib_state_reset(mgr, CALIB_SUCCESS);
|
||||
|
@ -197,6 +240,8 @@ static void calib_state_reset(struct lc15bts_mgr_instance *mgr, int outcome)
|
|||
mgr->calib.calib_timeout.data = mgr;
|
||||
mgr->calib.calib_timeout.cb = calib_loop_run;
|
||||
osmo_timer_schedule(&mgr->calib.calib_timeout, timeout, 0);
|
||||
/* TODO: do we want to notify if we got a calibration error, like no gps fix? */
|
||||
lc15bts_swd_event(mgr, SWD_CHECK_CALIB);
|
||||
}
|
||||
|
||||
mgr->calib.state = CALIB_INITIAL;
|
||||
|
@ -241,6 +286,7 @@ int lc15bts_mgr_calib_init(struct lc15bts_mgr_instance *mgr)
|
|||
mgr->calib.calib_timeout.data = mgr;
|
||||
mgr->calib.calib_timeout.cb = calib_loop_run;
|
||||
osmo_timer_schedule(&mgr->calib.calib_timeout, 0, 0);
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "misc/lc15bts_temp.h"
|
||||
#include "misc/lc15bts_power.h"
|
||||
#include "misc/lc15bts_led.h"
|
||||
#include "misc/lc15bts_swd.h"
|
||||
#include "limits.h"
|
||||
|
||||
#include <osmo-bts/logging.h>
|
||||
|
@ -116,7 +117,7 @@ static void handle_normal_actions(int actions)
|
|||
* and used SIGCHLD/waitpid to pick up the dead processes
|
||||
* without invoking shell.
|
||||
*/
|
||||
system("/bin/systemctl start lc15bts.service");
|
||||
system("/bin/systemctl start osmo-bts.service");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +152,7 @@ static void handle_actions(int actions)
|
|||
* and used SIGCHLD/waitpid to pick up the dead processes
|
||||
* without invoking shell.
|
||||
*/
|
||||
system("/bin/systemctl stop lc15bts.service");
|
||||
system("/bin/systemctl stop osmo-bts.service");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,6 +365,7 @@ static void sensor_ctrl_check_cb(void *_data)
|
|||
osmo_timer_schedule(&sensor_ctrl_timer, LC15BTS_SENSOR_TIMER_DURATION, 0);
|
||||
LOGP(DTEMP, LOGL_DEBUG,"Check sensors timer expired\n");
|
||||
/* TODO: do we want to notify if some sensors could not be read? */
|
||||
lc15bts_swd_event(mgr, SWD_CHECK_TEMP_SENSOR);
|
||||
}
|
||||
|
||||
int lc15bts_mgr_sensor_init(struct lc15bts_mgr_instance *mgr)
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
/* Systemd service wd notification for Litecell 1.5 BTS management daemon */
|
||||
|
||||
/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "misc/lc15bts_mgr.h"
|
||||
#include "misc/lc15bts_swd.h"
|
||||
#include <osmocom/core/logging.h>
|
||||
|
||||
/* Needed for service watchdog notification */
|
||||
#include <systemd/sd-daemon.h>
|
||||
|
||||
/* This is the period used to verify if all events have been registered to be allowed
|
||||
to notify the systemd service watchdog
|
||||
*/
|
||||
#define SWD_PERIOD 30
|
||||
|
||||
static void swd_start(struct lc15bts_mgr_instance *mgr);
|
||||
static void swd_process(struct lc15bts_mgr_instance *mgr);
|
||||
static void swd_close(struct lc15bts_mgr_instance *mgr);
|
||||
static void swd_state_reset(struct lc15bts_mgr_instance *mgr, int reason);
|
||||
static int swd_run(struct lc15bts_mgr_instance *mgr, int from_loop);
|
||||
static void swd_loop_run(void *_data);
|
||||
|
||||
enum swd_state {
|
||||
SWD_INITIAL,
|
||||
SWD_IN_PROGRESS,
|
||||
};
|
||||
|
||||
enum swd_result {
|
||||
SWD_FAIL_START,
|
||||
SWD_FAIL_NOTIFY,
|
||||
SWD_SUCCESS,
|
||||
};
|
||||
|
||||
static void swd_start(struct lc15bts_mgr_instance *mgr)
|
||||
{
|
||||
swd_process(mgr);
|
||||
}
|
||||
|
||||
static void swd_process(struct lc15bts_mgr_instance *mgr)
|
||||
{
|
||||
int rc = 0, notify = 0;
|
||||
|
||||
/* Did we get all needed conditions ? */
|
||||
if (mgr->swd.swd_eventmasks == mgr->swd.swd_events) {
|
||||
/* Ping systemd service wd if enabled */
|
||||
rc = sd_notify(0, "WATCHDOG=1");
|
||||
LOGP(DSWD, LOGL_NOTICE, "Watchdog notification attempt\n");
|
||||
notify = 1;
|
||||
}
|
||||
else {
|
||||
LOGP(DSWD, LOGL_NOTICE, "Missing watchdog events: e:0x%016llx,m:0x%016llx\n",mgr->swd.swd_events,mgr->swd.swd_eventmasks);
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
LOGP(DSWD, LOGL_ERROR,
|
||||
"Failed to notify system service watchdog: %d\n", rc);
|
||||
swd_state_reset(mgr, SWD_FAIL_NOTIFY);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* Did we notified the watchdog? */
|
||||
if (notify) {
|
||||
mgr->swd.swd_events = 0;
|
||||
/* Makes sure we really cleared it in case any event was notified at this same moment (it would be lost) */
|
||||
if (mgr->swd.swd_events != 0)
|
||||
mgr->swd.swd_events = 0;
|
||||
}
|
||||
}
|
||||
|
||||
swd_state_reset(mgr, SWD_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
static void swd_close(struct lc15bts_mgr_instance *mgr)
|
||||
{
|
||||
}
|
||||
|
||||
static void swd_state_reset(struct lc15bts_mgr_instance *mgr, int outcome)
|
||||
{
|
||||
if (mgr->swd.swd_from_loop) {
|
||||
mgr->swd.swd_timeout.data = mgr;
|
||||
mgr->swd.swd_timeout.cb = swd_loop_run;
|
||||
osmo_timer_schedule(&mgr->swd.swd_timeout, SWD_PERIOD, 0);
|
||||
}
|
||||
|
||||
mgr->swd.state = SWD_INITIAL;
|
||||
swd_close(mgr);
|
||||
}
|
||||
|
||||
static int swd_run(struct lc15bts_mgr_instance *mgr, int from_loop)
|
||||
{
|
||||
if (mgr->swd.state != SWD_INITIAL) {
|
||||
LOGP(DSWD, LOGL_ERROR, "Swd is already in progress.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mgr->swd.swd_from_loop = from_loop;
|
||||
|
||||
/* From now on everything will be handled from the failure */
|
||||
mgr->swd.state = SWD_IN_PROGRESS;
|
||||
swd_start(mgr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void swd_loop_run(void *_data)
|
||||
{
|
||||
int rc;
|
||||
struct lc15bts_mgr_instance *mgr = _data;
|
||||
|
||||
LOGP(DSWD, LOGL_NOTICE, "Going to check for watchdog notification.\n");
|
||||
rc = swd_run(mgr, 1);
|
||||
if (rc != 0) {
|
||||
swd_state_reset(mgr, SWD_FAIL_START);
|
||||
}
|
||||
}
|
||||
|
||||
/* 'swd_num_events' configures the number of events to be monitored before notifying the
|
||||
systemd service watchdog. It must be in the range of [1,64]. Events are notified
|
||||
through the function 'lc15bts_swd_event'
|
||||
*/
|
||||
int lc15bts_swd_init(struct lc15bts_mgr_instance *mgr, int swd_num_events)
|
||||
{
|
||||
/* Checks for a valid number of events to validate */
|
||||
if (swd_num_events < 1 || swd_num_events > 64)
|
||||
return(-1);
|
||||
|
||||
mgr->swd.state = SWD_INITIAL;
|
||||
mgr->swd.swd_timeout.data = mgr;
|
||||
mgr->swd.swd_timeout.cb = swd_loop_run;
|
||||
osmo_timer_schedule(&mgr->swd.swd_timeout, 0, 0);
|
||||
|
||||
if (swd_num_events == 64){
|
||||
mgr->swd.swd_eventmasks = 0xffffffffffffffffULL;
|
||||
}
|
||||
else {
|
||||
mgr->swd.swd_eventmasks = ((1ULL << swd_num_events) - 1);
|
||||
}
|
||||
mgr->swd.swd_events = 0;
|
||||
mgr->swd.num_events = swd_num_events;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Notifies that the specified event 'swd_event' happened correctly;
|
||||
the value must be in the range of [0,'swd_num_events'[ (see lc15bts_swd_init).
|
||||
For example, if 'swd_num_events' was 64, 'swd_event' events are numbered 0 to 63.
|
||||
WARNING: if this function can be used from multiple threads at the same time,
|
||||
it must be protected with a kind of mutex to avoid loosing event notification.
|
||||
*/
|
||||
int lc15bts_swd_event(struct lc15bts_mgr_instance *mgr, enum mgr_swd_events swd_event)
|
||||
{
|
||||
/* Checks for a valid specified event (smaller than max possible) */
|
||||
if ((int)(swd_event) < 0 || (int)(swd_event) >= mgr->swd.num_events)
|
||||
return(-1);
|
||||
|
||||
mgr->swd.swd_events = mgr->swd.swd_events | ((unsigned long long int)(1) << (int)(swd_event));
|
||||
|
||||
/* !!! Uncomment following line to debug events notification */
|
||||
LOGP(DSWD, LOGL_DEBUG,"Swd event notified: %d\n", (int)(swd_event));
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef _LC15BTS_SWD_H
|
||||
#define _LC15BTS_SWD_H
|
||||
|
||||
int lc15bts_swd_init(struct lc15bts_mgr_instance *mgr, int swd_num_events);
|
||||
int lc15bts_swd_event(struct lc15bts_mgr_instance *mgr, enum mgr_swd_events swd_event);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue