Пытаюсь понять, как *ramVectorTable попадает в ramVectorTable[ ]

Я пытаюсь понять, что на самом деле делает этот код. В частности, меня больше всего смущает часть после объявления и инициализации указателя ramVectorTable.

Речь идет о функции, которая устанавливает вектор прерывания указанного номера системного прерывания. Это для PsoC 5 кипариса с ARM Cortex M3, если это как-то поможет.

#define CY_INT_VECT_TABLE ((cyisraddress **) 0xe000ed08u)


typedef void (* cyisraddress)(void);


cyisraddress CyIntSetSysVector(uint8 number, cyisraddress address)
    {
        cyisraddress oldIsr;
        cyisraddress *ramVectorTable = *CY_INT_VECT_TABLE;

 /* Save old Interrupt service routine. */
        oldIsr = ramVectorTable[number & CY_INT_SYS_NUMBER_MASK];

        /* Set new Interrupt service routine. */
        ramVectorTable[number & CY_INT_SYS_NUMBER_MASK] = address;

        return (oldIsr);
    }


person Sava Krstović    schedule 25.05.2019    source источник


Ответы (2)


Это можно понять следующим образом:

cyisraddress — это указатель на функцию (указатель на функцию). Здесь она имеет вид функции, не принимающей аргументов (void) и ничего не возвращающей (void). Поскольку это на ARM Cortex-M3, указатель должен быть 4-байтовым значением, например. 0x20010004. Это 4-байтовое значение является расположением функции в памяти, т. е. адресом ее первой инструкции. Здесь oldIsr и address указывают на существующую и новую ISR (процедуру обслуживания прерываний) соответственно.

В этой строке указано, что #define CY_INT_VECT_TABLE ((cyisraddress **) 0xe000ed08u), 0xe000ed08u имеют тип cyisraddress **, что означает указатель на указатель на указатель на функцию. Обратите внимание, что 0xe000ed08u — это адрес регистра VTOR (регистр смещения векторной таблицы), в котором хранится смещение базового адреса векторной таблицы от адреса памяти 0x00000000 (ссылка)

Когда они используют *CY_INT_VECT_TABLE, это означает значение, хранящееся по адресу 0xe000ed08, который фактически является адресом векторной таблицы. Это значение имеет тип указатель на указатель функции.

Теперь самое интересное. Для cyisraddress *ramVectorTable типом ramVectorTable является указатель на указатель функции. При дальнейшем чтении кода вы заметите, что они используют ramVectorTable в качестве массива, что похоже на эту более простую версию:

int a[10];

Затем вы можете использовать a[i] (a как массив целых чисел) или *(a+i) (a как указатель на целое число) для доступа к элементам массива.

Следовательно, ramVectorTable можно использовать как массив указателей на функции, таким образом, ramVectorTable[number & CY_INT_SYS_NUMBER_MASK] — это просто *(ramVectorTable + number & CY_INT_SYS_NUMBER_MASK), это значение имеет тип cyisraddress (указатель на функцию).

Наконец, векторную таблицу можно рассматривать как массив указателей на функции, поэтому ramVectorTable — это просто массив указателей на ISR.

person DinhQC    schedule 12.06.2019
comment
Большое спасибо за столь подробное объяснение. Часть с массивами и указателями я понял, прочитав об этом в книге «Язык программирования C» от ​​Кернигана и Ритчи. Там сказано, что указатели можно использовать с индексом, например, если pa — это указатель, pa[i] идентично *(pa + i), поэтому арифметика указателя с ramVectorTable в тот момент была ясна. Но часть с разыменованием до сих пор меня смущала. - person Sava Krstović; 16.06.2019

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

Где-то в коде таблица, вероятно, размещена в памяти и выровнена по 0x200. Другая часть кода изменяет значение регистра VTOR на адрес этой таблицы.

person 0___________    schedule 25.05.2019
comment
какой-нибудь комментарий бесшумный двтер? - person 0___________; 25.05.2019
comment
Я оставил предложенное редактирование, поэтому я могу отменить это. Пожалуйста, просмотрите. - person S.S. Anne; 25.05.2019
comment
@P__J__ Прежде всего, спасибо за ответ. Я просто пытался понять, что происходит с C-кодом. Я постараюсь быть более точным. Адрес 0xe000ed08u был приведен к (cyisradress **), который будет двойным указателем типа cyisraddress. В функции CyIntSetSysVector указатель ramVectorTable указывает на *CY_INT_VECT_TABLE, который должен быть тем, что хранится по этому адресу, и это должен быть указатель на указатель, и вот здесь я начинаю путаться. - person Sava Krstović; 26.05.2019
comment
Часть, где oldIsr = ramVectorTable[number & CY_INT_SYS_NUMBER_MASK]; должно означать, что ramVectorTable представляет собой массив из cyisraddress элементов, тоже не могу понять. Я также должен подчеркнуть, что я не так хорош в C, поэтому я надеюсь, что это вас всех не беспокоит. - person Sava Krstović; 26.05.2019