Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Глобальное разрешение прерываний и SPI одновременно => сброс контроллера
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
Зверюга
Господа, открываю отдельную ветку специально для возникшей проблемы, обсуждавшейся в соседней теме про измерение длины импульса, здесь - http://electronix.ru/forum/index.php?showtopic=52057.

ПРоблема следующая - определенное сочетание некоторых строк кода вызывает постоянный ресет.

Пройденные и уже обсуждавшиеся грабли:
1. сторожевой таймер - отключен, отключался принудительно, при загрузке судя по WDTCR он отключен. Манипуляции со сторожем не влияют на ситуацию.
2. Ресет из-за проблем на входе RESET контроллера. По совету подключил резистор 4,7 к от RESET к + питания. Конденсатор не нашел, паять не стал. ПРи загрузке в регистре MCUCSR бит сброса по низкому уровню на ресет то сброшен, то установлен. ПРосьба не советовать мне копать в этом направлении ибо не зависимо от состояни этого бита работа контроллера одинакова. А при изменении кода определенным образом контроллер не сбрасывает даже при отсутствии подклчюения RESET к питанию через резистор.


Итак программа представляет собой следующее (подробнее ниже):
1 .инициализации портов D и С для использования подключенных к ним диодов в качестве маячков
2. инициализация SPI
3. отправка байта по SPI
4. глобальное разрешение прерываний

так вот если одновременно присутствуют пункты 2,3,4 происходит ресет контроллера.
Что-нибудь одно убираем - все ОК.


3 часа перелопачивал код, убирал незначащие фрагменты, в итоге получил коротенькую дефектную программу, вызывающую постоянный ресет контроллера.

Код
#include <mega32.h>
#include <delay.h>
#include <stdio.h>


#define LCD_PORT   PORTB           //
#define LCD_DDR    DDRB            //



#define LCD_RS       4
#define LCD_MOSI   5
#define LCD_MISO   6
#define LCD_SCK    7


#define  SPI2X   0  

#define  SPR0    0  
#define  SPR1    1  
#define  SPHA    2  
#define  SPOL    3  
#define  MSTR    4  
#define  DORD    5  
#define  SPE     6  
#define  SPIE    7  




void main(void)
{  

//WDTCR=0x18;         // это отключение
//WDTCR=0x00;         // сторожевого барбоса.  Не влияет на ситуацию

  DDRD=0xFF;          // здесь выводим состояние MCUCSR
  PORTD=MCUCSR;       // на подключенные к порту светодиоды.  На ресет у меня только резистор, советуемого конденсатора не подключал

  DDRC=0xFF;          // маркер старта контроллера
  PORTC=0xFF;         // если контроллер постоянно ресетит, то диоды горят постоянно
  delay_ms(500);      // через 500 мс
  DDRC=0x00;          // отключаем   - если погасло насовсем, значит ресета не происходит          

  
    

         LCD_DDR.LCD_MOSI=1;         // MOSI must be set as output for SPI  
         LCD_PORT.LCD_MOSI=1;         // MOSI must be set as output for SPI      
         LCD_PORT.LCD_SCK =0;        // set SCK low
         LCD_DDR.LCD_SCK=1;          // set SCK as output
        LCD_PORT.LCD_MISO=1;        // enable pull up of MISO to avoid floating input

// а вот здеcь интересно - можно не включать PORTB.4 (LCD_RS) - проблема появляется только тогда, когда DDR установлен в 1.
//         LCD_PORT.LCD_RS=1;          // RS=high              
        LCD_DDR.LCD_RS=1;           // RS is output

           SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR1)|(0<<SPR0);
           SPSR = (1<<SPI2X);

// ниже asm текст из функции отправляюще байт.
//АКЦЕНТИРУЮ ВАШЕ ВНИМАНИЕ:
// в данном случае передаваемому байту взяться неоткуда, это выдрано из функции, в параметры которой передавался байт.
// данный код и в представленном виде и будучи помещенным в функцию одинаково влияет на поведение контроллера.
// так что проблема возникает при самом факте отправления чего либо, а не с содержанием отправляемой информации.
// если не сокрщать программу, а использовать всю билиотеку - SPI работает нормально, что подтверждается корректной работой ЖКИ
#asm
    ld    r26,y            

   sbi 0xd,7            
    out 0xf,r26              
SPI_SEND_2:
    sbis    0xe,7          
    rjmp    SPI_SEND_2
    sbi 0x18,2

#endasm

#asm("sei"); //врубаем прерывания - и происходит ресет


    
}




ФЬЮЗЫ:

OSCCAL = CC, CB, C5, C5
BLEV = 1
BODEN = 1
SUT = 2
CKSEL = F
BLB1 = 3
BLB0 = 3
OCDEN = 1
JTAGEN = 1
CKOPT = 0
EESV = 1
BSIZ = 0
BRST = 1


