|
SPI1 в STM32F429 считывает 0 в младший бит |
|
|
|
 |
Ответов
(1 - 61)
|
Jun 16 2016, 07:13
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(RadiatoR @ Jun 16 2016, 08:11)  Попробуйте прочитать по флагу BSY. +1. В своё время отлаживал SPI, приходилось плясать вокруг разных битов статуса. До конца не стал вникать, как оно по феншую должно быть. Получил вариант, который работает, и оставил его: Код SPI1_DR = 0x05; while ((SPI1_SR & (1 << 1)) == 0) { /* wait for TXE */ } while ((SPI1_SR & (1 << 0)) == 0) { /* wait for RXNE */ } while ((SPI1_SR & (1 << 7)) != 0) { /* wait for !BUSY */ } CS_DEASSERT(); return SPI1_DR;
|
|
|
|
|
Jun 16 2016, 07:34
|

Местный
  
Группа: Свой
Сообщений: 270
Регистрация: 8-08-15
Из: Москва
Пользователь №: 87 901

|
Вообще сам флаг BSY для приема использовать не правильно. Для этого и нужен RXNE. Я отлаживая SPI на LIS3DS6 при вылавливании косяков тоже его использовал, думая что он сейчас все решит. Проблема оказалась в другом. Цитата(ЯadiatoR @ May 28 2016, 11:44)  После записи в регистре DR оставалось 2 байта. и при следующем чтении CS устанавливался и сразу сбрасывался И считывалось хрен знает что. Может тут тоже CS ножка на этот бит улетает и MISO в HiZ попадает? Отсюда и периодические срабатывания...
|
|
|
|
|
Jun 16 2016, 12:37
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
Цитата(RadiatoR @ Jun 16 2016, 09:11)  Попробуйте прочитать по флагу BSY. Вообще есть ли у вас возможность посмотреть оба канала - MISO относительно клока? Оба канала в смысле MOSI MISO? Нет как раз спалил логический анализатор. Только двухлучевой осциллограф. Но у меня на MISO жестко стоит единица -- нет надобности. Должен всефда читать 0xFF. Цитата(ViKo @ Jun 16 2016, 10:06)  Смотря, каким фронтом записываете и читаете. Надо внимательно изучить все варианты. Там всего четыре варианта. Я выбрал то, что надо периферийному устройству: инвертированный CLK и по читать фронту. Но в моем тесте нет вариантов получить сдвиг или гонки на меняющемся в момент выборки входе даже если неправильная фаза выборки -- у меня всегда единица на входе.
|
|
|
|
|
Jun 16 2016, 18:56
|

Местный
  
Группа: Свой
Сообщений: 270
Регистрация: 8-08-15
Из: Москва
Пользователь №: 87 901

