You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

306 lines
8.3 KiB
C

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/******************************************************************************
* file lib/process/pd_cpld.c
* author YuLiang
* version 1.0.0
* date 31-July-2023
* brief This file provides all the CPLD operation functions.
*
******************************************************************************
* Attention
*
* <h2><center>&copy; COPYRIGHT(c) 2023 LandPower</center></h2>
*
* 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 LandPower 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 HOLDER 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.
*
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* 标准C库头文件. */
/* 用户代码头文件. */
#include "cmd.h"
#include "hwgpio.h"
#include "pd_cpld.h"
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#define CPLD_CS_1 gpio_val_set(cpld_cs_idx, 1)
#define CPLD_CS_0 gpio_val_set(cpld_cs_idx, 0)
#define CPLD_SCLK_1 gpio_val_set(cpld_sclk_idx, 1)
#define CPLD_SCLK_0 gpio_val_set(cpld_sclk_idx, 0)
#define CPLD_MOSI_1 gpio_val_set(cpld_mosi_idx, 1)
#define CPLD_MOSI_0 gpio_val_set(cpld_mosi_idx, 0)
#define CPLD_MISO_READ(_val_) gpio_val_get(cpld_miso_idx, _val_)
/* Private typedef -----------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
cpld_version_t cpld_version;
static pthread_mutex_t cpld_mutex; // 多线程同时操作的信号量.
static int32_t cpld_cs_idx;
static int32_t cpld_sclk_idx;
static int32_t cpld_mosi_idx;
static int32_t cpld_miso_idx;
/* Private function prototypes -----------------------------------------------*/
/* 读取 CPLD 寄存器. */
CMD(cpld_reg_read,
cpld_reg_read_cmd,
"cpld read WORD",
"CPLD\n"
"CPLD register read.\n"
"Register address (HH)\n")
{
return CMD_SUCCESS;
uint16_t reg = 0;
uint16_t temp = 0;
char* str = NULL;
reg = strtol(argv[0], &str, 16);
if (*str != '\0')
{
return CMD_ERR_NO_MATCH;
}
cpld_read(reg, 1, &temp);
vty_out(vty, "Read reg 0x%02x value: 0x%04x%s\n", reg, temp, VTY_NEWLINE);
return CMD_SUCCESS;
}
/* 写 CPLD 寄存器. */
CMD(cpld_reg_write,
cpld_reg_write_cmd,
"cpld write WORD WORD",
"CPLD\n"
"CPLD register write\n"
"Register address (HH)\n"
"Value (HHHH)\n")
{
return CMD_SUCCESS;
uint16_t reg = 0;
uint16_t temp = 0;
char* str = NULL;
reg = strtol(argv[0], &str, 16);
if (*str != '\0')
{
return CMD_ERR_NO_MATCH;
}
temp = strtol(argv[1], &str, 16);
if (*str != '\0')
{
return CMD_ERR_NO_MATCH;
}
cpld_write(reg, 1, &temp);
vty_out(vty, "Write reg 0x%02x value: 0x%04x%s", reg, temp, VTY_NEWLINE);
cpld_read(reg, 1, &temp);
vty_out(vty, "Read reg 0x%02x value: 0x%04x%s\n", reg, temp, VTY_NEWLINE);
return CMD_SUCCESS;
}
/* 显示 CPLD 信息. */
CMD(show_cpld,
show_cpld_cmd,
"show cpld",
SHOW_STR
"CPLD\n")
{
return CMD_SUCCESS;
vty_out(vty, "Version: %04x-%02x-%02x%s\n", cpld_version.year, cpld_version.month, cpld_version.day, VTY_NEWLINE);
return CMD_SUCCESS;
}
//SPI可以同时读取和写入数据因此一个函数即可满足要求
int32_t _cpld_half_word_write(uint16_t data)
{
uint8_t i = 0;
for(i = 0; i < 16; i++)
{
if(data & 0x8000)
{
CPLD_MOSI_1;
}
else
{
CPLD_MOSI_0;
}
data <<= 1;
CPLD_SCLK_1;
CPLD_SCLK_0;
}
return E_NONE;
}
//SPI可以同时读取和写入数据因此一个函数即可满足要求
int32_t _cpld_half_word_read(uint16_t *data)
{
uint8_t i = 0;
uint8_t gpio_val = 0;
uint16_t data_rx = 0;
for(i = 0; i < 16; i++)
{
CPLD_SCLK_1;
data_rx <<= 1;
CPLD_MISO_READ(&gpio_val);
if (gpio_val)
{
data_rx |= 0x01;
}
CPLD_SCLK_0;
}
*data = data_rx;
return E_NONE;
}
/* Internal functions --------------------------------------------------------*/
/* Interface functions -------------------------------------------------------*/
/* CPLD 模块初始化代码. */
int32_t cpld_handle_init(void)
{
#if 0
uint16_t temp = 0;
/* 申请信号量, 防止多个线程同时操作 fifo. */
if (pthread_mutex_init(&cpld_mutex, NULL) != 0)
{
DBG(DBG_M_FIFO_ERR, "ERROR at mutex init return %s!\r\n", safe_strerror(errno));
return E_SYS_CALL;
}
/* 申请 GPIO. */
cpld_cs_idx = gpio_export(GPIO_CPLD_CS);
if (cpld_cs_idx < 0)
{
DBG(DBG_M_PD_CPLD, "ERROR return %d!\r\n", cpld_cs_idx);
return E_BAD_PARAM;
}
LD_E_RETURN(DBG_M_PD_CPLD, gpio_dir_set(cpld_cs_idx, GPIO_DIR_OUT));
cpld_sclk_idx = gpio_export(GPIO_CPLD_SCLK);
if (cpld_sclk_idx < 0)
{
DBG(DBG_M_PD_CPLD, "ERROR return %d!\r\n", cpld_sclk_idx);
return E_BAD_PARAM;
}
LD_E_RETURN(DBG_M_PD_CPLD, gpio_dir_set(cpld_sclk_idx, GPIO_DIR_OUT));
cpld_mosi_idx = gpio_export(GPIO_CPLD_MOSI);
if (cpld_mosi_idx < 0)
{
DBG(DBG_M_PD_CPLD, "ERROR return %d!\r\n", cpld_mosi_idx);
return E_BAD_PARAM;
}
LD_E_RETURN(DBG_M_PD_CPLD, gpio_dir_set(cpld_mosi_idx, GPIO_DIR_OUT));
cpld_miso_idx = gpio_export(GPIO_CPLD_MISO);
if (cpld_miso_idx < 0)
{
DBG(DBG_M_PD_CPLD, "ERROR return %d!\r\n", cpld_miso_idx);
return E_BAD_PARAM;
}
LD_E_RETURN(DBG_M_PD_CPLD, gpio_dir_set(cpld_miso_idx, GPIO_DIR_IN));
CPLD_CS_1;
CPLD_SCLK_0;
/* 获取版本号. */
cpld_read(CPLD_REG_V0, 1, &temp);
cpld_version.year = temp;
cpld_read(CPLD_REG_V1, 1, &temp);
cpld_version.month = temp >> 8;
cpld_version.day = temp & 0x00ff;
#endif
/* 注册命令. */
cmd_install_element(COMMON_NODE, &show_cpld_cmd);
cmd_install_element(ENABLE_NODE, &cpld_reg_read_cmd);
cmd_install_element(ENABLE_NODE, &cpld_reg_write_cmd);
return E_NONE;
}
int32_t cpld_read(uint16_t addr, uint16_t len, uint16_t *data)
{
int32_t i = 0;
pthread_mutex_lock(&cpld_mutex);
CPLD_CS_0;
_cpld_half_word_write(0x8000 | addr);
for(i = 0; i < len; i++)
{
_cpld_half_word_read(data + i);
}
CPLD_CS_1;
pthread_mutex_unlock(&cpld_mutex);
return E_NONE;
}
int32_t cpld_write(uint16_t addr, uint16_t len, uint16_t *data)
{
int32_t i = 0;
pthread_mutex_lock(&cpld_mutex);
CPLD_CS_0;
_cpld_half_word_write(0x7fff & addr);
for(i = 0; i < len; i++)
{
_cpld_half_word_write(data[i]);
}
CPLD_CS_1;
pthread_mutex_unlock(&cpld_mutex);
return E_NONE;
}
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/