目录
GPIO Pin Mux
Pin Mux相关的代码
Hal_spi.c/h的几组api
hal_iomux_set_spilcd
我的测试代码
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_teststatic 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的几组apiHal_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_SPIvoid 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_openextern void hal_iomux_set_spilcd(void);#define IOMUX_SET_SPI hal_iomux_set_spilcdstatic 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专栏文章