|
STM32 >> STR R1, [R0] >> сохраняется не корректно |
|
|
|
Jul 20 2012, 03:15
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Буэнос утрас, амигас!  STM32F103RC + IAR 6.30 + J-LINK Использую SPI1, через пины PB3, PB4 и PB5. Основная функция PB3, это JTDO. А основная функция PB4, это NJTRST. Обе мне не нужны, поскольку работаю через Serial Wire. Что бы вывести на эти ноги сигналы SPI1, конфигурирую их как альтернативные и делаю remap: Код McuPinInit( BSP_PIN_ISM_CSn, MCU_PIN_MODE_OUT_GP_PP_10MHZ ); McuPinInit( BSP_PIN_ISM_SCK, MCU_PIN_MODE_OUT_AF_PP_10MHZ ); McuPinInit( BSP_PIN_ISM_SI, MCU_PIN_MODE_OUT_AF_PP_10MHZ ); McuPinInit( BSP_PIN_ISM_SO, MCU_PIN_MODE_OUT_AF_PP_10MHZ ); McuPinInit( BSP_PIN_ISM_GDO2, MCU_PIN_MODE_INP_FLOATING ); McuPinInit( BSP_PIN_ISM_GDO0, MCU_PIN_MODE_INP_FLOATING );
McuPioRemap( MCU_PIO_REMAP_SPI1_ENABLE ); //McuPioRemap( MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_EN ); McuPioRemap( MCU_PIO_REMAP_SWJ_CFG_FULL_WITHOUT_NJTRST ); По конфигурации проблем нет, клок на GPIOx и AFIO включается в McuPinInit(). А вот с remap творится чертовщина. Ниже текст текущего варианта McuPioRemap(). Лишнее покоцал, но суть и так понятна: CODE typedef enum MCU_PIO_REMAP_e { MCU_PIO_REMAP_SWJ_CFG_FULL, MCU_PIO_REMAP_SWJ_CFG_FULL_WITHOUT_NJTRST, MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_EN, MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_DIS, ... MCU_PIO_REMAP_I2C1_DISABLE, MCU_PIO_REMAP_I2C1_ENABLE, MCU_PIO_REMAP_SPI1_DISABLE, MCU_PIO_REMAP_SPI1_ENABLE } MCU_PIO_REMAP;
//////////////////////////////////////////////////////////////////////////////// void McuPioRemap( MCU_PIO_REMAP Remap ) { switch( Remap ) { case MCU_PIO_REMAP_SWJ_CFG_FULL: AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_0; AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_1; AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_2; break;
case MCU_PIO_REMAP_SWJ_CFG_FULL_WITHOUT_NJTRST: AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_0; AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_1; AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_2; break;
case MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_EN: AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_0; AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_1; AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_2; break;
case MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_DIS: AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_0; AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_1; AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_2; break;
...
case MCU_PIO_REMAP_I2C1_DISABLE: AFIO->MAPR &= ~AFIO_MAPR_I2C1_REMAP; break;
case MCU_PIO_REMAP_I2C1_ENABLE: AFIO->MAPR |= AFIO_MAPR_I2C1_REMAP; break;
case MCU_PIO_REMAP_SPI1_DISABLE: AFIO->MAPR &= ~AFIO_MAPR_SPI1_REMAP; break;
case MCU_PIO_REMAP_SPI1_ENABLE: AFIO->MAPR |= AFIO_MAPR_SPI1_REMAP; break;
default: break; } } Сначала у меня перестал откликаться SW, пришлось временно закомментить remap. Подумал, что либо сам ошибся, либо в <stm32f10x.h> косячёк в #define. Полез смотреть по шагам. Вижу вполне корректный ассемблер: Код AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_0; ??McuPioRemap_4: 0x8000d40: 0xf8df 0x03f8 LDR.W R0, ??DataTable4_6; AFIO_MAPR 0x8000d44: 0x6801 LDR R1, [R0] 0x8000d46: 0xf041 0x7180 ORR.W R1, R1, #16777216; 0x1000000 0x8000d4a: 0x6001 STR R1, [R0] AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_1; 0x8000d4c: 0x6801 LDR R1, [R0] 0x8000d4e: 0xf021 0x7100 BIC.W R1, R1, #33554432; 0x2000000 0x8000d52: 0x6001 STR R1, [R0] AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_2; 0x8000d54: 0x6801 LDR R1, [R0] 0x8000d56: 0xf021 0x6180 BIC.W R1, R1, #67108864; 0x4000000 0x8000d5a: 0xe127 B.N ??McuPioRemap_3; 0x8000fac
...
??McuPioRemap_3: 0x8000fac: 0x6001 STR R1, [R0] } Когда дохожу до строки 0x8000d4a: 0x6001 STR R1, [R0]в регистрах вижу корректные значения, в R1 значение 0x01000001, а в R0 адрес AFIO->MAPR ( 0x40010004 ). Сразу после исполнения STR R1, [R0] в AFIO->MAPR вижу уже 0x02000001, вместо 0x01000001. Ну и на следующей инструкции, конечно, считывается как 0x02000001. Ну как-же так, доктор? Причем каждый из трех бит SWJ_CFG так же аккуратно сдвигается на единицу влево. А вот младшая 1, это remap SPI1, который был сделан ранее, причем этой же функцией. И ведь все корректно!
P.S. В еррате ничего похожего не нашел.
Сообщение отредактировал IgorKossak - Jul 20 2012, 07:11
Причина редактирования: [codebox] для длинного кода!!!
|
|
|
|
|
 |
