Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помогите разобраться с указателями
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Harvester
Добрый день.
Имеется следующий код (Cortex-M3)
Код
static Process prlist[2];
...
uint32_t *p = (uint32_t*)0x10000000;
prlist[0].context.sp = *p;
...
void _proc_stack_init(int id)
{
    _proc_stack_push(&prlist[id].context.sp, 0x01000000);
    _proc_stack_push(&prlist[id].context.sp, 0);
    _proc_stack_push(&prlist[id].context.sp, 0);
}

Который вызывает ассемблерную функцию
Код
_proc_stack_push:
    /* R0 - stack, R1 - value */
    push  {r2}
    ldr   r2, [r0]  // Грузим в R2 содержимое по адресу [R0]
    stmdb r2!,{r1}  // Сохраняем по адресу в R2 с преддекрементом содержимое R1, в R2 записывается новое значение
    str   r2, [r0]  // Сохраняем R2 по адресу [R0]
    pop   {r2}
    bx    lr

Хочу переписать все это на чистом Си, но что-то не получается.
Код
void _proc_stack_init(int id)
{
    uint32_t *sp_ptr = &prlist[id].context.sp;

    *--sp_ptr = 0x01000000;
    *--sp_ptr = 0;
    *--sp_ptr = 0;
}

Такое ощущение, что здесь нужно использовать двойной указатель, но вот как - ума не приложу. В общем, заблудился в трех соснах.
Подскажите, пожалуйста
aaarrr
Код
uint32_t *sp_ptr = &prlist[id].context.sp;

& лишний
Harvester
Цитата(aaarrr @ Mar 25 2016, 17:53) *
...
& лишний

Все равно что-то не то получается. В исходном варианте функция _proc_stack_push() изменяет значение переданного ей указателя, а в новом варианте, судя по листингу, ничего похожего нет:
Код
_proc_stack_init:
  ldr    r3, .L20          
  add    r0, r3, r0, lsl #4
  ldr    r3, [r0, #12]    
  mov    r2, #16777216    
  str    r2, [r3, #-4]    
  movs   r2, #0          
  str    r2, [r3, #-8]    
  str    r2, [r3, #-12]    
  bx     lr
aaarrr
Можно менять указатель, а можно использовать смещение. Компилятор выбрал последний вариант.
Harvester
Цитата(aaarrr @ Mar 25 2016, 21:47) *
Можно менять указатель, а можно использовать смещение. Компилятор выбрал последний вариант.

Но мне-то нужно и сам указатель менять.
Кажется дошло - добавил в конце
Код
prlist[id].context.sp = (uint32_t)sp_ptr;

Теперь результат похож на правду:
Код
ldr    r3, .L20          
mov    r2, #16777216    
add    r0, r3, r0, lsl #4
ldr    r3, [r0, #12]    
str    r2, [r3, #-4]    
movs    r2, #0          
str    r2, [r3, #-8]    
str    r2, [r3, #-12]!  
str    r3, [r0, #12]    ; <- финальное значение r3 пишется обратно
bx    lr
gosha-z
Какой-то взрыв мозга. А декремент-то зачем тут предполагается???
Harvester
Цитата(gosha-z @ Mar 29 2016, 21:41) *
Какой-то взрыв мозга. А декремент-то зачем тут предполагается???

Да там весь код - взрыв мозга. Такое вот наследство досталось. laughing.gif
А конкретно этот фрагмент подготавливает стековый фрейм (реально там 8 значений), который в прерывании подставляется вместо штатного. В результате возврат из прерывания происходит не в место прерывания, а на специальную функцию. Т.е. своеобразный аналог SVI-прерывания для вызова из других прерываний. wacko.gif
jcxz
Цитата(Harvester @ Mar 30 2016, 13:19) *
А конкретно этот фрагмент подготавливает стековый фрейм (реально там 8 значений), который в прерывании подставляется вместо штатного. В результате возврат из прерывания происходит не в место прерывания, а на специальную функцию. Т.е. своеобразный аналог SVI-прерывания для вызова из других прерываний. wacko.gif

Вполне себе штатный метод переключения контекстов задач в любой ОС на Cortex-M. Делается обычно внутри ISR PendSV. Изначально такой стековый фрейм создаётся при создании задачи (+остальные регистры), а в ISR PendSV делается переключение с одного стекового фрейма на другой. Остальные регистры контекста перегружаются программно.
Ваша часть кода как раз похожа на часть кода создания новой задачи в ОС (создание стекового фрейма).
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.