Post Go back to editing

Fail to use the function max31343_reg_read_time_stamp()

Category: Hardware
Product Number: AD-PQMON-SL

Hardware: AD-PQMON-SL

 

Goal:

Display RTC clock time (with battery) in iio_pqm.c

max31343_reg_read_time_stamp(max31343_dev, &ts)

 

case CURRENT_TIME_READABLE:

                return snprintf(buf, len, "%04d-%02d-%02d %02d:%02d:%02d",

                                                ts.year, ts.mon + 1, ts.day,

                                                ts.hr, ts.min, ts.sec);

 

Problem Description:

After adding max31343 initialisation, set the timestamp and cleanup code in basic_example.c, a hex file can be built, but fails to be detected by iio_info

 

Microsoft Windows [Version 10.0.19045.6466]

(c) Microsoft Corporation. All rights reserved.

 

C:\Users\YongYH>cd C:\Users\YongYH\Private\Tools\libiio\Windows-VS-2022-x64 & iio_info -u serial:COM4,115200,8n1

Unable to create IIO context serial:COM4,115200,8n1: No such file or directory (2)

 

Troubleshooting steps that I have taken:

  1. If max31343 related codes are removed from basic_example.c, iio_info can run without abnormal
  2. Using latest version of max31343.c and max31343.h
  3. Tried to refine my code in basic_example.c by using AI, but the error persisted.

/*******************************************************************************
 *   @file   basic_example.c
 *   @brief  PQM firmware, called by main
 *   @author Robert Budai (robert.budai@analog.com)
 ********************************************************************************
 * Copyright (c) 2024 Analog Devices, Inc.
 *
 * 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 Analog Devices, 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 ANALOG DEVICES, INC. “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 ANALOG DEVICES, INC. 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.
 *******************************************************************************/

#ifdef BASIC_EXAMPLE
#include "basic_example.h"
#endif

 /* ============ ADD THESE INCLUDES AT THE TOP ============ */
#include "max31343.h"
#include "common_data.h"
/* ============ END NEW INCLUDES ============ */

int32_t pqm_init(struct pqm_desc **desc, struct pqm_init_para *param)
{
	struct pqm_desc *d;
	d = (struct pqm_desc *)no_os_calloc(1, sizeof(*d));

	if (!d)
		return -ENOMEM;

	d->ext_buff = param->ext_buff;
	d->ext_buff_len = param->ext_buff_len;
	for (int i = 0; i < TOTAL_PQM_CHANNELS; i++) {
		for (int j = 0; j < MAX_CH_ATTRS; j++) {
			d->pqm_ch_attr[i][j] = 0;
		}
	}
	for (int i = 0; i < PQM_DEVICE_ATTR_NUMBER; i++) {
		d->pqm_global_attr[i] = param->dev_global_attr[i];
	}
	*desc = d;

	return 0;
}

int32_t pqm_remove(struct pqm_desc *desc)
{
	if (!desc)
		return -EINVAL;
	no_os_free(desc);

	return 0;
}

int32_t update_pqm_channels(void *dev, uint32_t mask)
{
	struct pqm_desc *desc;

	if (!dev)
		return -ENODEV;

	desc = dev;
	desc->active_ch = mask;

	return 0;
}

int32_t close_pqm_channels(void *dev)
{
	struct pqm_desc *desc;

	if (!dev)
		return -ENODEV;

	desc = dev;
	desc->active_ch = 0;

	return 0;
}

#if defined(PQM_CONN_SERIAL)
int32_t enable_RS482_driver()
{
	// Enable driver and receiver of ADM2587, used only by serial connection
	int status;
	struct no_os_gpio_sec *enable_ADM2587;
	struct nhd_c12832a1z_dev *nhd_c12832a1z_device;

	struct max_gpio_init_param gpio_extra_ip_ADM2587 = {
		.vssel = MXC_GPIO_VSSEL_VDDIOH,
	};

	struct no_os_gpio_init_param gpio_ADM2587_ip = {
		.port = 2,
		.number = 15,
		.pull = NO_OS_PULL_NONE,
		.platform_ops = &max_gpio_ops,
		.extra = &gpio_extra_ip_ADM2587,
	};

	status = no_os_gpio_get(&enable_ADM2587, &gpio_ADM2587_ip);
	if (status)
		return status;
	status = no_os_gpio_set_value(enable_ADM2587, 1);
	return status;
}
#endif

