Hello,
OS: FreeBSD:13.2-Release
Driver: spigen-rpi4
The issue: With 5MHz SPI clock the communication RPI<->mcp3912 is established smooth. After increasing the speed to 10MHz, data is very random/incorrect.
The SPI devices supports SPI clock to 20MHz.
Verification scenario is very short:
Would be great to focus only onto a SW/FW site. - of course any HW specific thoughts are nice to read as well.
MCP insides:
Many thanks for any advice!
Best regards,
Code I use with some readability trunks:
OS: FreeBSD:13.2-Release
Driver: spigen-rpi4
The issue: With 5MHz SPI clock the communication RPI<->mcp3912 is established smooth. After increasing the speed to 10MHz, data is very random/incorrect.
The SPI devices supports SPI clock to 20MHz.
Verification scenario is very short:
- store the value on a specific register
- read register and compare with the value
- values are not equal
Would be great to focus only onto a SW/FW site. - of course any HW specific thoughts are nice to read as well.
MCP insides:
- Each register is 24 bit
- Communication start with initial byte, where one determine address, register and write/read operation
Many thanks for any advice!
Best regards,
Code I use with some readability trunks:
C:
typedef union TB {
uint32_t msg;
uint8_t msg_u8[sizeof(uint32_t)];
} TB;
void mcp_spi_init(int32_t speed) {
ASSERT_COND(speed > 0);
atexit(close_descriptors);
spifd0 = open(mcp_spidev_0, O_RDWR);
ASSERT_IO(spifd0);
ASSERT(ioctl(spifd0, SPIGENIOC_SET_SPI_MODE, &spimode));
ASSERT(ioctl(spifd0, SPIGENIOC_SET_CLOCK_SPEED, &spispeed));
is_mode32 = false;
}
void mcp_spi_write(uint8_t dev_mask, uint8_t mcp_reg, uint32_t cmd) {
ASSERT_COND(!(cmd & 0xff000000));
TB tb;
tb.msg = bswap32(cmd);
uint8_t mcp_addr = (MCP_DEVADDR_DEFAULT << MCP_DEVADDR__O) |
(mcp_reg << MCP_REGADDR__O) | MCP_WRITE;
struct spigen_transfer mcp_trn;
mcp_trn.st_command.iov_base = &mcp_addr;
mcp_trn.st_command.iov_len = 1;
if (is_mode32) {
mcp_trn.st_data.iov_base = tb.msg_u8;
mcp_trn.st_data.iov_len = sizeof(uint32_t);
} else {
mcp_trn.st_data.iov_base = tb.msg_u8 + 1;
mcp_trn.st_data.iov_len = sizeof(uint32_t) - 1;
}
ASSERT(ioctl(spifd0, SPIGENIOC_TRANSFER, &mcp_trn));
}
uint32_t mcp_spi_read(uint8_t mcp_reg) {
TB tb;
tb.msg = 0;
uint8_t mcp_addr = (MCP_DEVADDR_DEFAULT << MCP_DEVADDR__O) |
(mcp_reg << MCP_REGADDR__O) | MCP_READ;
struct spigen_transfer mcp_trn;
mcp_trn.st_command.iov_base = &mcp_addr;
mcp_trn.st_command.iov_len = 1;
if (is_mode32) {
mcp_trn.st_data.iov_base = tb.msg_u8;
mcp_trn.st_data.iov_len = sizeof(uint32_t);
} else {
mcp_trn.st_data.iov_base = tb.msg_u8 + 1;
mcp_trn.st_data.iov_len = sizeof(uint32_t) - 1;
}
ASSERT(ioctl(spifd0, SPIGENIOC_TRANSFER, &mcp_trn));
return bswap32(tb.msg);
}