|
Цитата(Tarbal @ Jun 16 2016, 15:37)  Оба канала в смысле MOSI MISO? Нет как раз спалил логический анализатор. Только двухлучевой осциллограф. Я когда боролся с акселерометром нашел проблему просмотрев одновременно сигналы CS, MISO, CLK. Если есть возможность посмотрите их. У меня тоже читалось одно, а на ноге была единица - как я понял она подтягивалась осциллографом, я это по ссылке выше описывал.
|
|
|
|
|
Jun 17 2016, 11:59
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
Цитата(adnega @ Jun 16 2016, 23:38)  Видел такое, вроде, на SPI4 на PE2-PE6. На форуме поддержки мне написали, что известная проблема, но ST не шевелится: This is a recurrent problem, with around a dozen threads on this forum, which was never completely investigated down to the root - but I am afraid it can't be without active involvement of ST. It might be related to the sequencing of the very first SCK clock after enabling the peripheral, i.e. whether the SCK line was in active or inactive state from the point of view of CPOL just before enabling the peripheral or so. I've seen issues of a similar nature although not quite the same, when changing CPOL/CPHA on-the-go without stopping/restarting the peripheral (it's lots of fun to find out what's going on, I can recommend it as a weekend project ;-) ). Also, one friend of mine discovered, that the SPI receiver is driven from the pin directly rather than from an internal signal (i.e. when no pin was not set as SPI-SCK AF, the receiver did not work at all). I can't quite explain how could it be more specific to SPI1 - either through different parasitics, or different source clock (different APB)? https://my.st.com/public/STe2ecommunities/m...urrentviews=260
|
|
|
|
|
Jun 17 2016, 14:47
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
Цитата(ViKo @ Jun 17 2016, 17:16)  Не думаю, что в STM32F429 сделали неработающий SPI. Не верю! Да я тоже не верю, но уж упростил задачу до минимума. Инициализирую SPI, удерживаю периферию в сбросе (что значит на вход MISO подаю единицу). Читаю инигда 0xFE иногда 0xFF. Подключаю осциллограф к клоку и всегда читаю 0xFE. Каким таким чудесным образом клок влияет на достоверность чтения? В форуме объяснили этот эффект тем, что клок с ножки используется для работы приемника SPI. Но попробую добавить while (ANAS->SR & SPI_SR_BSY); Вы привели код для передачи. У меня с этим проблем нет. Вот прием читает нестабильно.
|
|
|
|
|
Jun 18 2016, 10:45
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(adnega @ Jun 18 2016, 11:40)  На пине микроконтроллера с AF SPI_MISO логическая единица, а приемник стабильно принимает байт с нулем в младшем разряде. Чего еще не понятно? Нигде этого не читал, сам с этим столкнулся и долго бодался. Было на каком-то SPI, на каком-то пине, (подробностей не помню, т.к. 2 года прошло) перешел на другие пины и другой номер SPI - чудеса пропали. Непонятно того, что из-за неправильного использования SPI (предполагаю, связано с периферийными тактами микроконтроллера), вы вдруг решили мне высказать несказанное, что на этом входе висит резистор. "Где имение, а где вода?" С железным подвешенным резистором можно быстрее докопаться до сути проблемы, чем с неким устройством, висящим в сбросе (может, и не выдающем единицу, а находящимся в высокоимпедансном состоянии). Желаете дальше дискутировать насчет резистора 0 ом? Цитата Prior to changing the CPOL/CPHA bits the SPI must be disabled by resetting the SPE bit. Цитата It is recommended to enable the SPI slave before the master sends the clock. If not, undesired data transmission might occur. The data register of the slave needs to be ready before the first edge of the communication clock or before the end of the ongoing communication. It is mandatory to have the polarity of the communication clock set to the steady state value before the slave and the master are enabled. Цитата During discontinuous communications, there is a 2 APB clock period delay between the write operation to SPI_DR and the BSY bit setting. As a consequence, in transmit-only mode, it is mandatory to wait first until TXE is set and then until BSY is cleared after writing the last data.
|
|
|
|
|
Jun 18 2016, 13:24
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(ViKo @ Jun 18 2016, 16:01)  С первого же сообщения... Дык, это была всего-лишь иллюстрация странного поведения. Затем русским-по-белому говорилось о жесткой единице. Подтверждаю, что сам сталкивался на stm32f429i-disco с аналогичной ситуацией. Сначала получал от слейва левый "нолик", затем довел ситуацию до предела - подключил MISO к 3.3В, а считывалось 0xFE. Перешел на другой порт и другие пины - и слейв прекрасно заработал. В эррате не нашел сей глюк, для себя отметил, может, экземпляр МК с дефектом. Похоже, что нет.
|
|
|
|
|
Jun 18 2016, 14:07
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
То, что читалось 0xFE, связано с работой не по мануалу. Чтобы убедиться, я и предложил повесить резистор. Во всяком случае, подключенный "щуп" осциллографа уж точно не должен был влиять на разное чтение, если там висит единица всегда. Цитата(adnega @ Jun 18 2016, 16:24)  Перешел на другой порт и другие пины - и слейв прекрасно заработал. В эррате не нашел сей глюк, для себя отметил, может, экземпляр МК с дефектом. Похоже, что нет. Вы просто не докопались до сути проблемы, вот на что это похоже.
|
|
|
|
|
Jun 19 2016, 08:38
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Genadi Zawidowski @ Jun 18 2016, 23:04)  Код отсылки/приёма байта по SPI в студию... Давно то было. Допускаю, что примерно так было CODE //--------------------------------------------------------------------------- // LED & BUTTON //--------------------------------------------------------------------------- SPI_NSS_bit = 1; for(i = 0; i < 3; i++) __NOP(); SPI_OE_bit = 0; SPI_NSS_bit = 0;
SPI2->CR2 = (0 << SPI_CR2_RXNEIE) | (0 << SPI_CR2_TXDMAEN) | (0 << SPI_CR2_RXDMAEN) | (1 << SPI_CR2_SSOE);
DMA1_Stream4->CR = (0 << DMA_SCR_PL) | (0 << DMA_SCR_CHSEL) | (1 << DMA_SCR_MINC) | (1 << DMA_SCR_DIR) | (0 << DMA_SCR_EN);
DMA1_Stream3->CR = (0 << DMA_SCR_PL) | (0 << DMA_SCR_CHSEL) | (1 << DMA_SCR_MINC) | (0 << DMA_SCR_DIR) | (0 << DMA_SCR_EN);
DMA1->LIFCR = (0x3D << 22); DMA1->HIFCR = (0x3D << 0);
for(i = 0; i < 10; i++) __NOP();
DMA1_Stream3->PAR = (DWORD)&SPI2->DR; DMA1_Stream3->M0AR = (DWORD)spi_rx; DMA1_Stream3->NDTR = SPI_SIZE; DMA1_Stream3->CR = (0 << DMA_SCR_PL) | (0 << DMA_SCR_CHSEL) | (1 << DMA_SCR_MINC) | (0 << DMA_SCR_DIR) | (1 << DMA_SCR_EN);
DMA1_Stream4->PAR = (DWORD)&SPI2->DR; DMA1_Stream4->M0AR = (DWORD)spi_tx; DMA1_Stream4->NDTR = SPI_SIZE; DMA1_Stream4->CR = (0 << DMA_SCR_PL) | (0 << DMA_SCR_CHSEL) | (1 << DMA_SCR_MINC) | (1 << DMA_SCR_DIR) | (1 << DMA_SCR_EN);
for(i = 0; i < 10; i++) __NOP();
SPI2->CR2 = (0 << SPI_CR2_RXNEIE) | (1 << SPI_CR2_TXDMAEN) | (1 << SPI_CR2_RXDMAEN) | (1 << SPI_CR2_SSOE);
Это рабочий код, т.к. использует SPI2 и DMA1. Нерабочий был, вроде, на SPI4 и DMA2. Отправка работала корректно, а прием 2 байт давал нулевой младший бит (вроде только в первом принимаемом байте, а не в каждом).
|
|
|
|
|
Jun 19 2016, 16:42
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
Вроде нашел в чем дело. Я поначалу не знал, что хардвер чип селект не доделан и его нужно только вручную ставить. Ну и выбрал хардвер, где-то нашел, что для его снятия надо вызывать DISABLE_SPI(). Вроде обмен происходит, а поскольку проблема не возникла сразу, а SPI это мизерная часть моего проекта, то я не стал вникать в детали тогда. Что происходит. При каждой транзакции разрешается интерфейс и одновременно сигнал клока идет в единицу (клок инвертирован), чип селект в ноль. Если на клоке есть емкость, то он немного запаздывает и видимо воспринимается как первый фронт клока. Будет время переделаю на софтвер чипселект и расскажу. Цитата(ViKo @ Jun 18 2016, 00:12)  И де вы такое прочитали?  На ноль омов резисторов не бывает.  Бывают. Цитата(ViKo @ Jun 18 2016, 17:01)  С первого же сообщения (slave устройство...) и до последнего от топикстартера. Поскольку есть устройство, то гарантии, что оно выдает мощную единицу всегда - нет. Топикстартер мог даже и не разглядеть кратковременного провала в цепи, в зависимости от качества осциллографа и квалификации "наблюдателя". Ну осциллографом я пользоваться умею и никакого другого значения кроме единицы там не видел.
|
|
|
|
|
Jun 19 2016, 18:13
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(Tarbal @ Jun 19 2016, 19:42)  Бывают. Пе-ре-мыч-ки. Цитата Ну осциллографом я пользоваться умею и никакого другого значения кроме единицы там не видел. Назовите модель осциллографа, полосу частот, частоту дискретизации.
|
|
|
|
|
Jun 19 2016, 18:21
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(ViKo @ Jun 19 2016, 18:28)  У меня есть STM32F429I-Disco. Если выложите код, похожий на нерабочий, могу посмотреть. Но с нуля писать лень. Вдруг не не заработает.  Короче, пытаюсь воспроизвести ошибку - не получается. Перепробовал SPI1, SPI4, SPI5. Точные номер SPI и номера пинов не помню. Хотел же тогда на электроникс запостить, но поленился описывать глюк. Итого: ошибку воспроизвести не могу; если кто сообщит номер SPI и номера пинов (и каналов DMA опционально), то могу попробовать на макете.
|
|
|
|
|
Jun 19 2016, 19:16
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(adnega @ Jun 19 2016, 21:21)  ошибку воспроизвести не могу Короче, проверил все с SPI1 по SPI5. Ошибка, увы, не воспроизводится. Читаю-пишу так Код BYTE spi_send_byte(const BYTE data) { BYTE spib; while((SPI3->SR & (1 << SPI_SR_TXE)) == 0); SPI3->DR = data; while((SPI3->SR & (1 << SPI_SR_RXNE)) == 0); spib = SPI3->DR; return spib; } Цитата(ViKo @ Jun 19 2016, 21:13)  Пе-ре-мыч-ки. Вопрос определений. Под "резистором 0 Ом" можно понимать: перемычку, резистор, кусок провода, печатную дорожку и т.п. Я покупаю такие; в счете написано "резисторы".
Эскизы прикрепленных изображений
|
|
|
|
|
Jun 19 2016, 22:23
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
Цитата(ViKo @ Jun 20 2016, 01:14)  Ага, нашел, jumper. Он еще и точность имеет, и мощность рассеивания.  Я буду называть перемычками, как принято.  Цитата(ViKo @ Jun 19 2016, 19:28)  У меня есть STM32F429I-Disco. Если выложите код, похожий на нерабочий, могу посмотреть. Но с нуля писать лень. Вдруг не не заработает.  Вот такой код. Только теперь вместо нуля всегда читает единицу и только в первом интерфейсе. CODE HAL_StatusTypeDef SPI_WaitOnFlagTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus Status, uint32_t Timeout) { uint32_t start = jiffies; while(__HAL_SPI_GET_FLAG(hspi, Flag) == Status){ if(jiffies - start >= Timeout){ return -HAL_TIMEOUT; } } return HAL_OK; } #if 0 /* This funtion is used to transmit and receive data * with SPI1 * data --> data to be transmitted * returns received value */ uint8_t SPI1_send(uint8_t data){
SPI1->DR = data; // write data to be transmitted to the SPI data register while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete while( !(SPI1->SR & SPI_I2S_FLAG_RXNE) ); // wait until receive complete while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore return SPI1->DR; // return received data from SPI data register } #endif
int SPI_Transmit1(SPI_HandleTypeDef *hspi, uint8_t* val, uint32_t timeout) { FlagStatus Status; __HAL_SPI_ENABLE(hspi); hspi->Instance->DR = *val; Status = SPI_WaitOnFlagTimeout(hspi, SPI_FLAG_TXE, RESET, timeout); if(HAL_OK != Status){ return Status; } Status = SPI_WaitOnFlagTimeout(hspi, SPI_FLAG_RXNE, RESET, timeout); if(HAL_OK != Status){ return Status; } Status = SPI_WaitOnFlagTimeout(hspi, SPI_FLAG_BSY, SET, timeout); *val = hspi->Instance->DR; return Status; }
int write_spi_reg(uint8_t chip_id, uint8_t reg_addr, uint8_t val) { SPI_HandleTypeDef* hspi; uint8_t buf[SPI_WRITE_LEN]; uint8_t i; uint8_t id; GPIO_TypeDef* port; uint16_t pin;
HAL_StatusTypeDef ret;
if(CHIPS_AMOUNT <= chip_id){ return -WRONG_PARAMETER; }
hspi = hspi1; id = 0 port = GPIOA; pin = GPIO_PIN_4;
buf[0] = WR_SPI_CMD(id); buf[1] = reg_addr; buf[2] = val;
for(i = 0; i < SPI_WRITE_LEN; i++){ HAL_GPIO_WritePin(port, pin, 0); short_delay(7); ret = SPI_Transmit1(hspi, &buf[i], SPI_TIMEOUT); HAL_GPIO_WritePin(port, pin, 1); short_delay(7);
if(HAL_OK != ret){ responce_handle(ret); return -ret; } } return NO_ERROR; }
int read_spi_reg(uint8_t chip_id, uint8_t reg_addr) { SPI_HandleTypeDef* hspi; uint8_t buf[2]; uint8_t id; HAL_StatusTypeDef ret; GPIO_TypeDef* port; uint16_t pin; chip_interface_t* chip_if;
if(CHIPS_AMOUNT <= chip_id){ return; } hspi = hspi1; id = 0 port = GPIOA; pin = GPIO_PIN_4;
buf[0] = RD_SPI_CMD(id); buf[1] = reg_addr;
HAL_GPIO_WritePin(port, pin, 0); short_delay(7); ret = SPI_Transmit1(hspi, &buf[0], SPI_TIMEOUT);
HAL_GPIO_WritePin(port, pin, 1); short_delay(7); HAL_GPIO_WritePin(port, pin, 0); short_delay(7); ret = SPI_Transmit1(hspi, &buf[1], SPI_TIMEOUT); HAL_GPIO_WritePin(port, pin, 1); short_delay(7);
if(HAL_OK != ret){ responce_handle(ret); return (uint16_t) -1; }
HAL_GPIO_WritePin(port, pin, 0); short_delay(7); ret = SPI_Transmit1(hspi, &buf[0], SPI_TIMEOUT); HAL_GPIO_WritePin(port, pin, 1); short_delay(7);
if(HAL_OK != ret){ responce_handle(ret); }
return (uint32_t)buf[0]; }
Конфигурация: Registers SPI_CR1 = 0x0000015F SPI_CR2 = 0x00000004
|
|
|
|
|
Jun 20 2016, 00:02
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
А замена на такую функцию (без аппаратной поддержки SPI) прекрасно работает. CODE #define PIN(PORT, PIN) GPIO##PORT, GPIO_PIN_##PIN
#define SPI1_CLK_PIN PIN(B, 3) #define SPI1_MOSI_PIN PIN(A,7) #define SPI1_MISO_PIN PIN(A, 6) #define SPI1_SS_PIN PIN(A, 4)
#define SET_CLK1() HAL_GPIO_WritePin(SPI1_CLK_PIN, 1) #define CLR_CLK1() HAL_GPIO_WritePin(SPI1_CLK_PIN, 0)
#define SET_MOSI1() HAL_GPIO_WritePin(SPI1_MOSI_PIN, 1) #define CLR_MOSI1() HAL_GPIO_WritePin(SPI1_MOSI_PIN, 0)
#define GET_MISO1() HAL_GPIO_ReadPin(SPI1_MISO_PIN)
int SPI_Transmit1(SPI_HandleTypeDef *hspi, uint8_t* val, uint32_t timeout) { int i; uint8_t res= 0, tmp = *val; if(&hspi1 == hspi){ for(i = 0; i < 8; i++){ res <<= 1; CLR_CLK1(); if(tmp & 0x80){ SET_MOSI1(); } else { CLR_MOSI1(); } res |= GET_MISO1(); SET_CLK1(); tmp <<= 1; } } else { return SPI_Transmit1_hw(hspi, val, timeout); } *val = res; return 0; }
В принципе если ожидать в цикле флагов, аппаратное исполнение не дает выигрыша, ну разве только на выскоких частотах обмена. Программное исполнение дает клок 1 мегагерц, что довольно сносно.
|
|
|
|
|
Jun 21 2016, 17:24
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(ViKo @ Jun 21 2016, 17:28)  Заметьте, у adnega все каналы SPI работают! Сейчас не получается воссоздать ошибку. Раньше точно помню, что замыкал MISO на 3.3В и получал 0xFE. Допускаю: 1. тогда я где-то нокосячил; 2. сейчас использую простой проект (LTDC, SDRAM, SPIx), а тогда - куча SPI (кнопки и светодиоды на сдвиговых регистрах, цифровой микрофон, I2S-кодек), таймеры (DS18B20, импульсы тестирования усилителей), UART (GSM, console), SDIO (uSD-карта), I2C (радио RDA5807). Все это густо разбавлено DMA.
|
|
|
|
|
Jun 21 2016, 23:31
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
Цитата(ViKo @ Jun 21 2016, 18:28)  Еще бы и программный ногодрыг не работал...  Четыре провода проложены, как положено. Это хорошо. Но мало. Заметьте, у adnega все каналы SPI работают! А вы ссылаетесь на форум каких-то... неучей... Не будьте так высокомерны. Это форум поддержки ST.
|
|
|
|
|
Jun 23 2016, 10:32
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
Цитата(ViKo @ Jun 23 2016, 08:39)  Ссылку на тему на ST выдайте, please! "что-то сказал" слегка противоречит "переводчик не нужен"  Вы как следователь на допросе. Я просто уже не помню что он сказал. То, что я работаю в Канаде слегка противоречит вашим подозрениям обо мне и о переводчике. Написал он банальность: Ok, so as the -ChipSelect goes high the slave will tri-state its output. So a) make sure you keep -CS low until you have clocked in the last bit, and  you are reading the slave output on the right edge of the clock What SPI device is the slave? Мой ответ: Thank you for response. First: CS starts going high one microsecond after the last clock transaction. Second: In order to simplify the test I managed to neutralize the slave peripheral holding reset all the time. MISO output is a solid high and never changes. I read 0xFE instead of 0xFF. The same firmware operates with the same peripheral on SPI2. No problems observed. I got the same behavior on two different boards for SPI1 only. SPI2 connected to the same kind of slave (si3050 as dazy chain of 5) operates properly on both boards. Коряво конечно, моя жена считает меня необучаемым языкам, но народ понимает что я имею ввиду.
|
|
|
|
|
Jun 23 2016, 17:45
|

