ARM: JTAG elektrodų atlaisvinimas

Posted: 2015-10-02 in Darbeliai
Žymos:,

Kaip jau buvo pas mane komentaruose minėta, šiais laikais daug ARM devboardų (o ir galutinių „produktų“) naudoja SWD, t.y. dviejų laidų debuginimą/flashinimą. Tai yra gerai dar ir tuo atžvilgiu, kad galima kitus JTAG naudojamus elektrodus atlaisvinti ir panaudoti savo reikmėms.

STM32F103C8T6 procesoriukas užsikrauna su visais JTAG elektrodais nustatytais būten tam — JTAG derinimui. Su šituo susidūriau gamindamas savo laikroduko prototipą ir pabandęs panaudoti kai kuriuos elektrodus mygtukams. Man tie mygtukai neveikė, nors pasiusk 🙂 Ką gi, ateity žadu nedideles plokštes su ARM procesoriuku naudoti savo „produkcinėms“ reikmėms. Plokštės kiek primena dydžiu Arduino Nano, tik kad jose sukasi ARM procesoriukas. Kai atkeliaus iš bičiuliškos Kinijos, jumi irgi parodysiu. Jos turi tik SWD derinimo išvadus taupant vietą, todėl ir JTAG skirtų elektrodų išlaisvinimas yra aktualus.

Taigi, dabar trumpas testukas. Aš jau savo turimus devboardukus su SWD derinti bandžiau, pavyko kuo sklandžiausiai.

Pirmiausia, pasižiūrėjus į schemutę reikia išsiaiškinti, kurie elektrodai yra naudojami JTAG. O naudojami šie: PB3, PB4, PA13, PA14 ir PA15. PA13 ir PA14 yra naudojami SWD, taigi iš viso galime atlaisvinti cielus tris elektrodus savo reikmėms! Liuks.

Praktikoje tas daroma labai paprastai, pora kodo eilučių. Pirmasis dalykas — būtina įjungti AFIO. Po to galima jau pakeisti standartinę elektrodų paskirtį. Štai tos kodo eilutės, kurios išlaisvina tris elektrodus:

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);

Va ir viskas. Juk paprasta, ar ne? O pabaigai — filmukas, kaip sekėsi. Pirmoje dalyje prijungti minėti trys elektrodai. Geltonas šviesos diodas prijungtas prie PB4 ir „pusiau ryškiai“ žiba. Antroje dalyje prijungiau laisvą PA8 elektrodą prie raudono, kad būtų matyti, jog mano mirksenimas veikia. Trečioje dalyje matyti, kaip ant PB3 ir PB4 elektrodų pakabinti žalias ir geltoni diodai mirksi kartu, o raudonas ant PA15 — atskirai nuo jų. Trečioje dalyje JTAG jau pilnai atlaisvintas ir paliktas tik SWD:

Štai tiek trumpai. Pabaigai viso šito bandymo kodas:

#include "stm32f10x.h"

/* Mirksiukų konstantos */
#define BLINK_PORT      GPIOA
#define BLINK_PIN       GPIO_Pin_15

#define BLINK_PORT2     GPIOB
#define BLINK_PIN2      GPIO_Pin_3
#define BLINK_PIN3      GPIO_Pin_4

#define BLINK_RCC_BIT   RCC_APB2Periph_GPIOA
#define BLINK_RCC_BIT2  RCC_APB2Periph_GPIOB

/* Mirksiukų „apvertimo“ kintamasis */
int bit = 0;

/* Sukuriam pertraukimo apdorojimo paprogramę */
void TIM2_IRQHandler()
{
	/* Indikuojam, kad sutvarkėm įvykį ir leidžiam laikmačiui kapsėti toliau */
	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	/* Junginėjam mirksiukus */
	if (bit) {
		GPIO_SetBits(BLINK_PORT, BLINK_PIN);
		GPIO_ResetBits(BLINK_PORT2, BLINK_PIN2);
		GPIO_ResetBits(BLINK_PORT2, BLINK_PIN3);
		bit = 0;
	} else {
		GPIO_ResetBits(BLINK_PORT, BLINK_PIN);
		GPIO_SetBits(BLINK_PORT2, BLINK_PIN2);
		GPIO_SetBits(BLINK_PORT2, BLINK_PIN3);
		bit = 1;
	}
}

int main(void)
{
	/* Šioje vietoje išjungiam JTAG elektrodus, bet paliekam SWD.
	 * Tam būtina įjungti AFIO, kitaip neveiks. */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);

	GPIO_InitTypeDef Init_PortA, Init_PortB;

	/* Įjungiam taktavimą */
	RCC_APB2PeriphClockCmd(BLINK_RCC_BIT | BLINK_RCC_BIT2,  ENABLE);

	/* Diodo elektrodus nustatom į push/pull režimą */
	Init_PortA.GPIO_Pin = BLINK_PIN;
	Init_PortA.GPIO_Speed = GPIO_Speed_50MHz;
	Init_PortA.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(BLINK_PORT, &Init_PortA);

	Init_PortB.GPIO_Pin = BLINK_PIN2 | BLINK_PIN3;
	Init_PortB.GPIO_Speed = GPIO_Speed_50MHz;
	Init_PortB.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(BLINK_PORT2, &Init_PortB);


	/* Įjungiam laikmačio taktavimą */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

	TIM_TimeBaseInitTypeDef timerInitStructure;
	/* Nustatom laikmatį atnaujinti skaitliuką kas milisekundę */
	timerInitStructure.TIM_Prescaler = 40000;
	timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	timerInitStructure.TIM_Period = 500;
	timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	timerInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &timerInitStructure);
	TIM_Cmd(TIM2, ENABLE);

	/* Įjungiam TIM_IT_Update įvykio generavimą */
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

	/* Konfigūruojam laikmačio petraukimo vektorių */
	NVIC_InitTypeDef nvicStructure;
	nvicStructure.NVIC_IRQChannel = TIM2_IRQn;
	nvicStructure.NVIC_IRQChannelPreemptionPriority = 0;
	nvicStructure.NVIC_IRQChannelSubPriority = 1;
	nvicStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&nvicStructure);

	while (1) {}

	return 0;
}
Advertisements
Komentarai
  1. dmb220 parašė:

    dar karta isgelbejo mane tavo straipsnis, pasidariau pcb, pasijungiau led matrix neveikia, pora pavalandu ieskojau kur blogai kojas nurodau, o pasirodo , uzsiroves buvau ant uzrakintu koju JTAG. gerai kad atsiminiau kad buvau skaites pas taves apie tai, tai tik pora koda eiluciu nusikopijavau iskart viskas pradejo veikti

Parašykite komentarą

Įveskite savo duomenis žemiau arba prisijunkite per socialinį tinklą:

WordPress.com Logo

Jūs komentuojate naudodamiesi savo WordPress.com paskyra. Atsijungti / Keisti )

Twitter picture

Jūs komentuojate naudodamiesi savo Twitter paskyra. Atsijungti / Keisti )

Facebook photo

Jūs komentuojate naudodamiesi savo Facebook paskyra. Atsijungti / Keisti )

Google+ photo

Jūs komentuojate naudodamiesi savo Google+ paskyra. Atsijungti / Keisti )

Connecting to %s