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

Доброго времени

Сформулирую вопрос так: нужно из некой "подпрограммы" вернуться только в одном случае в точку после вызова. В остальных случаях "подпрограмма" сама сделает goto к нужным меткам
вроде бы XC8 проглатывает выражение вида goto *voidptr_var, но самой voidptr_var присвоить адрес метки не могу - метка указана позже присвоения
В общем как-то непонятно, возможно, есть специальные механизмы для подобных вещей?

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


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

А вы на каком языке пишете? Вроде по синтаксису, похоже, что на Си. Но термин "подпрограмма" (не функция) говорит об ассемблере. Уж извините за придирчивость к терминам, но без разъяснений трудно понять, что вам нужно. Если это Си, то адрес метки вы взять в любом случае не можете. Предоставьте нам кусочек кода, если он на Си, то не должен сильно касаться архитектуры микроконтроллера. Здесь, вам многие смогу помочь)

 

Хотя, если там компилятор на основе GCC, то сделать это можно. Но, в любом случае, это какой-то уже хак.

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


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

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

только в одном случае в точку после вызова. В остальных случаях "подпрограмма"

Обыкновенное ветвление.

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


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

Да, пишется на Си
Есть много мест, где одна и та же вещь используется, типа такой:

temp = PORTA & PORTMASK;
do {
    etemp = PORTA & PORTMASK;
} while(temp == etemp);
    
if ((etemp&0x02)==0)  goto continue;   // SCL goes to LOW
if ((etemp&0x01)==0)  goto start_cond; // SDA goes to LOW
goto stop_cond; 

continue:
// здесь продолжаем работу

 

4 минуты назад, Plain сказал:

Обыкновенное ветвление.

да, но мест таких много, памяти мало) скорость выполнения критична
да и какой-то тайм-аут ещё вставить, чтобы PIC из прерывания вылетел, если хост "залипнет", и снова ввалился в спячку

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


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

52 минуты назад, haker_fox сказал:

Хотя, если там компилятор на основе GCC, то сделать это можно. Но, в любом случае, это какой-то уже хак.

не, так пробовал. Не видит компилятор метку - "Unable to resolve..."

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


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

2 часа назад, toweroff сказал:

Сформулирую вопрос так: нужно из некой "подпрограммы" вернуться только в одном случае в точку после вызова. В остальных случаях "подпрограмма" сама сделает goto к нужным меткам

В терминах си это называется "нелокальный переход". Воспользуйтесь гуглом. Например: https://ru.wikipedia.org/wiki/Setjmp.h

Я не уверен насчёт PIC (так как (насколько помню) стек там реализован аппаратно в виде отдельного FIFO, отдельного от остальной памяти), но в большинстве других архитектур невозможно просто так перейти изнутри одной функции в другую. Необходимо выполнить восстановление стека. Что и реализует setjmp()/longjmp().

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


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

26 минут назад, jcxz сказал:

В терминах си это называется "нелокальный переход". Воспользуйтесь гуглом. Например: https://ru.wikipedia.org/wiki/Setjmp.h

Я не уверен насчёт PIC (так как (насколько помню) стек там реализован аппаратно в виде отдельного FIFO, отдельного от остальной памяти), но в большинстве других архитектур невозможно просто так перейти изнутри одной функции в другую. Необходимо выполнить восстановление стека. Что и реализует setjmp()/longjmp().

Смотрел... Not supported :cray:

#ifndef	__SETJMP_H
#define	__SETJMP_H

#if	defined(_PIC18) || defined(__18CXX)
typedef	char jmp_buf[4];

#elif	defined(__DSPICC__)
typedef unsigned int jmp_buf[4];

#elif	defined(_PIC14E) || defined(_PIC14EX)
typedef char jmp_buf[3];

#else
#error	setjmp.h: Processor type not supported, or not defined.
#endif

#ifdef __STACK
extern __nonreentrant int		setjmp(jmp_buf);
extern __nonreentrant void	longjmp(jmp_buf, int);
#else
extern int	setjmp(jmp_buf);
extern void	longjmp(jmp_buf, int);
#endif

#endif	/* __SETJMP_H */

 

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


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

11 минут назад, toweroff сказал:

Смотрел... Not supported :cray:

Тогда только изучать архитектуру, ассемблер и реализовывать самостоятельно.

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


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

6 hours ago, toweroff said:

Сформулирую вопрос так: нужно из некой "подпрограммы" вернуться только в одном случае в точку после вызова. В остальных случаях "подпрограмма" сама сделает goto к нужным меткам

Это невозможно, даже на ассемблере. У PIC10 аппаратный стек, и если вы не сделаете ret, то на стеке останется адрес возврата, и выход из ближайшей процедуры улетит совсем не туда, куда вы ожидаете.

Сбросить стек нельзя, насколько я помню.

PS. Посмотрел в описание - у него всего 2 уровня стека :( В общем вернуться можно, но нужно учитывать, что на стеке после этого будет мусор.

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

void* address;


void sub1()
{
  
  goto *address;
}

void main()
{
  address = &&label;
  
  label:
  
}

 

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


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

Не, такие конструкции не прокатывает, пробовал

Стек - да, только call и ret. Никаких push-pop

Придётся вызывать обычную функцию с циклом, а после выхода проверять результат и прыгать. Каждый раз. А может и каждый раз делать цикл.. Посмотрю, что "дешевле"

Конструкция с вызовом функции сразу увеличила объём с 53% до 69... А ещё не реализованы нужные плюшки и запись во флешь надо сделать. Давненько я в таких жёстких рамках не был))

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


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

Уважаемый @toweroff, не в коем случае не призываю вас к революции смене микроконтроллера. Но вопрос задам: а какой смысл в pic10 с аппаратным стэком в 2020 году? Я думаю, такие крохи ставят из-за низкой цены в различные датчики или иные подобные электронные блоки, где важны габариты (посмотрел на фотку этого pic10), не нужен серьёзный функционал (типа вычисления float). Верно?

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


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

Основная задача - спать 99.9% времени, откушивая от батареи малую (нет - крохотную) копеечку. Просыпаться и отвечать по I2c когда спросят.

И да, места мало, к сожалению. Ну с трудом, думаю, tssop, скорее даже не 20

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


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

Уверен, если пересмотреть разделение программы по функциям, можно избавиться от необходимости безусловных переходов. 

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


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

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

И да, места мало, к сожалению. Ну с трудом, думаю, tssop, скорее даже не 20

EFM8 в QFN20 3*3 мм?

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


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

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

Уверен, если пересмотреть разделение программы по функциям, можно избавиться от необходимости безусловных переходов. 

Там функция-то, по сути, одна - прерывание по fall RA0 (ожидание START condition). Основной цикл main - увести в спячку. С функциями (а тем более с C-компилятором) вообще плохо, т.к. нет нормального стека с push/pop

23 минуты назад, Harbinger сказал:

EFM8 в QFN20 3*3 мм?

А вот с ними вообще не сталкивался(

Время на изучение нужно, камни подводные не пройдены... Но посмотрю, спасибо

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


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

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

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

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

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

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

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

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

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

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