Перейти к содержанию
    

dsPIC30f4012 Не доходит до главного цикла.

Доброго всем!
Нужна помощь. В программировании контроллеров не силен. Можно сказать - село не асфальтированное. Имею общее представление.
Для станка с ЧПУ понадобился сервопривод.
Ранее делал по протоколу плюс/минус 10 вольт. 
Нашел несложный на базе того же контроллера. Но, по протоколу степ/дир.
Спаял. Залил прошиву... И прослезился. Не стартовал проц от слова совсем.
Покопался в исходниках, нашел указания по конфигурации битов.
Поставил. Скомпилил и залил.
Контроллер ожил. Но зациклился. Причем не доходя до основного цикла.
Я так понимаю, что срабатывает какоето прерывание и перезапускает контроллер.
Вот привожу установку битов.
image.thumb.png.0df2ec95f48a6ef7b316521b50e1fadb.png

Вот результат запуска.
Внешняя программа коннектится по UART к MK И попадаю в цикл. Судя по сообщениям из МК, программа не доходит до основного цикла
И перезапускается. Очевидно, прерывание, потому как перезапускает проц не в одном и том же месте.
image.thumb.png.68126ba5a8198a95d8cdd2cfc5ec12db.png

Ну и привожу прогу main
и command
Там видно по printfам что она должна выводить. 
Может поможете советом или ткнете носом что поправить?
С надеждой и благодарностями

 

commands.c main.c

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

файл command.c отсутствует, а лучше приведите ссылку на источник и укажите в каком месте происходит перезапуск

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Первоисточник. https://www.vbesmens.de/en/downloadse.html
Конкретно вот этот проект https://www.vbesmens.de/images/Downloads/UPCX530PowerBoard.zip
Перезапуск происходит в разных местах (поэтому грешу на прерывание. Ватчдог вроде выключен).
 

int main(void) 
{
 int cs;
 ModeBLDC=0;
 setup_io();													// make all i/o pins go the right dir
 ModeBLDC=!((Hall1)&&(Hall2)&&(Hall3));							// switch to BLDC if one or more of the 3 hall pins are low

 setErr();														// error on
 setup_uart();													// setup the serial interface to the PC
 setup_TMR1();       											// set up 1ms timer
 IEC0bits.T1IE = 1;  											// Enable interrupts for timer 1 needed for delays in following routines	

 // 1/2 seconds startup delay 
timer_test = 5000;		
while (timer_test);

 if  (ModeBLDC) printf("BLDC Mode\r\n");
  else printf("DC Mode\r\n");

 printf("\r\nPowerup\r\ni/o,uart,timer OK\r\n");
 	
ПЕРЕЗАПУСК ПРОИСХОДИТ НА ЭТОМ ОТРЕЗКЕ обозначу волнистой линией
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 setup_pwm();													// start PWM
 set_pwm(0.0); 
 printf("pwm OK\r\n");

 init_pid();
 printf("pid OK\r\n");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 setup_encoder();    											// 16 bit quadrature encoder module setup
 printf("encoder OK\r\n");

 setup_capture();    											// 2 pins with quadrature cmd from PC
 printf("capture OK\r\n");

 // some junk for the serial channel
 printf(C_VERSION);
 printf(C_INFO1);
 printf(C_INFO2);
 printf(C_INFO3);
 

 clearErr();														// led off when init finished

 restore_setup();												    // restore config from eeprom
																	// Read array named "setupEE" from DataEEPROM and place 
																	// the result into array in RAM named, "setup" 
	
 cs = calc_cksum(sizeof(PID)/sizeof(int),(int*)&PID);	
 if ( cs != PID.cksum)
 {
  printf("No valid setup found in EEPROM, using defaults.\r\n"); // opps, no valid setup detected
  init_pid();
  clear_EE();
  save_setup();
 }
 else
 {
  printf("Using setup from eeprom.. ? for help\r\n");
  PID.error =0;	/* to avoid some bad bugs */
  PID.output = 0;
  PID.command = 0;
  PID.feedback = 0;
  print_tuning();
 }

 new_cmd = last_cmd = new_fb = last_fb = 0;
 set_pwm( 0.0 );
												// make sure we dont move on enabling
 cmd_posn = POSCNT;								// make 16bit incr registers match
 PID.feedback = PID.command = 0L;				// make 32 bit counter match
 new_cmd = last_cmd = new_fb = last_fb = 0;
 PID.error_i = 0.0;								// reset integrator
 PID.enable = 0;

 while (1)
 {
												// look for serial cmds
												// doing this while svo is enabled will cause bumps in servo loop
												// because of serial i/o time ( unless we get smart and move svo loop
												// into an isr )
  if (rxrdy) process_serial_buffer(); 
  test_handle_print();
		
  if(error_flags & 0b00000001)					// "maxerror exceeded" error
  {
   setErr();
   printf("MAXERROR exceeded!\r\n");
  } 
 }
 return 0;
}

