35 / 28 / 10
Регистрация: 11.04.2022
Сообщений: 197
1

stm32 запись в SD

03.12.2023, 23:37. Показов 544. Ответов 4
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте, возникла проблема при попытке записи на карту памяти данных (карта инициализируется, на команды отвечает, все ок), однако как только пытаюсь запихать туда страницу (а точнее блок данных 512 бит) у меня не выходит этого... Карта отвечает, однако статусы в регистре STA говорят о том, что у меня FIFO пуст и что счетчик передачи не 0 (ровно на четверть размера данных, т.е. если DataLength = 512, то все заканчивается, когда FIFOCNT = 128, если допустим поставить DataLength = 16, то FIFOCNT= 4), соответственно карта в статус tran не переходит, т.к. данных обещанных не хватает.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
uint32_t SDTransferData(uint32_t* TxData)
{
    SDIO_DataInitTypeDef dataConf;
    dataConf.DataBlockSize      = SDIO_DATABLOCK_SIZE_512B;
    dataConf.DataLength         = 512;                                   
    dataConf.DataTimeOut        = SDIO_STOPTRANSFERTIMEOUT;
    dataConf.TransferDir        = SDIO_TRANSFER_DIR_TO_CARD;
    dataConf.TransferMode       = SDIO_TRANSFER_MODE_BLOCK;
    dataConf.DPSM               = SDIO_DPSM_DISABLE;
    SDIO_ConfigData(SDIO,&dataConf);
    SDIO_WriteFIFO(SDIO,TxData);
 
    uint32_t volatile result =0;
    uint32_t volatile respData[4]={0,0,0,0};
    result          = SDMMC_CmdSendStatus(SDIO,RCA);
    if (result !=0) return result;
    respData[0]     = SDIO_GetResponse(SDIO,SDIO_RESP1);
 
    result          = SDMMC_CmdWriteSingleBlock(SDIO,0);
    if (result != 0) return result;
    respData[0]     = SDIO_GetResponse(SDIO,SDIO_RESP1);
 
    while(((respData[0]>>9)&0xf) != 6)
    {
        result      = SDMMC_CmdSendStatus(SDIO,RCA);
        if (result !=0) return result;
        respData[0] = SDIO_GetResponse(SDIO,SDIO_RESP1);
    }
    dataConf.DPSM   = SDIO_DPSM_ENABLE;
    SDIO_ConfigData(SDIO,&dataConf);
 
    while(((respData[0]>>9)&0xf) != 4)
        {
            result      = SDMMC_CmdSendStatus(SDIO,RCA);
            if (result !=0) return result;
            respData[0] = SDIO_GetResponse(SDIO,SDIO_RESP1);
            //SDIO_WriteFIFO(SDIO,TxData);
        }
    return 0;                                                           // succses
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
03.12.2023, 23:37
Ответы с готовыми решениями:

Stm32 fatfs запись в фаил
Доброе время. Сегодня подключил к stm32f103 карту памяти по spi , попробывал пример. Чтение из...

Запись состояния входа в память STM32
Здравствуйте, при помощи STM32 управляется микросхема, в определенные моменты времени из нее...

STM32. Не могу сделать нормально запись во флеш.
Не могу понять, с чем связана данная проблема. Код такой: #define PAGE_SIZE 1024UL #define...

Общение с барометром MS5540 на STM32 (Arduino to STM32)
Получил от китайца сей аппарат, пошел тут же гуглить что нибудь готовое, но не тут то было....

4
35 / 28 / 10
Регистрация: 11.04.2022
Сообщений: 197
05.12.2023, 09:38  [ТС] 2
Так, хорошо, допустим всем в лом разбираться в <...>… для примера взял на рассмотрение Hal функцию writeblock (нет у меня сейчас возможности код ее сюда скопировать), она располагается в .с файле дров Hal с репозитория гита от st. Вопрос, почему в функции идет проверка только на наличие только наполовину пустого буфера и дозапись(причем, я еще, видимо, ошибочно полагал, что fifo достаточно дать 1 указатель на массив)в fifo только половины данных, как до этого половина данных попала в fifo, если в функции вообще нет использования fifo tx до момента проверки флага заполненности половины fifo

Добавлено через 6 минут
Переделал по аналогии с вызовом функций как в Hal функции и теперь я могу записывать 1 значение в память (первое) сразу же после вызова первый раз функции writeFIFO, в которую передается указатель на переменную, у меня флаги статуса с буфер fifo наполовину пуст и целиком пуст и txact переходит в состояние transmit fifo underrun error, соответственно счетчик fifo cnt сбрасывается на 0
0
5 / 5 / 2
Регистрация: 02.10.2013
Сообщений: 130
07.12.2023, 11:23 3
FiFo buffer 32 bit регистр и соответственно влезает максимум 128 байт и это при условии что сам FIFO буфер состоит из 32 регистров, а это зависит от чипа. и чтобы впихнуть 512 байт нужно 4 раза забить буффер 128 байтами, а этого самого разбиения я как то и не наблюдаю.
0
35 / 28 / 10
Регистрация: 11.04.2022
Сообщений: 197
07.12.2023, 22:26  [ТС] 4
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
uint32_t SDTransferData(uint8_t* TxData, uint32_t writeAddr)
{
#define SD_NORMAL_MODE
    SDIO_DataInitTypeDef dataConf;
    dataConf.DataBlockSize      = SDIO_DATABLOCK_SIZE_512B;
    dataConf.DataLength         = 512;
    dataConf.DataTimeOut        = SDIO_STOPTRANSFERTIMEOUT;
    dataConf.TransferDir        = SDIO_TRANSFER_DIR_TO_CARD;
    dataConf.TransferMode       = SDIO_TRANSFER_MODE_BLOCK;
    dataConf.DPSM               = SDIO_DPSM_ENABLE;
    SDIO_ConfigData(SDIO,&dataConf);
 
    uint32_t pData;
    uint8_t* tempData = TxData;
 
    uint32_t volatile result =0;
    uint32_t volatile respData[4]={0,0,0,0};
    result          = SDMMC_CmdSendStatus(SDIO,RCA);
    if (result !=0) return result;
    respData[0]     = SDIO_GetResponse(SDIO,SDIO_RESP1);
 
    result          = SDMMC_CmdWriteSingleBlock(SDIO,writeAddr);
    if (result != 0) return result;
    respData[0]     = SDIO_GetResponse(SDIO,SDIO_RESP1);
 
    while(((respData[0]>>9)&0xf) != SD_RCV)
    {
        result      = SDMMC_CmdSendStatus(SDIO,RCA);
        if (result !=0) return result;
        respData[0] = SDIO_GetResponse(SDIO,SDIO_RESP1);
    }
    __SDIO_CLEAR_FLAG(SDIO,SDIO_STATIC_FLAGS);
#if defined (SD_NORMAL_MODE)
    while(!__SDIO_GET_FLAG(SDIO, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
    {
        if (__SDIO_GET_FLAG(SDIO,SDIO_FLAG_TXFIFOHE))
        {
            for (int i=0;i<8;++i)
            {
                pData = (uint32_t)*tempData;
                tempData++;
                pData |= (uint32_t)(*tempData)<<8;
                tempData++;
                pData |= (uint32_t)(*tempData)<<16;
                tempData++;
                pData |= (uint32_t)(*tempData)<<24;
                tempData++;
 
                SDIO_WriteFIFO(SDIO,&pData);
            }
        }
    }
#elif defined (SD_DMA_MODE)
{
    __SDIO_ENABLE_IT(SDIO, SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR);
    DMA_TxConfig();
    //__SDIO_DMA_ENABLE();
    
}
#endif
    while(((respData[0]>>9)&0xf) != SD_TRAN)
        {
            result      = SDMMC_CmdSendStatus(SDIO,RCA);
            if (result !=0) return result;
            respData[0] = SDIO_GetResponse(SDIO,SDIO_RESP1);
        }
    __SDIO_CLEAR_FLAG(SDIO,SDIO_STATIC_FLAGS);
    return 0;                                                           // succses
int32_t SDReceiveData(uint8_t* RxData , uint32_t readAddr)
{
    SDIO_DataInitTypeDef dataConf;
    dataConf.DataBlockSize      = SDIO_DATABLOCK_SIZE_512B;
    dataConf.DataLength         = 512;                                   // !!!!!! ИСПРАВИТЬ ЭТО ТОЛЬКО ДЛЯ КАЛОТЕСТА записи
    dataConf.DataTimeOut        = SDMMC_DATATIMEOUT;
    dataConf.TransferDir        = SDIO_TRANSFER_DIR_TO_SDIO;
    dataConf.TransferMode       = SDIO_TRANSFER_MODE_BLOCK;
    dataConf.DPSM               = SDIO_DPSM_ENABLE;
    uint32_t data =0;
    uint8_t* tempRx = RxData;
    SDIO_ConfigData(SDIO,&dataConf);
 
    uint32_t volatile result =0;
    uint32_t volatile respData[4]={0,0,0,0};
    result = SDMMC_CmdSendStatus(SDIO,RCA);
    if (result !=0) return result;
    respData[0] = SDIO_GetResponse(SDIO,SDIO_RESP1);
    while(((respData[0]>>9)&0xf) != SD_TRAN)
    {
        result = SDMMC_CmdSendStatus(SDIO,RCA);
        if (result !=0) return result;
        respData[0] = SDIO_GetResponse(SDIO,SDIO_RESP1);
    }
    result = SDMMC_CmdReadSingleBlock(SDIO,readAddr);
    if (result != 0) return result;
    respData[0] = SDIO_GetResponse(SDIO,SDIO_RESP1);
 
    __SDIO_CLEAR_FLAG(SDIO,SDIO_STATIC_FLAGS);
 
    while(((respData[0]>>9)&0xf) != SD_TRAN)
    {
        result = SDMMC_CmdSendStatus(SDIO,RCA);
        if (result !=0) return result;
        respData[0] = SDIO_GetResponse(SDIO,SDIO_RESP1);
    }
    uint16_t Cntdata = dataConf.DataLength;
    while(!__SDIO_GET_FLAG(SDIO, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
    {
        if (__SDIO_GET_FLAG(SDIO, SDIO_FLAG_RXFIFOHF))
        {
            for( int i =0;i<8;++i)
            {
                data = SDIO_ReadFIFO(SDIO);
                *tempRx = (uint8_t)(data & 0xff);
                tempRx++;
                Cntdata--;
                *tempRx = (uint8_t)((data>>8)& 0xff);
                tempRx++;
                Cntdata--;
                *tempRx = (uint8_t)((data>>16)& 0xff);
                tempRx++;
                Cntdata--;
                *tempRx = (uint8_t)((data>>24)& 0xff);
                tempRx++;
                Cntdata--;
            }
        }
    }
    if(__SDIO_GET_FLAG(SDIO,SDIO_FLAG_DTIMEOUT))
    {
        __SDIO_CLEAR_FLAG(SDIO,SDIO_FLAG_DTIMEOUT);
        return SDMMC_ERROR_DATA_TIMEOUT;
    }
    if(__SDIO_GET_FLAG(SDIO,SDIO_FLAG_DCRCFAIL))
    {
        __SDIO_CLEAR_FLAG(SDIO,SDIO_FLAG_DCRCFAIL);
        return SDMMC_ERROR_DATA_CRC_FAIL;
    }
    if(__SDIO_GET_FLAG(SDIO,SDIO_FLAG_RXOVERR))
    {
        __SDIO_CLEAR_FLAG(SDIO,SDIO_FLAG_RXOVERR);
        return SDMMC_ERROR_RX_OVERRUN;
    }
    while(Cntdata >0 && __SDIO_GET_FLAG(SDIO, SDIO_STA_RXDAVL))
    {
        data = SDIO_ReadFIFO(SDIO);
        *tempRx = (uint8_t)(data & 0xff);
        tempRx++;
        Cntdata--;
        *tempRx = (uint8_t)((data>>8)& 0xff);
        tempRx++;
        Cntdata--;
        *tempRx = (uint8_t)((data>>16)& 0xff);
        tempRx++;
        Cntdata--;
        *tempRx = (uint8_t)((data>>24)& 0xff);
        tempRx++;
        Cntdata--;
    }
    
 
 
    __SDIO_CLEAR_FLAG(SDIO,SDIO_STATIC_FLAGS);
    return 0;                                                           // succsess
}
}
рабочий код. Из НЮАНСОВ, огромных, таких нюансов это скорости шин, очень долго искал причину txunderrun. В первых итерациях я считывал с 32 битного слова и принимал тоже в 32 битное слово и все было хорошо, но как только я начал "собирать" 32 слово для записи в fifo (40 строчка), то я начал постоянно выпадать в txunderrun, методом огромного количества проб и ошибок догадался, что проблема мб в скорости шин. Была 72 МГц шина apb2 и 24 МГц шина SDIO, точнее SDIO_CK = 24 МГц, как только понизил частоту шины (поставил 48/8 = 6 МГц), то ошибки ушли. Всем спасибо за помощь и подробное разъяснение. Для примера были рассмотрены библиотеки HAL и старые библиотеки на SD также от самого ST. Во всех библиотеках проверка на наличие/запись в fifo осуществляется на половину fifo, если использовать флаги для целого fifo (т.е. TXFIFOE или RXFIFOF), то тоже проваливался в ошибки, в чем причина - не разобрался, возможно также в ограничениях скорости шины, но мб и что-то другое.

Добавлено через 4 минуты
p.s. Фактически 1 вопрос был некорректный, т.к. я неверно интерпретировал DATALEN и FIFOCNT, там все ок, т.к. FIFOCNT измеряется в словах (word = 32 бит).
0
35 / 28 / 10
Регистрация: 11.04.2022
Сообщений: 197
10.12.2023, 23:18  [ТС] 5
в 36 и 108 строчке кода в условия необходимо добавить проверку на текущее количество байт >0, бывает так, что while отработал и снова зашли в чтение или запись, а флаг SDIO_FLAG_DATAEND поднимается чуууть позже проверки и тогда выходим за границы допустимой памяти массива.
0
10.12.2023, 23:18
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.12.2023, 23:18
Помогаю со студенческими работами здесь

Чем связать STM32 + STM32 в одном корпусе?
Есть 2 платы: (1) - STM32 (Вывод на LCD + запись SD) и (2) - STM32F4 (обработка сигналов +...

stm32 + FSMC + stm32
Доброе времени суток. Возможно ли к Ftosh памяти подцепить два Stm32F4. Один МК будет записывать...

STM32 - STM32 I2C
*****ПРОБЛЕМА ИСПРАВЛЕНА****ОТВЕТ НИЖЕ , НЕ ВЧИТЫВАЙТЕСЬ В КОД ПРОГРАММЫ,УТОНЕТЕ)), НУ ЕСЛИ ТОЛЬКО...

Четыре кнопки на форме: добавить запись, удалить запись, закрыть, найти запись
Private Sub КнопкаДобавитьЗапись_Click() On Error GoTo Err_КнопкаДобавитьЗапись_Click ...

STM32 + SD
Кто-нибудь подключал карту памяти к STM32 ? Помогите с функциями обмена с картой. Для AVR эту...

STM32 на C#
1) Можно ли программировать STM32 на C#? Если вы натыкались на внятный гайд, дайте пожалуйста...

STM32: F0 vs F1
После беглого ознакомления со спектром МК STM32 мое внимание привлекли 2 семейства: F0 (Entry...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru