How to enable the SPI master function with low layer hal?
Posted: Thu Apr 23, 2020 12:47 pm
Hi,
i'm triying to use to enable the spi master function on esp32. with Pins (GPIO12~15 and a reset pin of GPIO4).
this is the spi init fucntion,
nt lgw_spi_open (void** spi_target_ptr) {
gpio_set_direction(CS_PIN, GPIO_MODE_OUTPUT);
PIN_FUNC_SELECT(IO_MUX_GPIO12_REG, FUNC_MTDI_HSPIQ); // Pin MTDI --> function 1: HSPI MISO (GPIO12)
PIN_FUNC_SELECT(IO_MUX_GPIO13_REG, FUNC_MTCK_HSPID); // Pin MTCK --> function 1: HSPI MOSI (GPIO13)
PIN_FUNC_SELECT(IO_MUX_GPIO14_REG, FUNC_MTMS_HSPICLK); // Pin MTMS --> function 1: HSPI SCLK (GPIO14)
PIN_FUNC_SELECT(IO_MUX_GPIO15_REG, FUNC_MTDO_GPIO15);
PIN_FUNC_SELECT(IO_MUX_GPIO4_REG, FUNC_GPIO4_GPIO4); //
gpio_set_level(RESET_PIN,0);
gpio_set_level(CS_PIN,1);
CLEAR_PERI_REG_MASK(SPI_CLOCK_REG(SPI_NUM_HSPI), SPI_CLK_EQU_SYSCLK);
WRITE_PERI_REG(SPI_CTRL_REG(SPI_NUM_HSPI), 0); // Clear CTRL register (disables "fast-read" mode)
WRITE_PERI_REG(SPI_CLOCK_REG(SPI_NUM_HSPI),
((0x01 & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) // Pre-divide by 2 --> 40MHz
| ((0x04 & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) // Further divide by 5 --> 8MHz
| ((0x01 & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) // = ((SPI_CLKCNT_N+1)/2)-1
| ((0x04 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)); // = SPI_CLKCNT_N
WRITE_PERI_REG(SPI_USER_REG(SPI_NUM_HSPI),
SPI_CK_I_EDGE // Slave edge rising
| SPI_USR_MOSI // Enable data-out phase
| SPI_DOUTDIN); // Full-duplex (also do data-in during data-out)
WRITE_PERI_REG(SPI_CTRL1_REG(SPI_NUM_HSPI), 0); // Clear CTRL1 register (from Arduino lib)
//reset the slave device
gpio_set_level(RESET_PIN,1);
wait_ms(100);
gpio_set_level(RESET_PIN,0);
*spi_target_ptr = (void*) 1;
return LGW_SPI_SUCCESS;
}
Then for a spi transmit function, like this:
static void spi_ex (int len) {
int i, words = (len + 3) / 4;
WRITE_PERI_REG(SPI_CMD_REG(SPI_NUM_HSPI),
((len * 8 - 1) << SPI_USR_MOSI_DBITLEN_S) // bit count out
| ((len * 8 - 1) << SPI_USR_MOSI_DBITLEN_S)); // bit count in - Do we need this for full duplex?
for (i = 0; i < words; i++) {
WRITE_PERI_REG(SPI_Wx(SPI_NUM_HSPI, i), spibuf.words);
}
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM_HSPI), SPI_USR);
// Busy wait (64B @ 8Mbps --> 64us max)
while ((READ_PERI_REG(SPI_CMD_REG(SPI_NUM_HSPI)) & SPI_USR) != 0);
wait_ms(1); // XXX - not sure yet why this is necessary
for (i = 0; i < words; i++) {
spibuf.words = READ_PERI_REG(SPI_Wx(SPI_NUM_HSPI, i));
}
}
#define SPI_Wx(i,x) (SPI_CMD_REG(i) + (x * 4))
Currenly i can't capture any signals on clk ,MISO and MOSI when i tried to read register from slave. Can you help to check all configuration is right? By the way, i just can't find any detailed document for the registers? Can you share that?
Thanks vry much.
i'm triying to use to enable the spi master function on esp32. with Pins (GPIO12~15 and a reset pin of GPIO4).
this is the spi init fucntion,
nt lgw_spi_open (void** spi_target_ptr) {
gpio_set_direction(CS_PIN, GPIO_MODE_OUTPUT);
PIN_FUNC_SELECT(IO_MUX_GPIO12_REG, FUNC_MTDI_HSPIQ); // Pin MTDI --> function 1: HSPI MISO (GPIO12)
PIN_FUNC_SELECT(IO_MUX_GPIO13_REG, FUNC_MTCK_HSPID); // Pin MTCK --> function 1: HSPI MOSI (GPIO13)
PIN_FUNC_SELECT(IO_MUX_GPIO14_REG, FUNC_MTMS_HSPICLK); // Pin MTMS --> function 1: HSPI SCLK (GPIO14)
PIN_FUNC_SELECT(IO_MUX_GPIO15_REG, FUNC_MTDO_GPIO15);
PIN_FUNC_SELECT(IO_MUX_GPIO4_REG, FUNC_GPIO4_GPIO4); //
gpio_set_level(RESET_PIN,0);
gpio_set_level(CS_PIN,1);
CLEAR_PERI_REG_MASK(SPI_CLOCK_REG(SPI_NUM_HSPI), SPI_CLK_EQU_SYSCLK);
WRITE_PERI_REG(SPI_CTRL_REG(SPI_NUM_HSPI), 0); // Clear CTRL register (disables "fast-read" mode)
WRITE_PERI_REG(SPI_CLOCK_REG(SPI_NUM_HSPI),
((0x01 & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) // Pre-divide by 2 --> 40MHz
| ((0x04 & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) // Further divide by 5 --> 8MHz
| ((0x01 & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) // = ((SPI_CLKCNT_N+1)/2)-1
| ((0x04 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)); // = SPI_CLKCNT_N
WRITE_PERI_REG(SPI_USER_REG(SPI_NUM_HSPI),
SPI_CK_I_EDGE // Slave edge rising
| SPI_USR_MOSI // Enable data-out phase
| SPI_DOUTDIN); // Full-duplex (also do data-in during data-out)
WRITE_PERI_REG(SPI_CTRL1_REG(SPI_NUM_HSPI), 0); // Clear CTRL1 register (from Arduino lib)
//reset the slave device
gpio_set_level(RESET_PIN,1);
wait_ms(100);
gpio_set_level(RESET_PIN,0);
*spi_target_ptr = (void*) 1;
return LGW_SPI_SUCCESS;
}
Then for a spi transmit function, like this:
static void spi_ex (int len) {
int i, words = (len + 3) / 4;
WRITE_PERI_REG(SPI_CMD_REG(SPI_NUM_HSPI),
((len * 8 - 1) << SPI_USR_MOSI_DBITLEN_S) // bit count out
| ((len * 8 - 1) << SPI_USR_MOSI_DBITLEN_S)); // bit count in - Do we need this for full duplex?
for (i = 0; i < words; i++) {
WRITE_PERI_REG(SPI_Wx(SPI_NUM_HSPI, i), spibuf.words);
}
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM_HSPI), SPI_USR);
// Busy wait (64B @ 8Mbps --> 64us max)
while ((READ_PERI_REG(SPI_CMD_REG(SPI_NUM_HSPI)) & SPI_USR) != 0);
wait_ms(1); // XXX - not sure yet why this is necessary
for (i = 0; i < words; i++) {
spibuf.words = READ_PERI_REG(SPI_Wx(SPI_NUM_HSPI, i));
}
}
#define SPI_Wx(i,x) (SPI_CMD_REG(i) + (x * 4))
Currenly i can't capture any signals on clk ,MISO and MOSI when i tried to read register from slave. Can you help to check all configuration is right? By the way, i just can't find any detailed document for the registers? Can you share that?
Thanks vry much.