И есть еще одно место в модуле commands.c
 

void print_tuning(void)
{
    // __asm__ volatile ("DISI #0x3FFF");				
	printf("\rCurrent Settings:\r\n");
  Из ВСЕГО СПИСКА ВЫВОДИТСЯ ТОЛЬКО ЭТА СТРОКА (см. принт скрин выше)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	printf("servo enabled = %d\r\n",	PID.enable);
	printf("(p) = %f\r\n",		(double)PID.pgain);
	printf("(i) = %f\r\n",		(double)PID.igain);
	printf("(d) = %f\r\n",		(double)PID.dgain);
	printf("FF(0) = %f\r\n",	(double)PID.ff0gain);
	printf("FF(1) = %f\r\n",	(double)PID.ff1gain);
    printf("dead(b)and = %f\r\n",(double)PID.deadband);
	printf("(m)ax Output = %.2f\r\n",(double)PID.maxoutput);
	printf("(f)ault error = %f\r\n", (double)PID.maxerror);
	printf("(x)pc cmd multiplier = %hu\r\n", PID.multiplier);
    printf("(t)icks per servo cycle= %hu\r\n",PID.ticksperservo);
    printf("(h)all timeout= %lu\r\n",PID.HallTimeout);
    printf("char(g)e elcos= %u\r\n",PID.DoChargeElcos);
    printf("phase (a)dvance= %u\r\n",PID.PhaseAdvance);
    printf("SVM (c)ycle= %u\r\n",PID.SVMCycle);       
    // DISICNT = 0; 
}

