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

Чтение внутренних регистров STM32

В стареньком ADS 1.2 можно было в функции С делать вставку inline asm ссылкой сразу на внутренние регистры r0-r15. Столкнулся в Кеил, что предыдущие inline asm не компилится. А вот что нашел в доках

"The inline assembler provides no direct access to the physical registers of an ARM processor. If an ARM register name is used as an operand in an inline assembler instruction it becomes a reference to a variable of the same name, and not the physical ARM register."

Есть ли способ чтения внутренних регистров, возможно средствами cmsis, или нужно создавать asm раздел и увязывать?

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


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

Есть ли способ чтения внутренних регистров, возможно средствами cmsis, или нужно создавать asm раздел и увязывать?

Я бы переписал существующий код так, чтобы вообще не приходилось лазить во внутренние регистры проца,

ибо рано или поздно эта "самодеятельность" еще проявит себя, причем, самым неожиданным способом :smile3046:

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


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

Я бы переписал существующий код так, чтобы вообще не приходилось лазить во внутренние регистры проца, ибо рано или поздно эта "самодеятельность" еще проявит себя, причем, самым пакостным способом, какой только можно себе вообразить :smile3046:
А если это планировщик задач? :rolleyes:

 

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


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

А если это планировщик задач? :rolleyes:

Планировщик прекрасно целиком пишется на голом C.

Вот переключение контекста нужно писать на asm (или на C c asm вставками целиком функций), но эти "порты" можно выдрать с любой годной оси (под KEIL или под нужную среду)

и переписать их под себя, коли так уже нужна самодельная ось.

Как-то помню возился и делал сам порт под Cortex-M0+, имея на руках тока порт под M3.

Мартышкин труд, промудохался помню много, потом открыл примеры других осей под M0 и дело пошло быстрее :)

 

 

Вот пример (кусок С-файла):

 

__asm void SVC_Handler (void) 
{
movs 	R0, #4
mov		R1, LR
tst 	R0, R1
beq		msp_stacked

psp_stacked
mrs	 R0,PSP						// Read PSP
b		done

msp_stacked
mrs	 R0,MSP						// Read MSP

done
ldr	 R1,[R0,#24]					// Read Saved PC from Stack
subs	R1,R1,#2					// Point to SVC Instruction
ldrb	R1,[R1]				 	// Load SVC index
cmp	 R1,#0
beq		svc_0						// SVC0
cmp	 R1,#1
beq		svc_1						// SVC1
cmp	 R1,#2
beq		svc_2						// SVC2

svc_0
ldr		R0, =__cpp(&tn_start_first_task)
bx		R0

svc_1
ldr		R0, =__cpp(&tn_tick_int_processing)
bx		R0

svc_2
ldr		R0, =__cpp(&tn_timer)
bx		R0

ALIGN
}

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

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


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

Я бы переписал существующий код так, чтобы вообще не приходилось лазить во внутренние регистры проца,

ибо рано или поздно эта "самодеятельность" еще проявит себя, причем, самым неожиданным способом :smile3046:

+много.

Вообще не понимаю, каким может быть код, якобы написанный на Си, и лезущий в регистры. Наверное, минное поле. Одно неосторожное движение - и вы отец :laughing:

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


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

Единственное, для чего мне это понадобилось, это скинуть дамп регистров при возникновении Fault.

Пришлось написать вставку на ASM для копирования регистров в память (структуру). Остальная работа на C.

 

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


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

Вот переключение контекста нужно писать на asm...
Я именно об этом и подразумевал под планировщиком.

 

 

...это скинуть дамп регистров при возникновении Fault...
Ну вот - человеку как раз нужен контекст.

 

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


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

Единственное, для чего мне это понадобилось, это скинуть дамп регистров при возникновении Fault.

Пришлось написать вставку на ASM для копирования регистров в память (структуру). Остальная работа на C.

Зачем копировать? Там уже все в стеке (правда, нужно определить правильный стек).

	.global	HardFaultException
.extern print_fault
HardFaultException:
mov	r0, sp
push	{lr}
bl	print_fault
pop	{pc}

void print_fault(sFAULT	*fault)
{
con_str("FAULT:\n\r");
con_str("r0   = "); con_dword(fault->r0);	con_str(", ");
con_str("r1   = "); con_dword(fault->r1);	con_str(", ");
con_str("r2   = "); con_dword(fault->r2);	con_str(", ");
con_str("r3   = "); con_dword(fault->r3);	con_str("\n\r");
con_str("r12  = "); con_dword(fault->r12);	con_str(", ");
con_str("lr   = "); con_dword(fault->lr);	con_str(", ");
con_str("pc   = "); con_dword(fault->pc);	con_str(", ");
con_str("xpsr = "); con_dword(fault->xpsr);	con_str("\n\r");
con_start();
}

typedef struct sFAULT
{
DWORD		r0;				//!< Регистр R0
DWORD		r1;				//!< Регистр R1
DWORD		r2;				//!< Регистр R2
DWORD		r3;				//!< Регистр R3
DWORD		r12;				//!< Регистр R12
DWORD		lr;				//!< Регистр LR
DWORD		pc;				//!< Регистр PC
DWORD		xpsr;				//!< Регистр XPSR
} sFAULT;

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


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

ИМХО - лучше всего сделать отдельный ассемблерный файл. Если кейловский ассемблер поддерживает директивы условной компиляции - вообще прекрасно. Можно сделать этот файл поддерживаемым несколькими вариантами ARM-платформы.

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


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

Всем Спасибо за комментарии. Регистры были необходимы для обработки Fault исключения.

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


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

А R4-R11 где?

Реально, по значениям LR, PC, R0-R4 в подавляющем большинстве случаев можно найти причину фэйла.

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

Меня больше интересует кто как обрабатывает это исключение?

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


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

Меня больше интересует кто как обрабатывает это исключение?

У меня алгоритм такой:

Исключение -> запись контекста исключения в RAM -> перезапуск -> сохранение контекста на внешнем носителе или передача на отладочный сервер -> возобновление работы

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


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

У меня алгоритм такой:

Исключение -> запись контекста исключения в RAM -> перезапуск -> сохранение контекста на внешнем носителе или передача на отладочный сервер -> возобновление работы

А на практике сильно помогает найти проблему? Какая самая частая проблема?

В моем случае только явная ошибка в коде (выход за границу массива, порча указателя, неинициализированные объекты, глючная библиотека и т.п.).

На Cortex-M0 добавляется невыровненный доступ.

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


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

А на практике сильно помогает найти проблему? Какая самая частая проблема?

Hard Fault - дело вообще не частое. Если возникает в процессе отладки ПО в лабораторных условиях,

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

Так как я пользуюсь только встроенными средствами диагностики и отладки, то даже и вопрос не

стоит о необходимости обработчика - других средств все равно нет.

 

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

помимо регистров изучать и содержимое стека.

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


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

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

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

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

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

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

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

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

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

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