int basic_pqm_firmware()
{

	struct no_os_uart_desc *uart_desc;
	struct pqm_desc *pqm_desc;
	struct iio_app_desc *app;
	struct iio_app_init_param app_init_param = {0};
	struct iio_data_buffer buff = {
		.buff = (void *)iio_data_buffer_loc,
		.size = MAX_SIZE_BASE_ADDR_WITH_SIZE,
	};
	pqlibExample.no_os_cb_desc = NULL;

	memset(iio_data_buffer_loc, 0, MAX_SIZE_BASE_ADDR_WITH_SIZE);

	int status = SYS_STATUS_SUCCESS;

	/* ============ ADD THESE VARIABLE DECLARATIONS ============ */
	struct max31343_dev* max31343_dev = NULL;
	struct max31343_time_stamp ts;
	struct max31343_init_param max31343_init_params;
	/* ============ END NEW VARIABLE DECLARATIONS ============ */

	status = init_lcd();
	if (status)
		goto exit;

	status = no_os_uart_init(&uart_desc, &uart_ip_stdio);
	if (status)
		goto exit;

	no_os_uart_stdio(uart_desc);

#if defined(PQM_CONN_SERIAL)
	status = enable_RS482_driver();
	if (status)
		goto exit;
#endif

	/* ============ INSERT MAX31343 INITIALIZATION HERE ============ */
/* Setup MAX31343 RTC initialization parameters */
	max31343_init_params.i2c_init = &i2c_ip;
	max31343_init_params.battery_en = 1;

	/* Initialize MAX31343 device */
	status = max31343_init(&max31343_dev, max31343_init_params);
	if (status) {
		printf("MAX31343 initialization failed, status: %d\n\r", status);
		goto exit;
	}
	printf("MAX31343 initialized successfully\n\r");

	/* Set the time stamp */
	ts.sec = 0;
	ts.min = 0;
	ts.hr = 12;
	ts.day = 25;
	ts.mon = 2;      /* Month: 0-11 (2 = March) */
	ts.year = 2026;

	status = max31343_set_time_stamp(max31343_dev, ts);
	if (status) {
		printf("Failed to set time stamp, status: %d\n\r", status);
		goto exit;
	}
	printf("Time stamp set successfully: %02d:%02d:%02d %02d-%02d-%04d\n\r",
		ts.hr, ts.min, ts.sec, ts.day, ts.mon + 1, ts.year);

	/* ============ END MAX31343 INITIALIZATION ============ */

#if defined(PQM_CONN_T1L)
	uint8_t adin1110_mac_address[6] = {0x00, 0x18, 0x80, 0x03, 0x25, 0x60};
	struct no_os_gpio_desc *adin1110_swpd_gpio;
	struct no_os_gpio_desc *adin1110_tx2p4_gpio;
	struct no_os_gpio_desc *adin1110_mssel_gpio;
	struct no_os_gpio_desc *adin1110_cfg0_gpio;
	struct no_os_gpio_desc *adin1110_cfg1_gpio;
	struct no_os_gpio_desc *adin1110_int_gpio;
	int ret;

	no_os_gpio_get(&adin1110_cfg0_gpio, &adin1110_cfg0_ip);
	no_os_gpio_get(&adin1110_swpd_gpio, &adin1110_swpd_ip);
	no_os_gpio_get(&adin1110_tx2p4_gpio, &adin1110_tx2p4_ip);
	no_os_gpio_get(&adin1110_mssel_gpio, &adin1110_mssel_ip);
	no_os_gpio_get(&adin1110_cfg1_gpio, &adin1110_cfg1_ip);
	no_os_gpio_get(&adin1110_int_gpio, &adin1110_int_ip);
	no_os_gpio_direction_output(adin1110_swpd_gpio, 1);
	no_os_gpio_direction_output(adin1110_tx2p4_gpio, 0);
	no_os_gpio_direction_output(adin1110_mssel_gpio, 1);
	no_os_gpio_direction_output(adin1110_cfg1_gpio, 1);
	no_os_gpio_direction_output(adin1110_cfg0_gpio, 1);
	no_os_gpio_direction_input(adin1110_int_gpio);

	memcpy(adin1110_ip.mac_address, adin1110_mac_address, NETIF_MAX_HWADDR_LEN);
	memcpy(app_init_param.lwip_param.hwaddr, adin1110_mac_address,
	       NETIF_MAX_HWADDR_LEN);
#endif

	status = afe_init();
	if (status != SYS_STATUS_SUCCESS) {
		printf("AFE Init failed \n\r");
		goto exit;
	}

	status = pqm_measurement_init();
	if (status != SYS_STATUS_SUCCESS) {
		printf("Pqm Measurement Init failed \n\r");
		goto exit;
	}

	status = pqm_init(&pqm_desc, &pqm_ip);
	if (status) {
		printf("PQM initialization failed \n\r");
		goto exit;
	}

	status = pqm_start_measurement(false);
	if (status != SYS_STATUS_SUCCESS) {
		printf("PQM could not start measurements, status: %d \n\r", status);
		goto exit;
	}
	printf("Mesurements started \n\r");

	struct iio_app_device devices[] = {
		IIO_APP_DEVICE("pqm", pqm_desc, &pqm_iio_descriptor, &buff, NULL, NULL)
	};

	app_init_param.devices = devices;
	app_init_param.nb_devices = NO_OS_ARRAY_SIZE(devices);

#if defined(PQM_CONN_USB)
	app_init_param.uart_init_params = iio_demo_usb_ip;
#elif defined(PQM_CONN_SERIAL)
	app_init_param.uart_init_params = iio_demo_serial_ip;
#elif defined(PQM_CONN_T1L)
	app_init_param.uart_init_params = iio_demo_serial_ip;
	app_init_param.lwip_param.platform_ops = &adin1110_lwip_ops;
	app_init_param.lwip_param.mac_param = &adin1110_ip;
	app_init_param.lwip_param.extra = NULL;
#endif

	app_init_param.post_step_callback = &(pqm_one_cycle);
	status = iio_app_init(&app, app_init_param);

	if (status)
		goto exit;

	status = iio_app_run(app);

	iio_app_remove(app);

exit:

	/* ============ ADD MAX31343 CLEANUP IN THE EXIT SECTION ============ */
	if (max31343_dev) {
		int ret_cleanup = max31343_remove(max31343_dev);
		if (ret_cleanup) {
			printf("MAX31343 removal failed, status: %d\n\r", ret_cleanup);
		}
	}
	/* ============ END MAX31343 CLEANUP ============ */

	pqm_remove(pqm_desc);
	no_os_uart_remove(uart_desc);
	return status;
}