Ответов
|
Jul 20 2012, 07:18
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(scifi @ Jul 20 2012, 10:55)  Вы уже сами написали, что работа с AFIO_MAPR у вас ведётся некорректно. Какой смысл разбираться дальше? Делайте как положено: AFIO_MAPR = (AFIO_MAPR & 0xF8FFFFFF) | new_val. Угу. Хотя это не лучший выход. Правда маска в стандартной библиотеке 0xF0FFFFFF, а не 0xF8FFFFFF, как в доке. Думаю, что не случайно, особенно в свете поведения AFIO_MAPR при записи ( я про сдвиг на один бит влево в группе SWJ_CFG ). Цитата(scifi @ Jul 20 2012, 11:12)  Только не берите пример с этой библиотеки. Качество кода там оставляет желать лучшего, мягко говоря. Первоисточник - это Reference Manual. Конечно. Потому и приходится, к сожалению, изобретать велосипед - писать своё. По мере надобности дописываю нужные куски.
|
|
|
|
|
Jul 20 2012, 07:43
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(scifi @ Jul 20 2012, 11:22)  Первоисточник - Reference Manual, остальное - от лукавого. В целом - да. Но в данном случае, судя по всему, не корректен имено Reference Manual. Вот это: Цитата 000: Full SWJ (JTAG-DP + SW-DP): Reset State не соотвествует действительности. Как я писал ранее: Цитата 2. Если поменять местами вызовы функций, т.е. сделать вот так: McuPioRemap( MCU_PIO_REMAP_SWJ_CFG_FULL_WITHOUT_NJTRST ); McuPioRemap( MCU_PIO_REMAP_SPI1_ENABLE ); то все чудесным образом начинает работать. И SPI пероиферию инициализирует, и отладчик не отваливается... Т.е. сначала я отключаю JTAG, а потом ( если верить мануалу ), записывая 0x00000001, тем самым записываю и 000 в SWJ_CFG. А стало быть, снова включаю JTAG, то бишь отключаю SPI1. Однако ж SPI1 остается "живее всех живых"(с), потому что продлолжает спокойно работать с периферией. И еще, насчет мануала. Ничего не имею против поведения NSS в SPI, как его организовали ST. Сначала огорчился, но потом пришел к выводу, что ничего фатального в этом нет: для single операций скорость все равно не критична, а для DMA, как правило, все равно приходится использовать прерывание об окончании трансфера, так что одно обращение к пину в нем особо погоды не делает. Но мало того, что они криво описали поведение NSS ( написанное в мануале расходилось с реальным поведенпием пина ), так ещё и не хотели сознаваться, что у них свой, особенный взгляд на NSS в SPI.
|
|
|
|
|
Jul 20 2012, 07:47
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Tahoe @ Jul 20 2012, 11:43)  не соотвествует действительности. Не верю. Цитата(Tahoe @ Jul 20 2012, 11:43)  Т.е. сначала я отключаю JTAG, а потом ( если верить мануалу ), записывая 0x00000001, тем самым записываю и 000 в SWJ_CFG. Это вы так думаете. В связи с тем, что работа с регистром у вас сделана некорректно, на самом деле может происходить что-то совсем иное. Дальше разбираться лень, да и пользы от этого не будет.
|
|
|
|
|
Jul 20 2012, 08:28
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(scifi @ Jul 20 2012, 11:47)  В связи с тем, что работа с регистром у вас сделана некорректно Да что ж тут может быть не корректного?  По сути, речь про одну строчку: Код AFIO->MAPR = 0x00000001; CODE //////////////////////////////////////////////////////////////////////////////// void McuPioRemap( MCU_PIO_REMAP Remap ) { uint32_t Temp = AFIO->MAPR & 0xF0FFFFFF;
switch( Remap ) { case MCU_PIO_REMAP_SWJ_CFG_FULL: Temp &= ~AFIO_MAPR_SWJ_CFG; break;
case MCU_PIO_REMAP_SWJ_CFG_FULL_WITHOUT_NJTRST: Temp &= ~AFIO_MAPR_SWJ_CFG; Temp |= AFIO_MAPR_SWJ_CFG_0; break;
case MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_EN: Temp &= ~AFIO_MAPR_SWJ_CFG; Temp |= AFIO_MAPR_SWJ_CFG_1; break;
case MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_DIS: Temp &= ~AFIO_MAPR_SWJ_CFG; Temp |= AFIO_MAPR_SWJ_CFG_2; break; ...
case MCU_PIO_REMAP_I2C1_DISABLE: Temp &= ~AFIO_MAPR_I2C1_REMAP; break;
case MCU_PIO_REMAP_I2C1_ENABLE: Temp |= AFIO_MAPR_I2C1_REMAP; break;
case MCU_PIO_REMAP_SPI1_DISABLE: Temp &= ~AFIO_MAPR_SPI1_REMAP; break;
case MCU_PIO_REMAP_SPI1_ENABLE: Temp |= AFIO_MAPR_SPI1_REMAP; break;
default: break; }
AFIO->MAPR = Temp; } Хотя неоднозначность заложена в самом мануале. Он должен описать поведение PB3, PB4, которые используются и JTAG, и SPI. При этом значение 0x00000001 для MAPR допустимо. Оно одновременно должно включать как SPI1 remap, так и JTAG-DP. Учитывая, что в том же мануале, основная функция PB3 это как раз JTDO, да и приоритеты явно не указаны, логично ожидать, что PB3 не будет функционировать как SPI1_SCK, а будет исполнять свою основную функцию JTDO. Ладно, забудем.  Сейчас проверил окончательный вариант. Пока не передернул питание, состояние SWJ_CFG не менялось. А вот когда питание передернул, доступ к периферии уже отсутствовал. В общем вывод остается прежним - remap JTAG делать в самую последнюю очередь. А в библиотеках от ST просто в наглую подставляется константа. И совсем не факт, что она совпадет с тем, как ранее настроил программер.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|