522 lines
14 KiB
C
Executable File
522 lines
14 KiB
C
Executable File
/*
|
|
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. 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 XRADIO TECHNOLOGY CO., LTD. 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
|
|
* OWNER 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.
|
|
*/
|
|
|
|
#include "cmd_util.h"
|
|
#include "cmd_i2c.h"
|
|
#include "driver/chip/hal_gpio.h"
|
|
#include "driver/chip/hal_i2c.h"
|
|
|
|
|
|
#define DRV_TEST_I2C_NORM 0
|
|
#define DRV_TEST_I2C_MEM 1
|
|
#define DRV_TEST_I2C_SCCB 0
|
|
|
|
#define DRV_TEST_I2C_ADDR_10BIT 0
|
|
|
|
static enum cmd_status cmd_i2c_init_exec(char *cmd)
|
|
{
|
|
int cnt;
|
|
uint32_t id, addr_mode, clock_freq;
|
|
I2C_InitParam i2c_param;
|
|
HAL_Status hal_status;
|
|
|
|
cnt = cmd_sscanf(cmd, "i=%u a=%u c=%u", &id, &addr_mode, &clock_freq);
|
|
if (cnt != 3) {
|
|
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (id >= I2C_NUM) {
|
|
CMD_ERR("invalid id %u\n", id);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
#if DRV_TEST_I2C_ADDR_10BIT
|
|
if ((addr_mode != 7) && (addr_mode != 10)) {
|
|
#else /* DRV_TEST_I2C_ADDR_10BIT */
|
|
if (addr_mode != 7) {
|
|
#endif /* DRV_TEST_I2C_ADDR_10BIT */
|
|
CMD_ERR("invalid addr mode %u\n", addr_mode);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if ((clock_freq < 100000) || (clock_freq > 400000)) {
|
|
CMD_ERR("invalid clock freq %u\n", clock_freq);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
#if DRV_TEST_I2C_ADDR_10BIT
|
|
if (addr_mode == 10)
|
|
i2c_param.addrMode = I2C_ADDR_MODE_10BIT;
|
|
else
|
|
#endif /* DRV_TEST_I2C_ADDR_10BIT */
|
|
i2c_param.addrMode = I2C_ADDR_MODE_7BIT;
|
|
i2c_param.clockFreq = clock_freq;
|
|
|
|
hal_status = HAL_I2C_Init((I2C_ID)id, &i2c_param);
|
|
if (hal_status == HAL_OK) {
|
|
return CMD_STATUS_OK;
|
|
} else {
|
|
CMD_ERR("HAL_I2C_Init return: hal_status = %d\n", hal_status);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
}
|
|
|
|
static enum cmd_status cmd_i2c_deinit_exec(char *cmd)
|
|
{
|
|
int cnt;
|
|
uint32_t id;
|
|
HAL_Status hal_status;
|
|
|
|
cnt = cmd_sscanf(cmd, "i=%u", &id);
|
|
if (cnt != 1) {
|
|
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (id >= I2C_NUM) {
|
|
CMD_ERR("invalid id %u\n", id);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
hal_status = HAL_I2C_DeInit((I2C_ID)id);
|
|
if (hal_status == HAL_OK) {
|
|
return CMD_STATUS_OK;
|
|
} else {
|
|
CMD_ERR("HAL_I2C_DeInit return: hal_status = %d\n", hal_status);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
}
|
|
|
|
#if DRV_TEST_I2C_NORM
|
|
static enum cmd_status cmd_i2c_transmit_norm_exec(char *cmd)
|
|
{
|
|
int cnt;
|
|
uint32_t id, dev_addr, len;
|
|
uint8_t *buf;
|
|
int32_t size;
|
|
|
|
cnt = cmd_sscanf(cmd, "i=%u d=%u l=%u", &id, &dev_addr, &len);
|
|
if (cnt != 3) {
|
|
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (id >= I2C_NUM) {
|
|
CMD_ERR("invalid id %u\n", id);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
#if DRV_TEST_I2C_ADDR_10BIT
|
|
if ((dev_addr >> 10) != 0) {
|
|
#else /* DRV_TEST_I2C_ADDR_10BIT */
|
|
if ((dev_addr >> 7) != 0) {
|
|
#endif /* DRV_TEST_I2C_ADDR_10BIT */
|
|
CMD_ERR("invalid dev_addr %u\n", dev_addr);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if ((len >> 31) != 0) {
|
|
CMD_ERR("invalid len %u\n", len);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
buf = (uint8_t *)cmd_malloc(len * sizeof(uint8_t));
|
|
if (buf == NULL) {
|
|
CMD_ERR("cmd_malloc return NULL.\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
cmd_write_respond(CMD_STATUS_OK, "OK");
|
|
|
|
cmd_raw_mode_enable();
|
|
size = cmd_raw_mode_read(buf, (int32_t)len, 10000);
|
|
if (size != (int32_t)len) {
|
|
CMD_ERR("len = %u, but raw mode read size = %d\n", len, size);
|
|
cmd_free(buf);
|
|
cmd_raw_mode_write((uint8_t *)"FAIL", 4);
|
|
cmd_raw_mode_disable();
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
|
|
size = HAL_I2C_Master_Transmit_IT((I2C_ID)id, (uint16_t)dev_addr, buf, (int32_t)len);
|
|
if (size != (int32_t)len) {
|
|
CMD_ERR("len = %u, but I2C transmit size = %d\n", len, size);
|
|
cmd_free(buf);
|
|
cmd_raw_mode_write((uint8_t *)"FAIL", 4);
|
|
cmd_raw_mode_disable();
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
|
|
cmd_free(buf);
|
|
cmd_raw_mode_write((uint8_t *)"OK", 2);
|
|
cmd_raw_mode_disable();
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
|
|
static enum cmd_status cmd_i2c_receive_norm_exec(char *cmd)
|
|
{
|
|
int cnt;
|
|
uint32_t id, dev_addr, len;
|
|
uint8_t *buf;
|
|
int32_t size;
|
|
|
|
cnt = cmd_sscanf(cmd, "i=%u d=%u l=%u", &id, &dev_addr, &len);
|
|
if (cnt != 3) {
|
|
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (id >= I2C_NUM) {
|
|
CMD_ERR("invalid id %u\n", id);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
#if DRV_TEST_I2C_ADDR_10BIT
|
|
if ((dev_addr >> 10) != 0) {
|
|
#else /* DRV_TEST_I2C_ADDR_10BIT */
|
|
if ((dev_addr >> 7) != 0) {
|
|
#endif /* DRV_TEST_I2C_ADDR_10BIT */
|
|
CMD_ERR("invalid dev_addr %u\n", dev_addr);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if ((len >> 31) != 0) {
|
|
CMD_ERR("invalid len %u\n", len);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
buf = (uint8_t *)cmd_malloc(len * sizeof(uint8_t));
|
|
if (buf == NULL) {
|
|
CMD_ERR("cmd_malloc return NULL.\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
cmd_memset(buf, 0, len);
|
|
|
|
size = HAL_I2C_Master_Receive_IT((I2C_ID)id, (uint16_t)dev_addr, buf,
|
|
(int32_t)len);
|
|
if (size != (int32_t)len) {
|
|
CMD_ERR("len = %u, but I2C receive size = %d\n", len, size);
|
|
cmd_free(buf);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
cmd_write_respond(CMD_STATUS_OK, "OK");
|
|
|
|
cmd_msleep(1000);
|
|
|
|
cmd_raw_mode_enable();
|
|
size = cmd_raw_mode_write(buf, (int32_t)len);
|
|
if (size != (int32_t)len) {
|
|
CMD_ERR("len = %u, but raw mode write size = %d\n", len, size);
|
|
}
|
|
|
|
cmd_free(buf);
|
|
cmd_raw_mode_disable();
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
#endif /* DRV_TEST_I2C_NORM */
|
|
|
|
#if DRV_TEST_I2C_MEM
|
|
static enum cmd_status cmd_i2c_transmit_mem_exec(char *cmd)
|
|
{
|
|
int cnt;
|
|
uint32_t id, dev_addr, mem_addr, mem_add_size, len;
|
|
uint8_t *buf;
|
|
int32_t size;
|
|
|
|
cnt = cmd_sscanf(cmd, "i=%u d=%u m=%u s=%u l=%u", &id, &dev_addr,
|
|
&mem_addr, &mem_add_size, &len);
|
|
if (cnt != 5) {
|
|
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (id >= I2C_NUM) {
|
|
CMD_ERR("invalid id %u\n", id);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if ((mem_add_size == 3) || (mem_add_size <= I2C_MEMADDR_SIZE_INVALID)
|
|
|| (mem_add_size > I2C_MEMADDR_SIZE_32BIT)) {
|
|
CMD_ERR("invalid mem_size %u\n", mem_add_size);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (len > 16) {
|
|
CMD_ERR("invalid len %u\n", len);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
buf = (uint8_t *)cmd_malloc(len * sizeof(uint8_t));
|
|
if (buf == NULL) {
|
|
CMD_ERR("cmd_malloc return NULL.\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
cmd_write_respond(CMD_STATUS_OK, "OK");
|
|
|
|
cmd_raw_mode_enable();
|
|
size = cmd_raw_mode_read(buf, (int32_t)len, 10000);
|
|
if (size != (int32_t)len) {
|
|
CMD_ERR("len = %u, but raw mode read size = %d\n", len, size);
|
|
cmd_free(buf);
|
|
cmd_raw_mode_write((uint8_t *)"FAIL", 4);
|
|
cmd_raw_mode_disable();
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
|
|
size = HAL_I2C_Master_Transmit_Mem_IT((I2C_ID)id, (uint16_t)dev_addr,
|
|
mem_addr, (I2C_MemAddrSize)mem_add_size, buf, (int32_t)len);
|
|
if (size != (int32_t)len) {
|
|
CMD_ERR("len = %u, but I2C transmit size = %d\n", len, size);
|
|
cmd_free(buf);
|
|
cmd_raw_mode_write((uint8_t *)"FAIL", 4);
|
|
cmd_raw_mode_disable();
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
|
|
cmd_free(buf);
|
|
cmd_raw_mode_write((uint8_t *)"OK", 2);
|
|
cmd_raw_mode_disable();
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
|
|
static enum cmd_status cmd_i2c_receive_mem_exec(char *cmd)
|
|
{
|
|
int cnt, i;
|
|
uint32_t id, dev_addr, mem_addr, mem_add_size, len;
|
|
uint8_t *buf;
|
|
int32_t size;
|
|
|
|
cnt = cmd_sscanf(cmd, "i=%u d=%u m=%u s=%u l=%u", &id, &dev_addr,
|
|
&mem_addr, &mem_add_size, &len);
|
|
if (cnt != 5) {
|
|
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (id >= I2C_NUM) {
|
|
CMD_ERR("invalid id %u\n", id);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if ((mem_add_size == 3) || (mem_add_size <= I2C_MEMADDR_SIZE_INVALID)
|
|
|| (mem_add_size > I2C_MEMADDR_SIZE_32BIT)) {
|
|
CMD_ERR("invalid mem_size %u\n", mem_add_size);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (len > 2048) {
|
|
CMD_ERR("invalid len %u\n", len);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
buf = (uint8_t *)cmd_malloc(len * sizeof(uint8_t));
|
|
if (buf == NULL) {
|
|
CMD_ERR("cmd_malloc return NULL.\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
cmd_memset(buf, 0, len);
|
|
|
|
size = HAL_I2C_Master_Receive_Mem_IT((I2C_ID)id, (uint16_t)dev_addr,
|
|
mem_addr, (I2C_MemAddrSize)mem_add_size, buf, (int32_t)len);
|
|
if (size != (int32_t)len) {
|
|
CMD_ERR("len = %u, but I2C receive size = %d\n", len, size);
|
|
cmd_free(buf);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
cmd_write_respond(CMD_STATUS_OK, "OK");
|
|
|
|
cmd_raw_mode_enable();
|
|
size = cmd_raw_mode_write(buf, (int32_t)len);
|
|
if (size != (int32_t)len) {
|
|
CMD_ERR("len = %u, but raw mode write size = %d\n", len, size);
|
|
}
|
|
|
|
printf("\nread_buf:\n");
|
|
for (i = 0; i < len; i++) {
|
|
printf("0x%02x ", buf[i]);
|
|
}
|
|
printf("\n");
|
|
|
|
cmd_free(buf);
|
|
cmd_raw_mode_disable();
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
#endif /* DRV_TEST_I2C_MEM */
|
|
|
|
#if DRV_TEST_I2C_SCCB
|
|
static enum cmd_status cmd_i2c_transmit_sccb_exec(char *cmd)
|
|
{
|
|
int cnt;
|
|
uint32_t id, dev_addr, sub_addr;
|
|
uint8_t *buf;
|
|
int32_t size;
|
|
|
|
cnt = cmd_sscanf(cmd, "i=%u d=%u s=%u", &id, &dev_addr, &sub_addr);
|
|
if (cnt != 3) {
|
|
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (id >= I2C_NUM) {
|
|
CMD_ERR("invalid id %u\n", id);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if ((dev_addr >> 8) != 0) {
|
|
CMD_ERR("invalid dev_addr %u\n", dev_addr);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if ((sub_addr >> 8) != 0) {
|
|
CMD_ERR("invalid sub_addr %u\n", sub_addr);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
buf = (uint8_t *)cmd_malloc(sizeof(uint8_t));
|
|
if (buf == NULL) {
|
|
CMD_ERR("cmd_malloc return NULL.\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
cmd_write_respond(CMD_STATUS_OK, "OK");
|
|
|
|
cmd_raw_mode_enable();
|
|
size = cmd_raw_mode_read(buf, 1, 10000);
|
|
if (size != 1) {
|
|
CMD_ERR("len = 1, but raw mode read size = %d\n", size);
|
|
cmd_free(buf);
|
|
cmd_raw_mode_write((uint8_t *)"FAIL", 4);
|
|
cmd_raw_mode_disable();
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
|
|
size = HAL_I2C_SCCB_Master_Transmit_IT((I2C_ID)id, (uint8_t)dev_addr,
|
|
(uint8_t)sub_addr, buf);
|
|
if (size != 1) {
|
|
CMD_ERR("len = 1, but I2C transmit size = %d\n", size);
|
|
cmd_free(buf);
|
|
cmd_raw_mode_write((uint8_t *)"FAIL", 4);
|
|
cmd_raw_mode_disable();
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
|
|
cmd_free(buf);
|
|
cmd_raw_mode_write((uint8_t *)"OK", 2);
|
|
cmd_raw_mode_disable();
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
|
|
static enum cmd_status cmd_i2c_receive_sccb_exec(char *cmd)
|
|
{
|
|
int cnt;
|
|
uint32_t id, dev_addr, sub_addr;
|
|
uint8_t *buf;
|
|
int32_t size;
|
|
|
|
cnt = cmd_sscanf(cmd, "i=%u d=%u s=%u", &id, &dev_addr, &sub_addr);
|
|
if (cnt != 3) {
|
|
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (id >= I2C_NUM) {
|
|
CMD_ERR("invalid id %u\n", id);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if ((dev_addr >> 8) != 0) {
|
|
CMD_ERR("invalid dev_addr %u\n", dev_addr);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if ((sub_addr >> 8) != 0) {
|
|
CMD_ERR("invalid sub_addr %u\n", sub_addr);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
buf = (uint8_t *)cmd_malloc(sizeof(uint8_t));
|
|
if (buf == NULL) {
|
|
CMD_ERR("cmd_malloc return NULL.\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
cmd_memset(buf, 0, 1);
|
|
|
|
size = HAL_I2C_SCCB_Master_Receive_IT((I2C_ID)id, (uint8_t)dev_addr,
|
|
(uint8_t)sub_addr, buf);
|
|
if (size != 1) {
|
|
CMD_ERR("len = 1, but I2C receive size = %d\n", size);
|
|
cmd_free(buf);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
cmd_write_respond(CMD_STATUS_OK, "OK");
|
|
|
|
cmd_msleep(1000);
|
|
|
|
cmd_raw_mode_enable();
|
|
size = cmd_raw_mode_write(buf, 1);
|
|
if (size != 1) {
|
|
CMD_ERR("len = 1, but raw mode write size = %d\n", size);
|
|
}
|
|
|
|
cmd_free(buf);
|
|
cmd_raw_mode_disable();
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
#endif /* DRV_TEST_I2C_SCCB */
|
|
|
|
static const struct cmd_data g_i2c_cmds[] = {
|
|
{ "init", cmd_i2c_init_exec },
|
|
{ "deinit", cmd_i2c_deinit_exec },
|
|
|
|
#if DRV_TEST_I2C_NORM
|
|
{ "transmit-norm", cmd_i2c_transmit_norm_exec },
|
|
{ "receive-norm", cmd_i2c_receive_norm_exec },
|
|
#endif /* DRV_TEST_I2C_NORM */
|
|
|
|
#if DRV_TEST_I2C_MEM
|
|
{ "transmit-mem", cmd_i2c_transmit_mem_exec },
|
|
{ "receive-mem", cmd_i2c_receive_mem_exec },
|
|
#endif /* DRV_TEST_I2C_MEM */
|
|
|
|
#if DRV_TEST_I2C_SCCB
|
|
{ "transmit-sccb", cmd_i2c_transmit_sccb_exec },
|
|
{ "receive-sccb", cmd_i2c_receive_sccb_exec },
|
|
#endif /* DRV_TEST_I2C_SCCB */
|
|
};
|
|
|
|
enum cmd_status cmd_i2c_exec(char *cmd)
|
|
{
|
|
return cmd_exec(cmd, g_i2c_cmds, cmd_nitems(g_i2c_cmds));
|
|
}
|