Parents
  • Hi @Retz,

    1. When I said the debug output, I was referring on what do you see on the COM port associated with the daplink since that one is used for the uart_stdio. Can you look on that port with 115200 baudrate 8N1?

      2. What is inside the script build_hex.sh? Can I see it since on my side it works?

      Sure, this build_hex.sh is the combination step of build hex file + drag and drop + iio_info test, I wrote it by using AI to reduce manual work. Feel free to edit

      #!/bin/bash


      # === USER CONFIG ===


      export MAXIM_LIBRARIES="C:/MaximSDK/Libraries"


      PROJECT_DIR="/c/Users/YongYH/no-OS/projects/eval-pqmon"


      PQLIB_PATH="C:/Users/YongYH/no-OS/projects/eval-pqmon/pqlib_dir"


      PLATFORM="maxim"


      TARGET="max32650"


      INTERFACE="usb"


      HEX_NAME="eval-pqmon.hex"


      HEX_PATH="$PROJECT_DIR/build/$HEX_NAME"


      IIO_CMD="/c/Users/YongYH/Private/Tools/libiio/Windows-VS-2022-x64/iio_info.exe"

      IIO_ARGS="-u serial:COM4,115200,8n1"


      # === Step 1: Go to project directory ===


      cd "$PROJECT_DIR" || exit 1


      echo "[INFO] Cleaning previous build..."


      make PLATFORM=$PLATFORM TARGET=$TARGET reset PQLIB_PATH=$PQLIB_PATH


      echo "[INFO] Building new HEX..."


      make PLATFORM=$PLATFORM TARGET=$TARGET INTERFACE=$INTERFACE PQLIB_PATH=$PQLIB_PATH run


      # === Step 2: Wait for .hex file ===


      if [ ! -f "$HEX_PATH" ]; then

      echo "[ERROR] HEX file not found: $HEX_PATH"

      exit 1

      fi


      echo "[INFO] Found hex file: $HEX_PATH"


      # === Step 3: Detect and copy to DAPLINK ===


      echo "[INFO] Detecting DAPLINK drive..."


      found=0


      for i in {1..10}; do

      DAP_DRIVE=$(powershell.exe -Command "Get-WMIObject Win32_Volume | Where-Object { \$_.Label -eq 'DAPLINK' } | Select-Object -ExpandProperty DriveLetter" | tr -d '\r')

      if [ -n "$DAP_DRIVE" ]; then

      echo "[INFO] DAPLINK drive found at $DAP_DRIVE"


      win_hex_path=$(echo "$HEX_PATH" | sed 's|/|\\|g')


      powershell.exe -Command "Copy-Item -Path \"$win_hex_path\" -Destination \"$DAP_DRIVE\\$HEX_NAME\""


      echo "[SUCCESS] HEX file copied to DAPLINK ($DAP_DRIVE)"

      found=1

      break

      else

      echo "[WAIT] DAPLINK not ready yet... retrying ($i/10)"

      sleep 1

      fi

      done


      if [ $found -eq 0 ]; then

      echo "[ERROR] DAPLINK not found after 10 seconds. Please check USB connection."

      exit 1

      fi


      # === Step 4: Wait briefly and run iio_info ===


      echo "[INFO] Waiting for device to boot..."

      sleep 3 # Give time for MCU to restart


      echo "[INFO] Running iio_info on COM4..."

      "$IIO_CMD" $IIO_ARGS

      3. Most important, do you have any printf() added inside the max31343_init()?

      Yes, in the basic_example.c. You may refer the basic_example.c in the question

      	/* Initialize MAX31343 device */
      	status = max31343_init(&max31343_dev, max31343_init_params);
      	if (status) {
      		printf("MAX31343 initialization failed, status: %d\n\r", status);
      		goto exit;
      	}
      	printf("MAX31343 initialized successfully\n\r");

      5. The working hex shows up as COM4 (USB Serial Port) in Device Manager. My script was using INTERFACE="usb", which seems to be causing the MAX31343 initialization failure.

    •  Hi,  Your program gets stuck just after the max31343_init() call with a status error -9. It doesn't even reach the part where the USB and IIO are configured. You can comment out the two "goto exit" jumps after the max31343 and even if the rtc will still not work and you will have error codes you should be able to see the iio working. So, the problem is with the max31343_init or the max31343 descriptors. Do you have the project on a public branch? If not, you can look at this part of code where the max31343_init function is located or even run the program in debug mode.

    • Hi  

      1. Do you have the project on a public branch?

    Reply Children
    No Data

    Before You Switch


    Switching languages will make ADI Explorer unavailable. Resume your session by switching back to English and reopening ADI Explorer.