SPI SD Card 32GB Never passes CMD55, ACMD41 Initalization Step - sd-card

I am using Elm-chan FatFs module. I ported it correctly as it works when using a 16GB SD card. But when using a 32GB card, the code is getting stuck at the CMD55, ACMD41 set up loop.
Bellow is the print out of the command and response I am experiencing
cmd0, resp = 0x01
cmd8, resp = 0x01
cmd55, resp = 0x01
cmd41, resp = 0x01
cmd55, resp = 0x7F
cmd55, resp = 0x7F
cmd55, resp = 0x7F
cmd55, resp = 0x7F
cmd55, resp = 0x7F
cmd55, resp = 0x7F
cmd55, resp = 0x7F
cmd55, resp = 0x7F
cmd55, resp = 0xFF
cmd55, resp = 0xFF
Then from there, cmd55 always gets a response of 0xFF indefinitely. I've looked at other questions, spi SDC guides, and other ff.c implementations, and I am for the most part following it, because the code does work for a 16GB card, just when I switch to a 32GB card and restart the code, the 32GB card does not initialize.
Does it matter on the brand? the 32GB card is a samsung evo select micro sdhc. The 16GB is a Lexar micro sdhc

It is not clear in your question which bytes are sent and which are received. Also you list different bytes in the question title that are not in the question body. Perhaps if you edit it then someone will be able to give you a better answer.
The response 0x80 to CMD55 means the card is not ready for the next command. After sending CMD55 you have to read bytes repeatedly in a loop until the most significant bit is clear. Only after that can you send the ACMD.

Related

Trinamic TMC2209 STM32 UART not reading from device

I've been struggling for ages, finally caved and asking for help now.
There are very little resources on STM32 for this driver that I have seen.
I can use the device with the STEP/DIR interface but I want to be able to do the more advanced things now with only the single UART line and not the STEP/DIR lines.
I am trying to control a TMC2209 in the most basic form to understand how it all works, without libraries and such.
I want to get basic controls working so I can understand it and build up my own code from there, right now the goal is to just talk to the thing and get it to spin.
I am using a STM32F103, I have setup the USART3 line (PC10) in signal wire half duplex mode and using the following code to try read from the CHOPCONF register.
Sync = 0x05; // sync byte to start the Tx
Address = 0x00; // MS1 and MS2 are pulled low so the device address is 0
RegAddress = 0x6C; // Trying for a basic read from the CHOPCONF Reg
motor_CRC = 0xCA; // CRC that has been worked out
HAL_UART_Transmit(&huart3,&Sync,sizeof(Sync),20);
HAL_UART_Transmit(&huart3,&Address,sizeof(Address),20);
HAL_UART_Transmit(&huart3,&RegAddress,sizeof(RegAddress),20);
HAL_UART_Transmit(&huart3,&motor_CRC,sizeof(motor_CRC),20);
// Receive the data from the TMC2209
HAL_UART_Receive(&huart3, &ReplySync, sizeof(ReplySync), 200);
HAL_UART_Receive(&huart3, &ReplyMasterAddr, sizeof(ReplyMaster), 20);
HAL_UART_Receive(&huart3, &ReplyAddr, sizeof(ReplyAddr), 20);
HAL_UART_Receive(&huart3, &Reply1, sizeof(Reply1), 20);
HAL_UART_Receive(&huart3, &Reply2, sizeof(Reply2), 20);
HAL_UART_Receive(&huart3, &Reply3, sizeof(Reply3), 20);
HAL_UART_Receive(&huart3, &Reply4, sizeof(Reply4), 20);
HAL_UART_Receive(&huart3, &ReplyCRC, sizeof(ReplyCRC), 20);
HAL_Delay(1000);
I expect the following : ( according to the Datasheet that is,,, )
ReplySync >>> 0x05
ReplyMasterAddr>>> 0xFF
ReplyAddr >>> 0xCA
Reply1 >>> 0x53
Reply2 >>> 0x00
Reply3 >>> 0x00
Reply4 >>> 0x10
ReplyCRC >>> I dont know this one yet,,,,
But I am getting this :
ReplySync >>> 0x05
ReplyMasterAddr>>> 0x00
ReplyAddr >>> 0x5D
Reply1 >>> 0x09
Reply2 >>> 0x08
Reply3 >>> 0x00
Reply4 >>> 0x02
ReplyCRC >>> 0x09
I am not sure if I am transmitting these in the correct order or maybe the HAL function should not be used for this at all ?
Any help or pointers in the right direction would be greatly appreciated.

