/// <summary> /// Обработка запросов на запись /// </summary> private void ProceedWriteItems(AbstractChannel channel) { for (int i = 0; i < this.writeItems.Count; i++) { RequestItem item = this.writeItems[i]; // Определяем, сколько можно записать за один запрос int packetSize = channel.GetPacketSize(item.MemoryType); // Разбиваем буфер по запросам и записываем их в контроллер for (int j = 0; j < item.Data.Length; j += packetSize) { int c = Math.Min(packetSize, item.Data.Length - j); byte[] buffer = new byte[c]; Array.Copy(item.Data, j, buffer, 0, c); try { channel.WriteToMemory(item.MemoryType, item.Address + j, buffer); this.WritedRequestsCount++; } catch { this.ErrorWritedRequestsCount++; item.Error = true; } // В случае необходимости, информируем о процессе записи if (item.ProgressChangedCallback != null) { // Устанавливаем параметры для выполнения события object[] Params = new object[4]; Params[0] = item.ProgressChangedCallback; Params[1] = item.Sender; Params[2] = (double)(j + c) / (item.Data.Length); Params[3] = null; // Выплняем Callback в главном потоке this.asyncOp.Post(this.exProgressChangedDelegate, Params); } } if (item.ProceedingCompletedCallback != null) { // Нужно проинформировать элемент о завершении получения данных // Устанавливаем параметры для выполнения события object[] Params = new object[4]; Params[0] = item.ProceedingCompletedCallback; Params[1] = item.Sender; Params[2] = null; Params[3] = item.Error; // Выполняем Callback в главном потоке this.asyncOp.Post(this.exProceedingCompleetedDelegate, Params); } this.writeItems.Remove(item); i--; } }
/// <summary> /// Добавляет новый элемент в запрос, с сохранением сортировки по адресу, /// ДОБАВЛЯТЬ ТОЛЬКО ТАК /// </summary> public void AddItem(RequestItem item) { if (this.Items.Contains(item)) { return; } if (item.MemoryType != this.MemoryType) { throw new Exception("Типы областей памяти должны совпадать"); } int idx = this.Items.BinarySearch(item); if (idx < 0) { idx = ~idx; } this.Items.Insert(idx, item); }
/// <summary> /// Добавляет в очередь опороса отладчика элемент чтения данных данных /// </summary> /// <param name="Address">Адрес области памяти, к которой производится обращение</param> /// <param name="MemoryType">Тип области памяти, которой производится обращение</param> /// <param name="Buffer">Записываемые даные</param> /// <param name="Sender">Опрашиваемый объект</param> /// <param name="ProgressChangedCallback">Callback для получения информации о процессе опроса</param> /// <param name="CompleetingCallback">Callback для порлучения информации о завершении опроса</param> public void AddReadItem(int Address, MemoryType MemoryType, int Count, object Sender, ProceedingProgressChangedDelegate ProgressChangedCallback, ProceedingCompleetedDelegate CompleetingCallback) { RequestItem item = new RequestItem() { Address = Address, Data = new byte[Count], MemoryType = MemoryType, RequestType = RequestType.Read, Sender = Sender, ProgressChangedCallback = ProgressChangedCallback, ProceedingCompletedCallback = CompleetingCallback }; this.lockingMemoryType = MemoryType; this.lockingAddress = Address; this.lockingLength = Count; this.lockingActive = true; this.AddReadItem(item); this.lockingActive = false; }
/// <summary> /// Добавляет в очередь опороса отладчика объект записи данных /// </summary> private void AddReadItem(RequestItem item) { if (this.maxRequestSize == -1) { if (this.Parameters.ProcessorType == ProcessorType.AT89C51ED2) { this.maxRequestSize = 8; } else { // Максимальный размер запроса неизвестен this.readItems.Add(item); return; } } ReadRequest request = new ReadRequest(item.Address, item.MemoryType, item.Size, this.GetRequestMinBytesToRead(), this.GetRequestMaxBytesToRead(item.MemoryType)); request.AddItem(item); // Получаем список запросов, в который надо добавить элемент List <ReadRequest> requests = this.requestsByMemory[item.MemoryType] as List <ReadRequest>; if (requests == null) { requests = new List <ReadRequest>(); this.requestsByMemory.Add(item.MemoryType, requests); } // Получаем индекс запроса, адрес которого больше или равен адресу добавляемого элемента int idx = requests.BinarySearch(request); if (idx < 0) { idx = ~idx; } // Добавляем элемент в очередь запросов if (requests.Count == 0) { requests.Add(request); } else if (idx < requests.Count && requests[idx].Address == item.Address) { // Адрес idx-запроса совпадает с адресом переменной requests[idx].AddItem(item); if (item.EndByteOffset > requests[idx].EndByteOffset) { requests[idx].ChangeBytesToRead(requests[idx].BytesToRead + Math.Min(item.EndByteOffset - requests[idx].EndByteOffset, requests[idx].GrowUpBytesCount)); } } else if (idx == 0) { // Адрес запроса наименьший из всех опрашиваемых requests.Insert(idx, request); } else if (requests[idx - 1].EndByteOffset + Math.Min(7, requests[idx - 1].GrowUpBytesCount) >= item.Address) { // По краеней мере часть элемента опрашивается текущим запросом requests[--idx].AddItem(item); if (item.EndByteOffset > requests[idx].EndByteOffset) { requests[idx].ChangeBytesToRead(requests[idx].BytesToRead + Math.Min(item.EndByteOffset - requests[idx].EndByteOffset, requests[idx].GrowUpBytesCount)); } } else { // Элемент находитя между запросами и не может быт опрошен левым даже частично requests.Insert(idx, request); } // Опрос элемента начинается запросом с индексом idx int c = idx; bool exit = true; do { // Убираем накладывающиеся друг на друга вопросы for (int i = c + 1; i < requests.Count && requests[i].Address <= requests[c].EndByteOffset + 1 + Math.Min(7, requests[c].GrowUpBytesCount); i++) { if (requests[c].Address + requests[c].BytesToRead + requests[c].GrowUpBytesCount - 1 >= requests[i].EndByteOffset) { // Запрос целиком поглощается текущим => элементы переносим в текущий, а сам запрос удаляем из списка requests[c].AddItems(requests[i].Items); // Изменяем размер запроса if (requests[c].GrowUpBytesCount > 0) { requests[c].ChangeBytesToRead(requests[i].EndByteOffset + 1 - requests[c].Address); } requests.RemoveAt(i--); } else { // Запрос накладывается на текущий частично => урезаем или смещаем его, элементы переносим в текущий for (int k = i; k < requests.Count && requests[k - 1].EndByteOffset >= requests[k].Address; k++) { int newAddress = requests[k - 1].Address + requests[k - 1].BytesToRead + requests[k - 1].GrowUpBytesCount; for (int j = 0; j < requests[k].Items.Count && requests[k].Items[j].Address < newAddress; j++) { requests[k - 1].AddItem(requests[k].Items[j]); if (requests[k].Items[j].EndByteOffset < newAddress) { requests[k].Items.RemoveAt(j--); } } if (requests[k].Items.Count == 0) { requests.RemoveAt(k--); } else { requests[k].ChangeAddress(newAddress); } } } } // Вычисляем условие выхода bool ItemCoveredByRequests = (item.EndByteOffset <= requests[c].EndByteOffset); if (!ItemCoveredByRequests) { // Элемент не покрывается запросами c++; if (c >= requests.Count || requests[c].Address > requests[c - 1].EndByteOffset + 1) { // Зпросов больше нет, либо между ними ести "дыра" requests.Insert(c, new ReadRequest(requests[c - 1].EndByteOffset + 1, item.MemoryType, item.EndByteOffset - requests[c - 1].EndByteOffset, this.GetRequestMinBytesToRead(), this.GetRequestMaxBytesToRead(item.MemoryType))); } requests[c].AddItem(item); } exit = ItemCoveredByRequests; }while (!exit); }
/// <summary> /// Удаляет опрашиваемый элемент из очереди запрсов отладчика /// </summary> /// <param name="Address">Адрес удаляемого элемента</param> /// <param name="MemoryType">Тип памяти, с которым работает удаляемый элемент</param> /// <param name="Sender">Идентификатор удаляемого элемента</param> public void RemoveReadItem(int Address, MemoryType MemoryType, object Sender) { // Ищем удаляемый элемент List <ReadRequest> requests = this.requestsByMemory[MemoryType] as List <ReadRequest>; if (requests == null) { List <RequestItem> read_items = this.readItems; if (read_items == null) { return; } //Удаление элемента из списка, если размер считывания не известен RequestItem removed_item = read_items.Find(new Predicate <RequestItem>(x => x.Address == Address && x.Sender.Equals(Sender))); // Элемент не найден if (removed_item == null) { return; } read_items.Remove(removed_item); return; } int idx = requests.BinarySearch(new ReadRequest(Address, MemoryType, 0, 0, 0)); if (idx < 0) { idx = ~idx - 1; } if (idx < 0) { return; } RequestItem RemovedItem = requests[idx].Items.Find(new Predicate <RequestItem>(x => x.Address == Address && x.Sender.Equals(Sender))); if (RemovedItem == null) { // Элемент не найден return; } // Получаем все запросы, в которых используется элемент List <ReadRequest> RequestsWithRemovedItem = requests.FindAll(new Predicate <ReadRequest>(x => (x.EndByteOffset >= RemovedItem.Address && x.EndByteOffset <= RemovedItem.EndByteOffset) || (x.Address >= RemovedItem.Address && x.EndByteOffset >= RemovedItem.EndByteOffset) || (x.Address <= RemovedItem.Address && x.EndByteOffset >= RemovedItem.EndByteOffset))); this.lockingAddress = RequestsWithRemovedItem[0].Address; this.lockingMemoryType = MemoryType; this.lockingLength = RequestsWithRemovedItem[RequestsWithRemovedItem.Count - 1].EndByteOffset + 1 - this.lockingAddress; this.lockingActive = true; // Удаляем эти запросы из списка запросов foreach (ReadRequest request in RequestsWithRemovedItem) { requests.Remove(request); } // Получаем список оставшихся элементов List <RequestItem> items = new List <RequestItem>(); foreach (ReadRequest request in RequestsWithRemovedItem) { foreach (RequestItem item in request.Items) { if (item != RemovedItem && !items.Contains(item)) { items.Add(item); } } } // Добавляем оставшиеся элементы обратно в список запросов foreach (RequestItem item in items) { this.AddReadItem(item); } this.lockingActive = false; }