目录
GPIO Pin Mux
SPI的调试需要考虑GPIO的选择和复用设定,
最开始的时候我拿到的是GPIO Pin Mux的Excel, 整理如下:
后面的研究发现这里有坑
Pin Mux相关的代码
hal_iomux_best2300p.c文件中pin_func_map函数定义了每个引脚所支持的各种复用功能,
我们可以注意到上节所说的坑, 因为这里的定义和上节的excel是对应不上的, 解决方法:应该采用SPILCD而不是SPI的相关接口.
至于SPI接口, 因为我的2300YP没有P04~07,所以用不上, 如果换成其他芯片和封装, 可以具体再研究下
其定义如下:
// 为方便阅读, 和针对2300yp, 部分无效引脚的代码删除
static const enum HAL_IOMUX_FUNCTION_T pin_func_map[HAL_IOMUX_PIN_NUM][IOMUX_ALT_FUNC_NUM] = {
// P0_0
{ HAL_IOMUX_FUNC_I2S0_SDI0, HAL_IOMUX_FUNC_UART2_RX, HAL_IOMUX_FUNC_PCM_DI, HAL_IOMUX_FUNC_SPILCD_DI0,
HAL_IOMUX_FUNC_PDM0_CK, HAL_IOMUX_FUNC_SPILCD_DCN, },
// P0_1
{ HAL_IOMUX_FUNC_I2S0_SDO, HAL_IOMUX_FUNC_UART2_TX, HAL_IOMUX_FUNC_PCM_DO, HAL_IOMUX_FUNC_SPILCD_DIO,
HAL_IOMUX_FUNC_PDM0_D, HAL_IOMUX_FUNC_NONE, },
// P0_2
{ HAL_IOMUX_FUNC_I2S0_WS, HAL_IOMUX_FUNC_I2C_M1_SCL, HAL_IOMUX_FUNC_PCM_FSYNC, HAL_IOMUX_FUNC_SPILCD_CS0,
HAL_IOMUX_FUNC_PDM1_D, HAL_IOMUX_FUNC_NONE, },
// P0_3
{ HAL_IOMUX_FUNC_I2S0_SCK, HAL_IOMUX_FUNC_I2C_M1_SDA, HAL_IOMUX_FUNC_PCM_CLK, HAL_IOMUX_FUNC_SPILCD_CLK,
HAL_IOMUX_FUNC_PDM2_D, HAL_IOMUX_FUNC_NONE, },
// P1_0
{ HAL_IOMUX_FUNC_SDMMC_DATA2, HAL_IOMUX_FUNC_I2S1_SCK, HAL_IOMUX_FUNC_SPILCD_CLK, HAL_IOMUX_FUNC_SPI_CS1,
HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_NONE, },
// P1_1
{ HAL_IOMUX_FUNC_SDMMC_DATA3, HAL_IOMUX_FUNC_I2S1_WS, HAL_IOMUX_FUNC_SPILCD_CS0, HAL_IOMUX_FUNC_SPI_CS2,
HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_NONE, },
// P1_2
{ HAL_IOMUX_FUNC_SDMMC_CMD, HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_SPILCD_CS1, HAL_IOMUX_FUNC_SPI_CS3,
HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_NONE, },
// P1_3
{ HAL_IOMUX_FUNC_SDMMC_CLK, HAL_IOMUX_FUNC_I2S0_MCLK, HAL_IOMUX_FUNC_SPILCD_DCN, HAL_IOMUX_FUNC_CLK_OUT,
HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_NONE, },
// P1_4
{ HAL_IOMUX_FUNC_SDMMC_DATA0, HAL_IOMUX_FUNC_I2S1_SDI0, HAL_IOMUX_FUNC_SPILCD_DI0, HAL_IOMUX_FUNC_NONE,
HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_NONE, },
// P1_5
{ HAL_IOMUX_FUNC_SDMMC_DATA1, HAL_IOMUX_FUNC_I2S1_SDO, HAL_IOMUX_FUNC_SPILCD_DIO, HAL_IOMUX_FUNC_I2S0_MCLK,
HAL_IOMUX_FUNC_CLK_OUT, HAL_IOMUX_FUNC_NONE, },
// P1_6
{ HAL_IOMUX_FUNC_UART0_RX, HAL_IOMUX_FUNC_I2C_M0_SCL, HAL_IOMUX_FUNC_BT_UART_RX, HAL_IOMUX_FUNC_NONE,
HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_NONE, },
// P1_7
{ HAL_IOMUX_FUNC_UART0_TX, HAL_IOMUX_FUNC_I2C_M0_SDA, HAL_IOMUX_FUNC_BT_UART_TX, HAL_IOMUX_FUNC_NONE,
HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_NONE, },// P2_2
{ HAL_IOMUX_FUNC_I2C_M1_SCL, HAL_IOMUX_FUNC_UART2_RX, HAL_IOMUX_FUNC_UART1_CTS, HAL_IOMUX_FUNC_BT_UART_CTS,
HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_I2S0_MCLK, },
// P2_3
{ HAL_IOMUX_FUNC_I2C_M1_SDA, HAL_IOMUX_FUNC_UART2_TX, HAL_IOMUX_FUNC_UART1_RTS, HAL_IOMUX_FUNC_BT_UART_RTS,
HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_CLK_OUT, },
// P2_5
{ HAL_IOMUX_FUNC_PWM1, HAL_IOMUX_FUNC_CLK_REQ_IN, HAL_IOMUX_FUNC_SPI_CS3, HAL_IOMUX_FUNC_NONE,
HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_NONE, },
// P2_6
{ HAL_IOMUX_FUNC_PWM2, HAL_IOMUX_FUNC_SPILCD_DI1, HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_SPDIF0_DI,
HAL_IOMUX_FUNC_CLK_32K_IN, HAL_IOMUX_FUNC_NONE, },
// P2_7
{ HAL_IOMUX_FUNC_PWM3, HAL_IOMUX_FUNC_SPILCD_CS1, HAL_IOMUX_FUNC_NONE, HAL_IOMUX_FUNC_SPDIF0_DO,
HAL_IOMUX_FUNC_CLK_OUT, HAL_IOMUX_FUNC_NONE, },
};
在hal_iomux_set_function函数中会基于pin_func_map来将功能序号转为寄存器掩码值,
这段代码如下:
// Other func values: 0 -> gpio, 6 -> rf_ana, 7 -> jtag/btdm, 9 -> clk_req, 10 -> ana_test
static const uint8_t index_to_func_val[IOMUX_ALT_FUNC_NUM] = { 1, 2, 3, 4, 5, 8, };
if (func == HAL_IOMUX_FUNC_GPIO) {
val = IOMUX_FUNC_VAL_GPIO;
}
else
{
for (i = 0; i < IOMUX_ALT_FUNC_NUM; i++)
{
if (pin_func_map[pin][i] == func)
{
break;
}
}
if (i == IOMUX_ALT_FUNC_NUM) {
return 3;
}
val = index_to_func_val[i];
}
reg = &iomux->REG_004 + pin / 8;
shift = (pin % 8) * 4;
*reg = (*reg & ~(0xF << shift)) | (val << shift);
Hal_spi.c/h的几组api
Hal_spi.c/h中有几组不同的api, 每组api有不同的原语(这个词我可能用的不合适)实现, 总结如下:
粗略的喵了一下, 这几组api只是用不同SPI_id调用一组后缀带_id的函数
所以这里我们应该可以忽略spi和spilcd的差别, 使用spilcd来替代本来预期的spi模块
hal_iomux_set_spilcd
这两个函数在hal_iomux_best2300p.c中定义, 是用来将GPIO的功能设定为用于SPILCD的.
他依赖于宏来控制所用的引脚, 以及SPI接口类型(3线或4线)
我的宏定义如下
#define SPILCD_IOMUX_4WIRE
// 使用GPIO 00~03时
#define SPILCD_IOMUX_DI0_INDEX 0
// 使用GPIO 10,11,14,15时
#define SPILCD_IOMUX_INDEX 10
#define SPILCD_IOMUX_DI0_INDEX 14
如果实在不放心, 请用以下函数
#define USE_GPIO_0_FOR_SPI
void my_iomux_set_spi()
{
#ifdef USE_GPIO_0_FOR_SPI
static const struct HAL_IOMUX_PIN_FUNCTION_MAP pinmux_spi_4wire[4] = {
{HAL_IOMUX_PIN_P0_3, HAL_IOMUX_FUNC_SPILCD_CLK, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL},
{HAL_IOMUX_PIN_P0_2, HAL_IOMUX_FUNC_SPILCD_CS0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL},
{HAL_IOMUX_PIN_P0_1, HAL_IOMUX_FUNC_SPILCD_DIO, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL},
{HAL_IOMUX_PIN_P0_0, HAL_IOMUX_FUNC_SPILCD_DI0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL},
};
#else // USE_GPIO_0_FOR_SPI
static const struct HAL_IOMUX_PIN_FUNCTION_MAP pinmux_spi_4wire[4] = {
{HAL_IOMUX_PIN_P1_0, HAL_IOMUX_FUNC_SPILCD_CLK, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL},
{HAL_IOMUX_PIN_P1_1, HAL_IOMUX_FUNC_SPILCD_CS0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL},
{HAL_IOMUX_PIN_P1_5, HAL_IOMUX_FUNC_SPILCD_DIO, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL},
{HAL_IOMUX_PIN_P1_4, HAL_IOMUX_FUNC_SPILCD_DI0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL},
};
#endif //USE_GPIO_0_FOR_SPI
hal_iomux_init(pinmux_spi_4wire, ARRAY_SIZE(pinmux_spi_4wire));
}
我的测试代码
#include "hal_spi.h"
#define SPI_DMA_SEND hal_spilcd_dma_send
#define SPI_DMA_RECV hal_spilcd_dma_recv
#define SPI_ENABLE_AND_SEND hal_spilcd_enable_and_send
#define SPI_ENABLE_AND_RECV hal_spilcd_enable_and_recv
#define SPI_OPEN hal_spilcd_open
extern void hal_iomux_set_spilcd(void);
#define IOMUX_SET_SPI hal_iomux_set_spilcd
static const struct HAL_SPI_CFG_T _spi_cfg_default =
{
.rate = 200000,
.clk_delay_half = true,
.clk_polarity = true,
.slave = false,
.dma_rx = true,
.dma_tx = true,
.rx_sep_line = true,
.cs = 0,
.tx_bits = 32,
.rx_bits = 32,
.rx_frame_bits = 0,
};
static struct HAL_SPI_CTRL_T _spi_ctrl_8bit;
void spi_test()
{
TRACE(1,"spi_test start!");
IOMUX_SET_SPI();
// my_iomux_set_spi();
int32_t ret = SPI_OPEN(&_spi_cfg_default);
TRACE(3,"%s, spi open failed! ret = %d", __func__, ret);
while(1)
{
uint8_t cmd[4];
cmd[0] = 0XAA;
cmd[1] = 0X55;
cmd[2] = 0XAA;
cmd[3] = 0X55;
ret = SPI_ENABLE_AND_SEND(&_spi_ctrl_8bit, cmd, sizeof(cmd));
TRACE(3,"%s, spi 1 send, ret = %d", __func__, ret);
osDelay(10);
ret = SPI_DMA_SEND(cmd, sizeof(cmd), NULL);
TRACE(3,"%s, spi dma send, ret = %d", __func__, ret);
osDelay(10);
}
TRACE(1,"spi_test done !");
}
// 测试时, 在app_init之前调用了spi_test
欢迎阅读更多 BES专栏文章