I2C: difference between I2C Tools and python SMBus2

I am trying to understand the i2c protocol and it's implementation through the python SMBus library and I2C Tools for Linux.
Let's look at the following I2C Sequences out of a datasheet: chapter 4.2 for the SFM3003:
I can read out the data, if I first initialise a continuous measurement with $i2cset -y 0x28 0x36 0x08 i
and then run my python script:
from smbus2 import SMBus, i2c_msg
import time
OFFSET_FLOW = -24576 # [-]
SCALEFACTOR_FLOW = 170 # [slm^-1]
OFFSET_TEMP = 0 # [-]
SCALEFACTOR_TEMP = 200 # [°C^-1]
#bus.write_byte_data(0x28, 0x36, 0x08)
msg = i2c_msg.read(0x28, 9)
bus = SMBus(1)
while True:
bus.i2c_rdwr(msg)
data = list(msg)
# JUST SOME CONVERSION FROM HERE ON
flow_bytes = data[0:2]
flow_bytes_converted = bytes(flow_bytes)
flow_raw = int.from_bytes(flow_bytes_converted, byteorder='big', signed=True)
print("flow_raw: ", flow_raw)
flow = (flow_raw-OFFSET_FLOW)/SCALEFACTOR_FLOW
print("flow: ", flow)
temp_bytes = data[3:5]
temp_bytes_converted = bytes(temp_bytes)
temp_raw = int.from_bytes(temp_bytes_converted, byteorder='big', signed=True)
print("temp_raw: ", temp_raw)
temp = (temp_raw-OFFSET_TEMP)/SCALEFACTOR_TEMP
print("temp: ", temp)
time.sleep(0.1)
If I uncomment the line bus.write_byte_data(0x28, 0x36, 0x08) and try to run the python script without initialisation from the command line($i2cset -y 0x28 0x36 0x08 i), I get an Remote I/O Error and see a NACK on my bus after writing 0x08 to the register 0x36.
So how is that command different to what I do with the I2C Linux Tools?

Reading/Writing to LSM6DSOX via SPI from Raspberry Pi

I'm having trouble reading and writing to my Adafruit LSM6DSOX IMU from my Raspberry Pi 4 running Ubuntu 20.04. I need to do it via SPI since I require the bandwidth, but I can only seem to read the WHO_AM_I register successfully. Reading/writing to any other register only returns 0x00. I have verified that I can read data off the IMU from an Arduino via SPI, but if I try to read a register other than 0x0F (the IMU_ID) I get 0x0 as a response. Any insight/ideas what could be causing this would be greatly appreciated!
EDIT: It turns out I can read the following registers:
0x0f : 0x6c
0x13 : 0x1c
0x33 : 0x1c
0x53 : 0x1c
0x73 : 0x1c
These are all random registers however, and the value 0x1C doesn't seem to correspond with anything.
This is my main.py:
import LSM6DSOX
def main():
imu=LSM6DSOX.LSM6DSOX()
imu.initSPI()
whoamI=imu.read_reg(0x0F)
while(whoamI != imu.LSM6DSOX_ID):
imu.ms_sleep(200)
print('searching for IMU')
whoamI=imu.get_id()
print(hex(whoamI))
print('found lsm6dsox IMU')
imu.spi.close()
imu.spi = None
if __name__=="__main__":
main()
This is an excerpt from my LSM6DSOX.py:
def initSPI(self):
# Setup communication SPI
self.spi = spidev.SpiDev()
self.spi.open(0, 0)
self.spi.mode=0b11 #mode 3, (mode 0 is also fine)
self.spi.max_speed_hz = 500000
return self.spi
def read_reg(self, reg, len=1):
# Set up message
buf = bytearray(len+1)
buf[0] = 0b10000000 | reg # MSB bit must be 1 to indicate a read operation. this is OR'd with the register address you want to read
resp =self.spi.xfer2(buf) #send (and recieve) data to the imu
if len==1:
return resp[1]
else:
return resp[1:] #display recieved data
def write_reg(self, reg, data, len=1):
# Set up message
buf = bytearray(len+1)
buf[0] = 0b00000000 | reg # MSB bit must be 0 to indicate a read operation. this is OR'd with the register address you want to read
buf[1:] =bytes(data)
resp =self.spi.xfer2(buf) #send (and recieve) data to the imu
return resp[1:] #display recieved data