В аттаче скриншот с настройками проекта в CodeVision.
ReAl
Цитата(Зверюга @ Sep 2 2008, 20:02) *
3 часа перелопачивал код, убирал незначащие фрагменты, в итоге получил коротенькую дефектную программу, вызывающую постоянный ресет контроллера.

Код
void main(void)
{  

...
#asm("sei"); //врубаем прерывания - и происходит ресет
    
}

Ну именно этот, приведённый тут код, выглядит странно. Хоть бы for(;;); перед закрывающей main() фигруной скобкой.
Куда пойдёт в CV программа после выхода из main() ?
В avr-gcc она на нулевой адрес и перейдёт.

А так - не знаю. Если при разрешении прерываний бяка - не знаю, как у CV с незадействованными в програме векторами работа идёт, но вдруг ненароком прерывание разрешается (проверьте mega32.h на правильность определения битов, может вместо какого SPR0 включается SPIE) и возникает, а обработчика нет.
Зверюга
Цитата
Куда пойдёт в CV программа после выхода из main() ?
В avr-gcc она на нулевой адрес и перейдёт.



Простите меня, но вы нелогичны)))
Вы пишите что пр отсутствии цикла for(;;) программа должна перейти на нулевой адрес. Я же писал о том что некоторые манипуляции с кодом НЕ СВЯЗАННЫЕ С ЗАЦИКЛИВАНИЕМ устраняют постоянный ресет. Тогда причем здесь зацикливание?

Справедливости ради скажу, что зацикливание раньше в прорамме было и ресет при нем был. Зацикливание убрал для упрощения кода.


Цитата
(проверьте mega32.h на правильность определения битов, может вместо какого SPR0 включается SPIE) и возникает, а обработчика нет.


Ну вот опять.... имеет смысл ваше предположения учитывая что я писал: "если не сокрщать программу, а использовать всю билиотеку - SPI работает нормально, что подтверждается корректной работой ЖКИ"?

Повнимательней пожалуйста )))
AHTOXA
Цитата(Зверюга @ Sep 2 2008, 23:52) *
Простите меня, но вы нелогичны)))
...
Я же писал о том что некоторые манипуляции с кодом НЕ СВЯЗАННЫЕ С ЗАЦИКЛИВАНИЕМ устраняют постоянный ресет. Тогда причем здесь зацикливание?
...
Ну вот опять.... имеет смысл ваше предположения учитывая что я писал:
...


Вы часом не юрист? Уж больно грамотно юлитеsmile.gif Однако тут у вас немного другая задача, надо не запутать всё до предела, и не уличить оппонентов в невнимании, а вовсе даже наоборот, всё прояснить и во всём разобратьсяsmile.gif И люди, которые пишут - не оппоненты вовсе, а хотят вам помочь (ну, кроме меня конечноsmile.gif )

По сути. Пример кривой, стало быть выводы на его основе некорректны. Отмазки типа "был цикл" - не принимаются. Надо новый пример, снова всё проверить, все эти 1, 2, 3 и 4.
Зверюга
Цитата
Вы часом не юрист?


Я судмедэксперт. В судах иногда в такие баталии с юристами приходится вступать, что приходится приспосабливаться, так что интуиция вас не подвела.

Цитата
Отмазки типа "был цикл" - не принимаются. Надо новый пример, снова всё проверить, все эти 1, 2, 3 и 4.


Так я прежде чем писать снова цикл поставил и проверил))) Общение с юристами приучило)))

В общем странная фишка получается - манипулирую с LCD_PORT.LCD_RS и LCD_DDR.LCD_RS - комментироваине этих строк решает проблему, но выключает ЖКИ. ПРичем какую-то непостижимую роль играет номер бита 4 - пересадил ножку RS на PORTA.0 - Проблема исчезла, но ЖКИ не захотел работать. Пересадил на PORTA.4 - ЖКИ заработал, но проблема появилась вновь...


Цитата
Отмазки типа "был цикл" - не принимаются.


Вы как плохие из моих коллег врачей - с чем бы к ним ни пришел - попейте анальгин, не поможет - аспирин, через неделю приходите.

Я расписал все как мог. И если я вижу, что совет противоречит тому что написано, я вправе сделать вывод, что мой пост не читали. Уж извините, я не хочу здесь накалять обстановку, но просто по опыту общения на форумах знаю, что хоть я и написал про "грабли", про сторожевой таймер, про RESET - еще не один человек в теме мне на это укажет.

Проверил еще раз с циклом - не заработало.
Что делать и кто виноват?
AHTOXA
Цитата(Зверюга @ Sep 3 2008, 01:14) *
Я судмедэксперт. В судах иногда в такие баталии с юристами приходится вступать, что приходится приспосабливаться, так что интуиция вас не подвела.


Ну тут всё же не тамsmile.gif Попроще надо.

Цитата
Вы как плохие из моих коллег врачей - с чем бы к ним ни пришел - попейте анальгин, не поможет - аспирин, через неделю приходите.