Т.е. из всех операторов printf идущих подряд выполняется только один. Иногда два... 
Что то похоже перезапускает проц. (((

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, newhumanoid сказал:

Что то похоже перезапускает проц. (((

Если в разных местах, то: питание (его просадки/помехи), WDT (внешний и внутренний), ...

 

PS: По коду - жесть какая... на дохлом ПИКе и double!  :shok:  типичный признак говнокода....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Выкиньте этот говнокод. Нерабочий он.

Во-первых: Изначально (на старте ПО) указатель, по которому пишутся принимаемые UART байты (rxbuffptr) не инициализирован. И, после инита UART, входящие байты (не равные '\r' и '\n') начнут писаться с адреса 0 памяти и далее - с инкрементом, снося по ходу дела всё содержимое ОЗУ, которое попадётся по пути. Инит rxbuffptr делается только при приёме кода '\r'. Так что - чтобы не портило ОЗУ, нужно чтобы первым символом пришедшим в UART после старта ПО был код '\r' (13). В этом случае повезёт. У автора сего поделия видимо всегда первым шёл '\r', а у вас - что-то другое (может байты мусора).

Во-вторых: "парсер" команд и ISR приёма по UART.RX никак не синхронизированы между собой. Т.е. - после приёма '\r' в ISR UART должна запуститься обработка принятой строки в process_serial_buffer(). Но при этом ISR UART.RX продолжает работать. И если сразу после '\r' начнут поступать новые байты (в то время как process_serial_buffer() ещё не успел обработать предыдущие), то содержимое предыдущей принятой строки будет порушено (новые символы приклеятся в конец предыдущей строки).

В-третьих: reset_buffer() в после завершения обработки некоторых команд вызывается дважды. А это значит, что в некоторых случаях, если не повезёт, то начало следующей принимаемой UART строки команды может быть потеряно (вторым вызовом reset_buffer()).

В-четвёртых: нигде нет ни одного volatile. При взаимодействии основной задачи и ISR. А значит при включении оптимизации, добавятся новые "сюрпризы". Такое поделие может ещё более-менее как-то "работать" только с полностью отключенной оптимизацией кода в компиляторе.

 

Просмотрел по диагонали. Первое что попалось на глаза. Дальше смотреть даже не стал. И так всё ясно.

 

PS: Вобщем - этому говнокоду место только в помойке.  :unknw:

PPS: Первое впечатление (от наличия double) полностью подтвердилось...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

29 minutes ago, jcxz said:

PS: По коду - жесть какая... на дохлом ПИКе и double!  :shok:  типичный признак говнокода....

Ну я писал, что не силен в программинге МК. Немного имею представление. Могу только повторить.
Вот начал эксперименты.
взял голій процик подпаял питание, землю, подтянул три ноги к питанию, которіе узнают тип движка, ну и Tx RX PGd PGC...
Ставлю в разные части кода printf и смотрю куда попадает....
Обнаружилась другая бяка.... Уже третий процик после десятка перепрошивок уходит в кирпич (((
Вот такая картинка 
image.thumb.png.d67c76a8187a3ef336f7b52683d51734.png

Чего это они?
Пользуюсь ПИККИТ2 Лайт. Питание на проц не подавал, только от программатора....(((

image.thumb.png.f006da15907dc44bb14ae5a6dd7d5bbd.pngВот так припаяно
 

9 minutes ago, jcxz said:

Выкиньте этот говнокод. Нерабочий он.

Просмотрел по диагонали. Первое что попалось на глаза. Дальше смотреть даже не стал. И так всё ясно.

 

PS: Вобщем - этому говнокоду место только в помойке.  :unknw:

Спасибо огромное что уделили время.
Мда.... Печально... Ну навроде как этот код делался на базе аналогичного серводрайвера, которыые у меня успешно эксплуатируются уже много лет.
различие у них в том, что предыдущий драйвер использовал управление движком по протоколу плюс/минус 10 вольт и только коллекторники и требовал стороннего усилителя (т.е. силовая часть была от стороннего производителя американские АМС). Раньше у китайсав я купил их не дорого, ныне же они только на ИБЭе и цены далеко не гуманные плюс доставка, посему искал другое решение.
А текущий драйвер имеет силовуху на борту и управляется по степ/дир. 

Я сравнивал тексты.  Отличаются тем что текущий умеет крутить бесколлекторники.
Головная прога отличается.
Ну а код по УАРТУ по сути один в один содран. 
Еще раз спасибо за потраченное время. :negative:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 9/19/2021 at 11:09 AM, jcxz said:

начнут писаться с адреса 0 памяти и далее - с инкрементом, снося по ходу дела всё содержимое ОЗУ, которое попадётся по пути.

И что может таким образом превратить процик в кирпич?
Уже 4-й кирпич... (((
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 минут назад, aerobus сказал:

И что может таким образом превратить процик в кирпич?

А почему решили что "кирпич"?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

image.thumb.png.00693761f9692041cd130e799356546a.png
Может и не прав. Ну Помимо этого сообщения МПЛАБа ПИККИТ тоже не признает его.

 

36 minutes ago, jcxz said:

почему решили что "кирпич"?

Ну и вот таким образом проц подключаю к программатору. В такой обвязке. Внешнего питания не подаю.
image.thumb.png.9ec017ad65f8bd9af0b16707ae02963c.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 9/19/2021 at 11:09 AM, jcxz said:

Во-первых: Изначально (на старте ПО) указатель, по которому пишутся принимаемые UART байты (rxbuffptr) не инициализирован.

rxbuffptr инициализирован в void setup_uart( void )

On 9/19/2021 at 11:09 AM, jcxz said:

В-четвёртых: нигде нет ни одного volatile. 

// serial.c

volatile char rxbuff[30];		// global rx buffer for serial data
volatile char *rxbuffptr;		// local input ptr for storing data
volatile short int rxrdy;		// flag to indicate a line of data is available in 
On 9/19/2021 at 11:09 AM, jcxz said:

PPS: Первое впечатление (от наличия double) полностью подтвердилось...

И чем плох double, если вычисление не ограничивают (не ухудшают) работоспособность ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 minutes ago, dimka76 said:

И чем плох double

Дело в том, что тут без дробных значей не обойтись.
ПИД может быть и в тысячных, а то и десятитысячных единицах.... (((

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

// Initialization of timer 1 as a periodic interrupt 
// each 0.1 ms (10khz)
void setup_TMR1(void)
{
printf("\r\n\555555555555\r\n");
 T1CON = 0x0020;						// internal Tcy/64 clock
 TMR1 = 0;
 #define PR1PRESET  (FCY/64/10000)
 PR1 = PR1PRESET;						// 0.1 ms interrupts (100us)
 T1CONbits.TON = 1;						// turn on timer 1 
 _T1IP = 6;
}

Вот вставил в таймер строчку принт...
И натыкал в начале строк \r\n\
Вот что получаю при коннектк

23:24:52  
23:24:52  
23:24:52  m555555555
23:24:52  
23:24:52  
23:24:52  
23:24:52  servo-enabled~~~~
23:24:52  
23:24:52  >
23:24:52  
23:24:52  m555555555
23:24:52  
23:24:52  
23:24:52  
23:24:52  servo-enabled~~~~
23:24:52  
23:24:53  >
23:24:53  
23:24:53  m555555555
23:24:53  
23:24:53  
23:24:53  
23:24:53  servo-enabled~~~~
23:24:53  
23:24:53  >
23:24:53  
23:24:53  m555555555
23:24:53  
23:24:53  
23:24:53  
23:24:53  m555555555
23:24:53  
23:24:53  
23:24:53  
23:24:53  servo-enabled~~~~
23:24:53  
23:24:53  >
23:24:53  
23:24:53  DC Mode
23:24:53  
23:24:53  
23:24:53  
23:24:53  Powerup
23:24:53  
23:24:53  i/o,uart,timer OK
23:24:53  
23:24:53  
23:24:53  
23:24:53  m555555555
23:24:53  
23:24:53  
23:24:53  
23:24:53  servo-enabled~~~~
23:24:53  
23:24:54  >
23:24:54  
23:24:54  m555555555
23:24:54  
23:24:54  
23:24:54  
23:24:54  m555555555
23:24:54  
23:24:54  
23:24:54  
23:24:54  m555555555
23:24:54  
23:24:54  
23:24:54  
23:24:54  servo-enabled~~~~
23:24:54  
23:24:55  >
23:24:55  
23:24:55  m555555555
23:24:55  
23:24:55  
23:24:55  
23:24:55  servo-enabled~~~~
23:24:55  
23:24:55  >
23:24:55  
23:24:55  m555555555
23:24:55  
23:24:55  
23:24:55  
23:24:55  servo-enabled~~~~
23:24:55  
23:24:56  >
23:24:56  
23:24:56  DC Mode
23:24:56  
23:24:56  
23:24:56  
23:24:56  Powerup
23:24:56  
23:24:56  i/o,uart,timer OK
23:24:56  
23:24:56  
23:24:56  
23:24:56  m555555555
23:24:56  
23:24:56  
23:24:56  
23:24:56  m555555555
23:24:56  
23:24:56  
23:24:56  
23:24:56  servo-enabled~~~~
23:24:56  
23:24:56  ю
23:24:56  
23:24:56  m555555555
23:24:56  
23:24:56  
23:24:56  
23:24:56  servo-enabled~~~~
23:24:56  
23:24:57  >
23:24:57  
23:24:57  m555555555
23:24:57  
23:24:57  
23:24:57  
23:24:57  servo-enabled~~~~
23:24:57  
23:24:57  >
23:24:57  
23:24:57  DC Mode
23:24:57  
23:24:57  
23:24:57  
23:24:57  Powerup
23:24:57  
23:24:57  i/o,uart,timer OK
23:24:57  
23:24:57  
23:24:57  
23:24:57  m555555555
23:24:57  
23:24:57  
23:24:57  
23:24:57  servo-enabled~~~~
23:24:57  
23:24:58  >
23:24:58  
23:24:58  DC Mode
23:24:58  
23:24:58  
23:24:58  
23:24:58  Powerup
23:24:58  
23:24:58  i/o,uart,timer OK
23:24:58  
23:24:58  
23:24:58  
23:24:58  m555555555
23:24:58  
23:24:58  
23:24:58  
23:24:58  servo-enabled~~~~
23:24:58  
23:24:58  >
23:24:58  
23:24:58  DC Mode
23:24:58  
23:24:58  
23:24:58  
23:24:58  Powerup
23:24:58  
23:24:58  i/o,uart,timer OK
23:24:58  
23:24:59  
23:24:59  
23:24:59  m555555555
23:24:59  
23:24:59  
23:24:59  
23:24:59  servo-enabled~~~~
23:24:59  

Гдето перезапускается таймер?

Изменено пользователем aerobus

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

47 минут назад, dimka76 сказал:

rxbuffptr инициализирован в void setup_uart( void )

Ок, смотрел по диагонали.

Там и других чудес хватает, кроме описанных. Вот ещё - putchar() внутри ISR?! Вызов блокирующей функции внутри ISR? Особенно если учесть, что в основном цикле она тоже вызывается и если в МК нет FIFO, то высока вероятность подвисания внутри ISR на некоторое время.

Да и непонятно как она реализована (видимо библиотечная), но автор ничтоже сумняшеся вызывает её и из ISR и из основного цикла (вместе с кучей printf()), ничуть не задумываясь - допускает ли она такое?

Кстати - сейчас только заметил: из другого ISR у автора аж printf("servo-enabled\r\n>"); вызывается!! :shok:  Как оно вообще как-то работало?

 

Цитата

И чем плох double, если вычисление не ограничивают (не ухудшают) работоспособность ?

Так её, работоспособности, то и нет. Как выяснил ТС.

И здесь вроде реалтайм управление какими-то процессами, на МК вроде как не имеющем аппаратной поддержки float/double.

Причём опять-же заметьте - эти операции с плавучкой используются и в ISR-ах и в основном цикле одновременно. Автор в ISR даже операции с double делает!   :shok:

И у меня что-то нет уверенности, что библиотека эмуляции плавающей точки на этом МК реентерабельна.

43 минуты назад, aerobus сказал:

Дело в том, что тут без дробных значей не обойтись.

И что? Для "дробных значений" не нужны ни double ни float.

1 час назад, aerobus сказал:

Ну и вот таким образом проц подключаю к программатору. В такой обвязке. Внешнего питания не подаю.

Если вы вывод "получился кирпич" сделали из того, что "не коннектится программатор/эмулятор", то "неконнектиться" он может по той причине например, что прошивка МК циклически пересбрасывается сразу после старта. Чтобы вывести из такого состояния, обычно boot-пины МК переводят в состояние, запрещающее запуск кода из флешь. И в таком состоянии подключаются эмулятором/программатором.

Также прошивка сразу после старта может переназначать ноги МК, используемые эмулятором. Лечится так же.

Могут быть и другие причины. Эти причины - из опыта с другими МК, в PIC-ах я не силён, но вполне может быть то же самое. Читайте мануал на ваш МК.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 hours ago, jcxz said:

Если вы вывод "получился кирпич" сделали из того, что "не коннектится программатор/эмулятор", то "неконнектиться" он может по той причине например, что прошивка МК циклически пересбрасывается сразу после старта. Чтобы вывести из такого состояния, обычно boot-пины МК переводят в состояние, запрещающее запуск кода из флешь. И в таком состоянии подключаются эмулятором/программатором.

Также прошивка сразу после старта может переназначать ноги МК, используемые эмулятором. Лечится так же.

Могут быть и другие причины. Эти причины - из опыта с другими МК, в PIC-ах я не силён, но вполне может быть то же самое. Читайте мануал на ваш МК.

Здесь нет BOOT пина. Вход в режим программирования осуществляется по ноже RESET, которая програмно не переназначается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

52 minutes ago, dimka76 said:

Здесь нет BOOT пина. Вход в режим программирования осуществляется по ноже RESET, которая програмно не переназначается.

Т.е. - кирпич? (((

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...