Местный
  
Группа: Свой
Сообщений: 270
Регистрация: 8-08-15
Из: Москва
Пользователь №: 87 901

|
Извиняюсь, что немного не в тему, но ситуация тоже с SPI. Сегодня выкопал баг: Код byte SPIRead(byte reg) { volatile short temp; temp=SPI2->DR;// Эти сделаны как заплатка. Без них получается какая-то шляпа temp=SPI2->DR; temp=SPI2->DR; CS_EN; SPI2->DR=reg|0x80; //busy=true; Это я в комментах расскажу while(!(SPI2->SR&SPI_SR_RXNE)); //busy=false; CS_DIS; temp=SPI2->DR; temp>>=8; return temp; } Короче заметил девайс подвисает периодически. Начал дебажить - зависает в while(!(SPI2->SR&SPI_SR_RXNE));. Что в итоге происходит - пока ждем, возникает прерывание системного таймера. Он сам по себе устанавливает 1 флаг в 50 герц, по которому из главного цикла опрашивается акселерометр, это единственная его задача. После обработчика возвращаемся в цикл и больше никогда из него не выходим. То есть если в нем войти в обработчик, то бит RXNE не установится. Юзал бряк busy и через if(busy) в таймере понимал, что мы попали в прерывание во время цикла. В пошаговой отладке этот бит не устанавливается, хотя в ДШ четко сказано: A read access to the SPIx_DR register must be managed by the RXNE event. This event is triggered when data is stored in RXFIFO and the threshold (defined by FRXTH bit) is reached. When RXNE is cleared, RXFIFO is considered to be empty.Или по крайней мере этот бит очень быстро сбрасывается (не понятно почему)
|
|
|
|
|
Jun 24 2016, 07:40
|

Местный
  
Группа: Свой
Сообщений: 270
Регистрация: 8-08-15
Из: Москва
Пользователь №: 87 901

|
Цитата(RadiatoR @ Jun 23 2016, 20:45)  Или по крайней мере этот бит очень быстро сбрасывается (не понятно почему) Разобрался - до сих пор не могу в голову вдолбить, что регистру пофигу кто его читает - mcu или дебаггер. После чтения дебаггером регистра (а он читается автоматически при пошаговой отладке) RXNE сбрасывался и происходило бесконечное ожидание. Дописал timeout на всякий случай. Цитата(Obam @ Jun 24 2016, 09:55)  Не флуда ради, а токмо просвещения для… какое соотношение между частотой ядра и частотой SCK, что все (ну практически все) в примерах с SPI в тупых циклах ожидают изменения флагов, а не используют \шёпотом\ прерывание? 48МГц/93кГц. Все что делает у меня прога это 50раз в сек читает датчик и выкидывает его на CAN шину. Даже заморачиваться не стал с прерываниями.
|
|
|
|
|
Jun 24 2016, 10:13
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
Я бы провел серию тестов. Вот такую функцию (сами подставьте правильное выражение для статуса и вашего busy) поставить в разные места прерывания и найти в каком месте флаг меняется. Может каким неожиданным способом флаг читается. Ну там поинтер не туда указывает и т.д.. Когда найдете место, то под лупой рассмотрите его. Тестировать так: Поставили в одно место запустили. Если подвисло в ловушке, то убираем отсюда и ставим выше по коду если подвисло в ожидании флага, то ниже. Код void trap() { if(your sign that interrupt happen in specific moment) if(RXNE != (SPI_STATUS & RXNE)) while(1) {} }
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|