Я пока лишь попросил поточнее описать симптомы и направил на анализы. Чтоб не делать поспешных выводов. Имхо так делают как раз хорошие из ваших коллегsmile.gif

Цитата
Я расписал все как мог. И если я вижу, что совет противоречит тому что написано, я вправе сделать вывод, что мой пост не читали. Уж извините, я не хочу здесь накалять обстановку, но просто по опыту общения на форумах знаю, что хоть я и написал про "грабли", про сторожевой таймер, про RESET - еще не один человек в теме мне на это укажет.


Ну что поделать, форум - он и есть форум. Человек читает сообщение, опытный взгляд видит явный ляп - и естественно считает, что причина в этом. Мало кто читал всю предысторию, тем более, что вы вынесли обсуждение в новую тему.

Цитата
Проверил еще раз с циклом - не заработало.
Что делать и кто виноват?


Давайте сделаем такой анализ: поставьте на все прерывания в системе заглушки. Пустые обработчики. Можно в них взводить какой-нибудь флажок. Можно выводить флажок на экран. Не суть. И посмотрите, перестанет зависать или нет.

........

Кажись нашёл.
В spi_send() строчка
Код
   sbi 0xd,7


как раз и включает прерывание от SPI. 0x0D - это SPCR, бит 7 - SPIE.
Уберите её, она не нужна.
Зверюга
Цитата
sbi 0xd,7



ВЫ ГЕНИЙ! ЗАРАБОТАЛО! СПАСИБО!

Только я не пойму, строка включала прерывание, что было неправильно, но почему исход был такой грубый - ресет?
AHTOXA
Выполнение прыгало на адрес вектора (0x18), там пусто, а следом - программа. Вот она и начинала выполняться сначала. То есть, резета как такового скорее всего не было, просто рестарт. Хотя это не факт, зависит от кодов команд, которые располагаются начиная от вектора и до начала собственно программы.
Зверюга
Хм... по удалению указанной строки ЖКИ работает нормально.
Тогда ваше предположение - чего хотел добиться автор кода этой строкой?
AHTOXA
Могу только догадыватьсяsmile.gif Скорее всего, он перепутал номер бита, хотел взводить бит 6 (SPE) перед передачей и отключать его после. Так делают, когда надо использовать ноги SPI как обычные ноги между передачами. Короче, содрал откуда-то бездумно.
Кстати, подтяните ногу SS к питанию или сконфигурируйте её как выход. А то когда она вход и на ней 0, SPI перестаёт передавать (думает, что он ведомый).
ReAl
Цитата(Зверюга @ Sep 2 2008, 20:52) *
Цитата(ReAl @ Sep 2 2008, 20:40) *
А так - не знаю. Если при разрешении прерываний бяка - не знаю, как у CV с незадействованными в програме векторами работа идёт, но вдруг ненароком прерывание разрешается (проверьте mega32.h на правильность определения битов, может вместо какого SPR0 включается SPIE) и возникает, а обработчика нет.

Ну вот опять.... имеет смысл ваше предположения учитывая что я писал: "если не сокрщать программу, а использовать всю билиотеку - SPI работает нормально, что подтверждается корректной работой ЖКИ"?
Повнимательней пожалуйста )))

Цитата(AHTOXA @ Sep 2 2008, 23:16) *
Кажись нашёл.
В spi_send() строчка
Код
   sbi 0xd,7
как раз и включает прерывание от SPI. 0x0D - это SPCR, бит 7 - SPIE.
Уберите её, она не нужна.

Цитата(Зверюга @ Sep 3 2008, 06:12) *
ВЫ ГЕНИЙ! ЗАРАБОТАЛО! СПАСИБО!
Только я не пойму, строка включала прерывание, что было неправильно, но почему исход был такой грубый - ресет?

Ну и?
При всей своей невнимательности я с самого начала посоветовал присмотреться к SPIE. Правда, не думал, что ляп в самой библиотеке, ожидал описку где-то во включаемых файлах.
Так что направление поиска я указал правильно, а внимательно вычитывать код какой-то ненужной мне библиотеки от какого-то ненужного мне компилятора я и не собирался.


Цитата(Зверюга @ Sep 3 2008, 07:57) *
Тогда ваше предположение - чего хотел добиться автор кода этой строкой?
Возможно, для Вас лично будет полезнее помедитировать над тем, как и почему при отсутствии обработчика включенного прерывания программа иногда работала (и что было основанием для упрёков в мой адрес).
Может, в следующий раз вместо обвинений в невнимательности будете прислушиваться.

За сим откланиваюсь.
Зверюга
Цитата
и что было основанием для упрёков в мой адрес



Да ладно, извините меня, был неправ. Почитайте предыдущую тему - я 3 дня до красных глаз бился над этой проблемой, представил ее как мог, а тут советы попробовать то, что я уже делал. Спасибо и Вам за Ваши советы.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.