Data transmission Pi/MCP3008

I have a question regarding data transmisison from a Raspberry Pi to a mcp3008. It is just a theoretical one. When they exchange the bytes does the master send 1 byte and receives 1 byte. Then sends the 2nd byte and receives 2nd byte.. OR does the master send 3 bytes and receives 3 bytes after that. From my understanding it is the first one, am I right?
Adafruit's library for the MCP3008 has your answer. Check out the read_adc() function:
def read_adc(self, adc_number):
"""Read the current value of the specified ADC channel (0-7). The values
can range from 0 to 1023 (10-bits).
"""
assert 0 <= adc_number <= 7, 'ADC number must be a value of 0-7!'
# Build a single channel read command.
# For example channel zero = 0b11000000
command = 0b11 << 6 # Start bit, single channel read
command |= (adc_number & 0x07) << 3 # Channel number (in 3 bits)
# Note the bottom 3 bits of command are 0, this is to account for the
# extra clock to do the conversion, and the low null bit returned at
# the start of the response.
resp = self._spi.transfer([command, 0x0, 0x0])
# Parse out the 10 bits of response data and return it.
result = (resp[0] & 0x01) << 9
result |= (resp[1] & 0xFF) << 1
result |= (resp[2] & 0x80) >> 7
return result & 0x3FF
It appears that it sends a three-byte command (where only one byte is non-zero):
resp = self._spi.transfer([command, 0x0, 0x0])
The response is three bytes which contains the packed 10-bit ADC value.
resp = self._spi.transfer([command, 0x0, 0x0])
# Parse out the 10 bits of response data and return it.
result = (resp[0] & 0x01) << 9
result |= (resp[1] & 0xFF) << 1
result |= (resp[2] & 0x80) >> 7

SPI fails to read first 6 bytes

I'm having a lot of issues with SPI module on my STM32F051 MCU. I've got it configured as a master to drive a slave flash memory module (that doesn't really matter).
I'm trying to read 8 bytes from memory, this is how the 'read data' message is structured:
First 4 bytes of the message are transmitted, next 8 are received.
First byte is 'read data' opcode, three following are data address and equal 0 in this case.
Code:
memset(out, 0x00, 256);
memset(in, 0x00, 256);
out[0] = OPCODE_READ;
out[1] = 0x00;
out[2] = 0x00;
out[3] = 0x00;
uint32_t len = 4 + size; // size == 8
spi_select(M25P80);
HAL_SPI_TransmitReceive(&hspi1, out, in, len, TIMEOUT);
delay_ms(BYTE_SPEED_MS * 5); // Needed because ^ finishes before physically
// transmitting the data. Nevermind the 5, it
// was picked experimentally
spi_deselect(M25P80);
Signal (yellow - clock, red - miso):
At 488 bits/s transmitting 4 bytes takes 4 * 1E3 / (488 / 8) = 65.5 ms. Then the reception starts. Memory starts transmitting [0xFF...0xFF] right away, but contents of the 'in' buffer are:
[0x00 0x00 0x00 0x00] [0x00 0x00 0x00 0x00 0x00] 0xFF 0xFF 0x00...0x00
^ zero because this ^ should be 0xFF ^ correct data
is the part where
data was being sent
to the memory
So first six bytes of data are just lost. Am I the only one who's having such a hard time with STM's SPI module?
EDIT:
I've gotten myself a different eval board with a slightly different MCU (STM32F030) and it gets even weirder:
[0x02 0x02 0x02 0x02]
0x00 0x02 0x00 0x00 0xFF 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00...0x00
Although I must mention that I'm using a different compiler with this MCU.
EDIT 2:
The way I partially got it to work is using 16-bit mode with SPI. This fixed this particular bug, but there are more similar oddities with STM32's SPI.
EDIT 3:
SPI initialisation code:
void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLED;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLED;
HAL_SPI_Init(&hspi1);
}
Are you sure that the initialization of SPI is right?
Maybe your Clock polarity or phase settings does not match between Master and Slave?
Take a watch to ClockSettings.
Please show your SPI-Initialization-Code!