Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPI DR is write-size sensitive #755

Open
jonathanpallant opened this issue Aug 12, 2022 · 4 comments
Open

SPI DR is write-size sensitive #755

jonathanpallant opened this issue Aug 12, 2022 · 4 comments

Comments

@jonathanpallant
Copy link

The SPI2::DR field is defined in the PAC as 16-bits. However, writing a value to the FIFO this way places two 8-bit bytes into the FIFO, giving the same symptoms as this post: https://community.st.com/s/question/0D53W00000uVnbwSAC/spi-configured-to-send-8bit-sends-16bits

If I do this, I get eight bytes in the FIFO, every other byte is 0x00:

// Send data
dp.SPI2.dr.write(|w| w.dr().bits(buffer[0] as u16));
dp.SPI2.dr.write(|w| w.dr().bits(buffer[1] as u16));
dp.SPI2.dr.write(|w| w.dr().bits(buffer[2] as u16));
dp.SPI2.dr.write(|w| w.dr().bits(buffer[3] as u16));

If I do this instead, I get the four bytes I expect, not eight.

// Send data
let p = dp.SPI2.dr.as_ptr() as *mut u8;    
unsafe {
    p.write_volatile(buffer[0]);        
    p.write_volatile(buffer[1]);        
    p.write_volatile(buffer[2]);        
    p.write_volatile(buffer[3]); 
}
@adamgreig
Copy link
Member

The size of the field in the register doesn't change the access width, but instead it depends on the size of the register itself. I'm not sure which PAC you're looking at exactly but I guess most of them are similar. I believe the HALs generally do a direct pointer write as per your second example.

The CRC peripheral has a similar functionality which was addressed in #412 by adding some virtual registers for the other sizes - in fact looking over the comments there the applicability to SPI even came up then. If you'd like to try adding similar register aliases to SPI it sounds like a sensible thing to include.

@thejpster
Copy link

Oh, so it's doing a 32 bit write but the underlying register is only 16 bits so half gets thrown away.

Maybe the dr() docs could note that the hardware design makes the PAC function useless unless you are in 16 bit mode.

The chip was an STM32F030K6T6.

@adamgreig
Copy link
Member

Yea, it looks like at the moment the register is set to 32 bits wide in the SVD. It should be updated to 16 bits wide, and additionally you could add a second register at the same offset that was 8 bits wide and call it DR8 or something like that, which would then generate 8-bit writes when used.

I don't think it's useless even in 8-bit SPI mode - you can put two bytes in at once to load the SPI FIFO quicker. In any event it does accurately model the hardware peripheral; I think the HAL should be the place for abstracting over these details.

@hydra
Copy link
Contributor

hydra commented Sep 13, 2023

Would just like to confirm that this is an issue on at least the H743, and here's the relevant section from the datasheet.

image

Not all SPI peripherals on ST silicon are the same, for instance the F446's datasheet is like this:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants